From 01bda62ce2e8f280ffc9878b10d9d7979758c5eb Mon Sep 17 00:00:00 2001 From: fairlight <31534717+fairlighteth@users.noreply.github.com> Date: Fri, 8 Sep 2023 17:53:54 +0100 Subject: [PATCH 01/36] Permit styles tag 1 (#3083) * feat: add permit tag token selector * feat: add permit tag token selector * feat: optimize * Permit styles [Modal/Stepper/IconSpinner] (#3097) * feat: updates * feat: updates * feat: updates * feat: updates * feat: updates * feat: fix box shadow var * feat: optimize * feat: optimize IconSpinner (#3099) * feat: optimize IconSpinner * feat: optimize * feat: add ENUM * feat: add ENUM (#3110) * feat: updates * feat: updates * feat: updates * feat: updates * feat: updates * feat: fix box shadow var * feat: optimize * feat: optimize IconSpinner (#3099) * feat: optimize IconSpinner * feat: optimize * feat: add ENUM * feat: add ENUM * feat: add ENUM * feat: add ENUM usage * feat: add ENUM usage * feat: add ENUM usage * fix: restore yarn.lock to version matching parent branch * fix: reverted package.json changes as well * chore: restore once again yarn.lock * feat: add ENUM usage * feat: add ENUM usage --------- Co-authored-by: Alfetopito * feat: updates --------- Co-authored-by: Alfetopito --- .../src/assets/icon/arrow.svg | 1 + .../src/assets/icon/check.svg | 1 + .../src/assets/icon/gas-free.svg | 1 + apps/cowswap-frontend/src/assets/icon/x.svg | 1 + .../src/common/constants/cosmos.ts | 11 ++ .../src/common/constants/theme.ts | 64 ++++++ .../src/common/pure/ButtonSecondary/index.tsx | 8 +- .../RequestCancellationModal.tsx | 3 +- .../ConfirmationModal/ConfirmationModal.tsx | 5 +- .../ConfirmationModalHeader.tsx | 6 +- .../ConfirmationPendingContent/styled.tsx | 16 +- .../pure/ConfirmedButton/ConfirmedButton.tsx | 4 +- .../pure/CurrencyArrowSeparator/styled.tsx | 6 +- .../pure/CurrencyInputPanel/index.cosmos.tsx | 5 +- .../common/pure/CurrencyInputPanel/styled.tsx | 5 +- .../src/common/pure/CurrencyLogo/index.tsx | 2 +- .../src/common/pure/ExpertModeModal/index.tsx | 11 +- .../src/common/pure/FiatValue/index.tsx | 3 +- .../common/pure/IconSpinner/index.cosmos.tsx | 47 +++++ .../src/common/pure/IconSpinner/index.tsx | 91 +++++++++ .../src/common/pure/Modal/index.cosmos.tsx | 99 ++++++++++ .../src/common/pure/Modal/index.tsx | 186 +++++++++++++++++- .../src/common/pure/Modal/styled.tsx | 6 +- .../src/common/pure/NetworksList/styled.tsx | 4 +- .../RateTooltipHeader.tsx | 4 +- .../src/common/pure/RateInfo/index.tsx | 5 +- .../src/common/pure/SelectDropdown/index.tsx | 18 +- .../src/common/pure/Stepper/index.cosmos.tsx | 62 ++++++ .../src/common/pure/Stepper/index.tsx | 138 +++++++++++++ .../TransactionErrorContent/index.cosmos.tsx | 4 +- .../SurplusModal.tsx | 5 +- .../TransactionSubmittedContent/styled.tsx | 4 +- .../cowswap-frontend/src/cosmos.decorator.tsx | 3 +- .../legacy/assets/images/arrow-down-grey.svg | 11 +- .../src/legacy/assets/styles/styled.ts | 4 +- .../components/AddressInputPanel/index.tsx | 7 +- .../legacy/components/Button/ButtonMod.tsx | 10 +- .../src/legacy/components/Button/index.tsx | 10 +- .../src/legacy/components/Card/index.tsx | 4 +- .../src/legacy/components/Copy/CopyMod.tsx | 5 +- .../components/CowBalanceButton/index.tsx | 3 +- .../CowSubsidyModal/SubsidyTable.tsx | 7 +- .../ErrorBoundary/ErrorWithStackTrace.tsx | 6 +- .../components/FlashingLoading/index.tsx | 6 +- .../Header/MobileMenuIcon/index.tsx | 4 +- .../Header/NetworkSelector/index.tsx | 7 +- .../src/legacy/components/Header/Polling.tsx | 9 +- .../src/legacy/components/Header/styled.tsx | 34 ++-- .../src/legacy/components/InfoIcon/index.tsx | 4 +- .../src/legacy/components/ListLogo/index.tsx | 3 +- .../components/{ => Loader}/Logo/index.tsx | 2 +- .../legacy/components/MenuDropdown/styled.ts | 10 +- .../components/NetworkAlert/NetworkAlert.tsx | 12 +- .../legacy/components/NetworkAlert/styles.ts | 4 +- .../components/NumericalInput/index.tsx | 3 +- .../components/OrderProgressBar/styled.ts | 10 +- .../legacy/components/Popover/PopoverMod.tsx | 9 +- .../src/legacy/components/Popups/styled.ts | 4 +- .../QuestionHelper/QuestionHelperMod.tsx | 2 +- .../components/QuestionHelper/index.tsx | 4 +- .../CurrencyList/CurrencyListMod.tsx | 16 +- .../SearchModal/CurrencyList/index.tsx | 169 ++++++---------- .../SearchModal/CurrencyList/styled.ts | 80 +++++++- .../CurrencySearch/CurrencySearchMod.tsx | 3 +- .../SearchModal/CurrencySearch/index.tsx | 8 +- .../SearchModal/ImportRow/index.tsx | 6 +- .../SearchModal/ImportToken/index.tsx | 3 +- .../components/SearchModal/Manage/index.tsx | 6 +- .../ManageLists/ManageListsMod.tsx | 3 +- .../SearchModal/ManageLists/index.tsx | 14 +- .../SearchModal/ManageTokens/index.tsx | 6 +- .../legacy/components/SearchModal/styleds.tsx | 6 +- .../components/Settings/SettingsMod.tsx | 3 +- .../src/legacy/components/Settings/index.tsx | 12 +- .../src/legacy/components/SideMenu/index.tsx | 4 +- .../src/legacy/components/Stepper/index.tsx | 4 +- .../legacy/components/SwapWarnings/index.tsx | 4 +- .../src/legacy/components/Toggle/index.tsx | 4 +- .../Tokens/FavouriteTokenButton.tsx | 4 +- .../src/legacy/components/Tokens/styled.ts | 27 +-- .../TransactionConfirmationModal/styled.ts | 16 +- .../TransactionSettingsMod.tsx | 9 +- .../components/TransactionSettings/index.tsx | 12 +- .../src/legacy/components/Version/index.tsx | 4 +- .../swap/SwapHeader/SwapHeaderMod.tsx | 4 +- .../components/swap/SwapModalFooter/index.tsx | 4 +- .../components/swap/SwapModalHeader/index.tsx | 6 +- .../UnsupportedCurrencyFooterMod.tsx | 3 +- .../src/legacy/components/swap/styleds.tsx | 6 +- .../legacy/state/lists/wrappedTokenInfo.ts | 1 + .../src/legacy/theme/baseTheme.tsx | 115 +++++++---- .../src/legacy/theme/components.tsx | 4 +- .../containers/AccountDetails/SurplusCard.tsx | 4 +- .../containers/AccountDetails/styled.ts | 36 ++-- .../account/containers/OrdersPanel/index.tsx | 11 +- .../account/containers/Transaction/styled.ts | 13 +- .../containers/TradeWidgetLinks/styled.ts | 26 +-- .../modules/application/pure/Page/index.tsx | 6 +- .../modules/application/pure/Widget/index.tsx | 4 +- .../containers/FortuneWidget/index.tsx | 15 +- .../containers/RateInput/styled.ts | 16 +- .../pure/DeadlineSelector/styled.tsx | 20 +- .../pure/ExecutionPriceTooltip/styled.ts | 4 +- .../limitOrders/pure/InfoBanner/styled.ts | 4 +- .../pure/LimitOrdersDetails/index.tsx | 5 +- .../pure/LimitOrdersDetails/styled.tsx | 3 +- .../limitOrders/pure/OrderType/styled.tsx | 10 +- .../pure/RateImpactIndicator/index.tsx | 5 +- .../pure/RateImpactWarning/index.tsx | 3 +- .../limitOrders/pure/Settings/styled.ts | 10 +- .../MultipleCancellationMenu/index.tsx | 3 +- .../OrderRow/OrderContextMenu.tsx | 6 +- .../OrdersTableContainer/OrderRow/styled.tsx | 3 +- .../pure/OrdersTableContainer/OrdersTable.tsx | 3 +- .../OrdersTablePagination.tsx | 8 +- .../pure/OrdersTableContainer/OrdersTabs.tsx | 8 +- .../pure/OrdersTableContainer/styled.tsx | 5 +- .../ordersTable/pure/ReceiptModal/styled.ts | 10 +- .../swap/containers/FeesDiscount/index.tsx | 6 +- .../pure/EthFlow/EthFlowBanner/styleds.ts | 6 +- .../EthFlowModalTopContent.tsx | 4 +- .../pure/EthFlow/EthFlowStepper/index.tsx | 6 +- .../EthFlow/EthFlowStepper/steps/Step3.tsx | 4 +- .../pure/EthFlow/WrappingPreview/styled.tsx | 12 +- .../swap/pure/ReceiveAmount/styled.tsx | 4 +- .../src/modules/swap/pure/Row/styled.ts | 8 +- .../modules/swap/pure/TradeRates/styled.tsx | 9 +- .../src/modules/swap/pure/styled.tsx | 6 +- .../trade/containers/TradeWidget/styled.tsx | 4 +- .../trade/pure/ConfirmDetailsItem/styled.ts | 4 +- .../src/modules/trade/pure/Settings/styled.ts | 12 +- .../trade/pure/TradeConfirmation/styled.tsx | 4 +- .../trade/pure/TradeNumberInput/styled.tsx | 4 +- .../modules/trade/pure/TradeSelect/index.tsx | 8 +- .../modules/trade/pure/TradeTextBox/index.tsx | 4 +- .../trade/pure/UnlockWidgetScreen/styled.ts | 4 +- .../pure/TradeFormBlankButton/index.tsx | 4 +- .../containers/TwapFormWidget/tooltips.tsx | 4 +- .../pure/CustomDeadlineSelector/styled.tsx | 8 +- .../wallet/api/pure/AddToMetamask/index.tsx | 3 +- .../api/pure/ConnectWalletOption/index.tsx | 4 +- .../wallet/api/pure/Identicon/index.tsx | 4 +- .../wallet/api/pure/WalletModal/styled.tsx | 8 +- .../wallet/api/pure/Web3StatusInner/styled.ts | 12 +- .../wallet/api/pure/ZengoBanner/styled.ts | 6 +- .../AccountSelectorModal/styled.tsx | 4 +- .../pure/AccountIndexSelect/index.cosmos.tsx | 4 +- .../pure/AccountIndexSelect/styled.tsx | 3 +- .../src/pages/Account/Tokens/styled.ts | 9 +- .../src/pages/Account/styled.tsx | 35 ++-- .../src/pages/Claim/styled.ts | 56 +++--- .../src/pages/CookiePolicy/index.tsx | 6 +- .../cowswap-frontend/src/pages/Faq/styled.tsx | 8 +- apps/cowswap-frontend/yarn.lock | 4 + 154 files changed, 1548 insertions(+), 573 deletions(-) create mode 100644 apps/cowswap-frontend/src/assets/icon/arrow.svg create mode 100644 apps/cowswap-frontend/src/assets/icon/check.svg create mode 100644 apps/cowswap-frontend/src/assets/icon/gas-free.svg create mode 100644 apps/cowswap-frontend/src/assets/icon/x.svg create mode 100644 apps/cowswap-frontend/src/common/constants/cosmos.ts create mode 100644 apps/cowswap-frontend/src/common/constants/theme.ts create mode 100644 apps/cowswap-frontend/src/common/pure/IconSpinner/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/common/pure/IconSpinner/index.tsx create mode 100644 apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/common/pure/Stepper/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/common/pure/Stepper/index.tsx rename apps/cowswap-frontend/src/legacy/components/{ => Loader}/Logo/index.tsx (95%) create mode 100644 apps/cowswap-frontend/yarn.lock diff --git a/apps/cowswap-frontend/src/assets/icon/arrow.svg b/apps/cowswap-frontend/src/assets/icon/arrow.svg new file mode 100644 index 0000000000..4875d9d873 --- /dev/null +++ b/apps/cowswap-frontend/src/assets/icon/arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/cowswap-frontend/src/assets/icon/check.svg b/apps/cowswap-frontend/src/assets/icon/check.svg new file mode 100644 index 0000000000..67ed5ae733 --- /dev/null +++ b/apps/cowswap-frontend/src/assets/icon/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/cowswap-frontend/src/assets/icon/gas-free.svg b/apps/cowswap-frontend/src/assets/icon/gas-free.svg new file mode 100644 index 0000000000..96b8d2d0c0 --- /dev/null +++ b/apps/cowswap-frontend/src/assets/icon/gas-free.svg @@ -0,0 +1 @@ + diff --git a/apps/cowswap-frontend/src/assets/icon/x.svg b/apps/cowswap-frontend/src/assets/icon/x.svg new file mode 100644 index 0000000000..1345e9bcea --- /dev/null +++ b/apps/cowswap-frontend/src/assets/icon/x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/cowswap-frontend/src/common/constants/cosmos.ts b/apps/cowswap-frontend/src/common/constants/cosmos.ts new file mode 100644 index 0000000000..a933e516b3 --- /dev/null +++ b/apps/cowswap-frontend/src/common/constants/cosmos.ts @@ -0,0 +1,11 @@ +import { Token } from '@uniswap/sdk-core' + +export const MOCK_TOKEN = new Token( + 1, + '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', + 18, + 'AAVE', + 'Aave Token' +) + +export const IMAGE_ACCOUNT = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE8AAABOCAYAAABhaEsjAAAKCklEQVR42t2c+1dTVxbH+RP8fbTG+qitj6KooCi9dmYBYoQICDhAiLxVHhEXRIiQy0NeARKMgiht0GFkarWxavE5pDLOOFO1sZ2qIwEODyEPjVf9B/YcqcujS5B7yb3JjWet72/8QD7r7LP3/p59rp+3ltKIZmVrTVSgXJW/MiHXKIlQmJZt24kWRqahBVvSYF6EAiQRKTBfugMWRqUzS2J2ojnhyeaAtCLTKpWWjmlol2W3miR+H/oiwEYpacO4fpPWYQmtc0AwPQpr1A8hoOhn8Ff+CMt3nYMlGZ2wWN4CC+Iq4aMtuTA7XAF/CE2a0BwMdEVBNQTs004osKQRgkt16Av6oHHDfoPMYkGzPihg6i4bFdk0ro/SOZjgCies46i19BgEqvsgoPAW+O85+BLalMIgIXBfozFIraV8GlqSwUbF6J3m0HoCwh0Flt0goFgoRNOMQsoOpfhYaNqosDqneX2lw21gZPdZIaD4EIHDTSi4rFncEOkumyTxsNNMQpMncOV2WK3uJDBmqNXFWhRZ1y4+iLKm8fyN1Q6GP2hEa0qvEAj8yKgymiSi2G3SRrt5XYUDhAAXRP+Cf2wDf+CIUGhli8xr4BIMo1SE1kZ2G+/hOgKrStoEAEfKnKCSBo3HwVWdcWg21ZPdJki47r8gCLR3yxu9kVLqPFMfZh4b0wRXOgUFF6i57RFwJJk0WGijWViAijabJqRK2B23lh6AVcWkGPaU1u3XWfyF2oG7jDaNUMCIbLgs+ZuHwRGtxQCNJp53IP2tTfNljQOEyqqkLLlGsquXtLH8kJk3cAidwA13CfT8sxgu9ZbBuZ5KOH21Bk5eboDj3c3Qfr4FDp9tB92ZDqj/thOquk6B5q/fQfGJH6Dg68uQe6wHdrb1QlrrTUg23IZ4/S8ga7wP0vo+CKtF8GX1CIRUjcO68gf4n9d5B9q7PbLObXAPEC1xDKSgF0ObQSgxaAuMPIiF2PoK74MjCQRwHeheNzI+WE7ACaiqTqVIwBFhz5DxV+lm1omMojbN8yGp4OCeY126Loc/0sSnE9EO5H7+2ZBJ8nQojR0AntT/WzTkHVGJDuAGtU7JCR4zXmP2HDgihzUSjl/IhI2aavGEb3EDw7oDeeI0K14MRfMIhbvu3Y2FPzdqRAMwUN3ILvvah5tIkvCiniEpVOJEslZdJ4rsG063vj95PHp0RcGgKAGhcNe13mQIrajyOsCNdLP+vfAeDx0gZ52INPI/GZR2FHg7dBmKnuLs6+u74e8iGVZ0un17FwSW/Qsf4AavAaToZnry8mSkvYPUdeLTzZ/2vDJJ+2F1yXEvwTuIJk8UaC9JFCLU9ZtFxEQot2Oz9DIEFHu+F07QGam3uwnbKOVC8SBmeFdvqCe547hHrHoPKaRM93biGB44qhcnNKLu65rJrazycewBnvGYlbWhTP926DqG1Baxwzvbc+A9XqADgjS3cDI57AHDtAleO86IYWY9RkoQO7xTV+tY3LgNeMSJTj54QvHqvLNST1Gc6OF1Xmpi6UiPYUe6B/9IvZD3HfrfzzvUrXyGtogenrHbwPEi6SGsKBQmG6/Zpz07AW9k0NAhXmhEbedbud2JlDtAEqmET1OLYGVRPb/nnroJTcBzItrsC/AOnf2K287TPII5mzMnhiLnxWTDir3V/NlUWK/g7bX4ArzG0ye43cSp+2F22BtTpZt3wGcZJRCg4mcX1pguSvycQyWML8Cr/aaLE7zVql8xtOTX8LAwzGRYmJiPz8Jat+Ftqz/q7/d4uBh8AV5F1xlO8FYW3HgJbFJ9JE2F5XkVbva5BgrbUIU+Aa+08ywneMtzu6eAR3bh4jQVrCiamdm6Xq3zHXiq492c4C3J7CKw3iPJ1iw8KH5gpvD2+QS8gq+vcIK3WHGUQJpGszelwGeZJRzDFsNzIiXyBXg5x8yc4C1MqCWA2AiH8fyEXFzS1LCCl/TSmnIMa3wCXuaRG5zgSbYWEjAcNDcyHZbuKmNXqthQueiL5OdYipb/cJmgx6GYNgN4JJkskhfgzqRuqrtc+L23HWzpED08JIVEwx0Oo2oDBIYbkkSlw+fKqkkfyEzAG0AXsDEg1rsLMkkVp/+VNbxVRRY+4JGSJlVFOpM3Z1jQ6C2KQdtFDc81EAVbm+6zhrdC2UsA8KT5cTmvS5qQsld3uAw2Q13De0QNz2GNgciGh6zhfZ7TzSs40pnsgCVZagirOhJFbHhUImpzYOxhPETU97MvkDNO8gyOaB5u7ZS6VskbF0Ator4AQvcTIbwOsYb3SUqrcPA2Kyxvzx1jK96FYkUL7+F/d8CfaobZF8jb6wSDt1CWoX93TmVEI1pr6re7GXjwe5Slg2yHj2NLeYZGMm9OTSv17hhtf73+uUhLlp/v7IYvqsbYPfYrG8ZdglIQeMtisicft0A2C+UayhIlvH//lA8bKu0sHeQ+mB2eKky2DZdPPSFvF+mIWe/NQghm+XJ8VeEd4iDzqKWxOyFIoZx6wBFZddQzFCM2eBMPaIIrHCwL5B8F2XVLorON00/CDypFt/su9ZayzrTLdp/jP1w3yfGuU0mmhWdFV6lnIhutPW+uYF8gp3fyDs8/freR/csfVCeq3Xf6Wg17BzmlhWd4iUimpCWs4aGJRyypooF38nIjVweZN/nH7VZyf+1o1dJisarw60rW8D6OUfMYrruQ30yXA6lEYRi0X2hh3V3M3ZLHV5JgOIXru+F7ET8ZzfJ623b4+2Msu4sRmBORyUcxDAHb89z/gM1Iv0HmQilehaf7roN9dxGW4r79HqGg/fhaY8NGr55/9adOsoKHv3TmdnexMj7H5Mf3GrbSNINkXoGHn96zdJAvugVu7qYUi0SmFOYLF6PWQvo58jw8TaeJZYH8l5n7dFHpFp3RRMAJA7AYh7Bnn5QWnzjPzkFOPjQjcJ/IMiwSSiEsOBLCB+inKMlj8PYaL7GCtyChmvutmDStw2S2eAYcKWMMsseDccgT8HLbe9gVyNElXDIqLIhMpf28tdCDbIl9sAAJ7UBnt/2DBTwHzJXuZgVuTrgc+SfkUAJh4X4OugQM49SWmyzmU8bJDPIUmo21SJZuopQcM6rwYayTuAYTO14I8OxUbrjN4pNx1veCWxSVgZbGZov7K7ZPbEaFE+UhPkua+Oa70xfIRXemSAipzDr5XtrPl1Z/30HFk6EsMx+2fnTTvWnh+ef//a3e9NPoLBQk30OTEsQHl+2BQvKoL6/DheLQTF+SS7XWaeEtzfoGZ9AUZk2S0rRAqqD8PrRltbZS9v40/ZPB7RYXigcWWXrib8Jq0aTAXn4IMeSAA60vt+s3KE/LSIfwgS+LhZ41irSUfUCezwxs0z8d3Gp+NhRreYpikGswGhgUhRUJTwa2QmjtMLOx2o6Cy51mqsZpXF/pzE9qGZFRNPIqrP8DVTMveX7cETIAAAAASUVORK5CYII=" diff --git a/apps/cowswap-frontend/src/common/constants/theme.ts b/apps/cowswap-frontend/src/common/constants/theme.ts new file mode 100644 index 0000000000..3fb31faf81 --- /dev/null +++ b/apps/cowswap-frontend/src/common/constants/theme.ts @@ -0,0 +1,64 @@ +export enum UI { + // Colors + COLOR_WHITE = '--cow-color-white', + COLOR_BLUE = '--cow-color-blue', + COLOR_GREY = '--cow-color-grey', + COLOR_LIGHT_BLUE = '--cow-color-lightBlue', + COLOR_LIGHT_BLUE_OPACITY_90 = '--cow-color-lightBlue-opacity-90', + COLOR_LIGHT_BLUE_OPACITY_80 = '--cow-color-lightBlue-opacity-80', + COLOR_YELLOW = '--cow-color-yellow', + COLOR_YELLOW_LIGHT = '--cow-color-yellow-light', + COLOR_GREEN = '--cow-color-green', + COLOR_RED = '--cow-color-red', + + // Elements + COLOR_BORDER = '--cow-color-border', + COLOR_CONTAINER_BG_01 = '--cow-container-bg-01', + COLOR_CONTAINER_BG_02 = '--cow-container-bg-02', + + // Misc + MODAL_BACKDROP = '--cow-modal-backdrop', + BORDER_RADIUS_NORMAL = '--cow-border-radius-normal', + PADDING_NORMAL = '--cow-padding-normal', + BOX_SHADOW_NORMAL = '--cow-box-shadow-normal', + + // Icons + ICON_SIZE_NORMAL = '--cow-icon-size-normal', + ICON_COLOR_NORMAL = '--cow-icon-color-normal', + + // States + COLOR_INFORMATION = '--cow-color-information', + COLOR_INFORMATION_BG = '--cow-color-information-bg', + COLOR_INFORMATION_TEXT = '--cow-color-information-text', + COLOR_ALERT = '--cow-color-alert', + COLOR_ALERT_BG = '--cow-color-alert-bg', + COLOR_ALERT_TEXT = '--cow-color-alert-text', + COLOR_ALERT2 = '--cow-color-alert2', + COLOR_ALERT2_BG = '--cow-color-alert2-bg', + COLOR_ALERT2_TEXT = '--cow-color-alert2-text', + COLOR_SUCCESS = '--cow-color-success', + COLOR_SUCCESS_BG = '--cow-color-success-bg', + COLOR_SUCCESS_TEXT = '--cow-color-success-text', + COLOR_DANGER = '--cow-color-danger', + COLOR_DANGER_BG = '--cow-color-danger-bg', + COLOR_DANGER_TEXT = '--cow-color-danger-text', + + // Text + COLOR_TEXT1 = '--cow-color-text1', + COLOR_TEXT1_INACTIVE = '--cow-color-text1-inactive', + COLOR_TEXT1_OPACITY_25 = '--cow-color-text1-opacity-25', + COLOR_TEXT1_OPACITY_10 = '--cow-color-text1-opacity-10', + COLOR_TEXT2 = '--cow-color-text2', + COLOR_LINK = '--cow-color-link', + COLOR_LINK_OPACITY_10 = '--cow-color-link-opacity-10', + FONT_WEIGHT_NORMAL = '--cow-font-weight-normal', + FONT_WEIGHT_MEDIUM = '--cow-font-weight-medium', + FONT_WEIGHT_BOLD = '--cow-font-weight-bold', + FONT_SIZE_SMALLER = '--cow-font-size-smaller', + FONT_SIZE_SMALL = '--cow-font-size-small', + FONT_SIZE_NORMAL = '--cow-font-size-normal', + FONT_SIZE_MEDIUM = '--cow-font-size-medium', + FONT_SIZE_LARGE = '--cow-font-size-large', + FONT_SIZE_LARGER = '--cow-font-size-larger', + FONT_SIZE_LARGEST = '--cow-font-size-largest', +} diff --git a/apps/cowswap-frontend/src/common/pure/ButtonSecondary/index.tsx b/apps/cowswap-frontend/src/common/pure/ButtonSecondary/index.tsx index e134f59500..b376304a41 100644 --- a/apps/cowswap-frontend/src/common/pure/ButtonSecondary/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/ButtonSecondary/index.tsx @@ -1,8 +1,10 @@ import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const ButtonSecondary = styled.button` - background: var(--cow-color-lightBlue-opacity-90); - color: var(--cow-color-lightBlue); + background: var(${UI.COLOR_LIGHT_BLUE_OPACITY_90}); + color: var(${UI.COLOR_LIGHT_BLUE}); font-size: 12px; font-weight: 600; border: 0; @@ -16,6 +18,6 @@ export const ButtonSecondary = styled.button` white-space: nowrap; &:hover { - background: var(--cow-color-lightBlue-opacity-80); + background: var(${UI.COLOR_LIGHT_BLUE_OPACITY_80}); } ` diff --git a/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx b/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx index 133d38b207..5db6020bcf 100644 --- a/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx +++ b/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx @@ -13,6 +13,7 @@ import { LegacyConfirmationModalContent } from 'legacy/components/TransactionCon import { LinkStyledButton } from 'legacy/theme' import { Routes } from 'common/constants/routes' +import { UI } from 'common/constants/theme' import { CancellationType } from 'common/hooks/useCancelOrder/state' import { TokenAmount } from 'common/pure/TokenAmount' @@ -63,7 +64,7 @@ const CancellationSummary = styled.span` padding: 12px; margin: 0; border-radius: 6px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); line-height: 1.6; ` diff --git a/apps/cowswap-frontend/src/common/pure/ConfirmationModal/ConfirmationModal.tsx b/apps/cowswap-frontend/src/common/pure/ConfirmationModal/ConfirmationModal.tsx index 7a01bf4dc5..3e650d13bb 100644 --- a/apps/cowswap-frontend/src/common/pure/ConfirmationModal/ConfirmationModal.tsx +++ b/apps/cowswap-frontend/src/common/pure/ConfirmationModal/ConfirmationModal.tsx @@ -1,6 +1,7 @@ import { Trans } from '@lingui/macro' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' import { ContentWrapper, Modal } from 'common/pure/Modal' import { ConfirmationModalHeader } from './ConfirmationModalHeader' @@ -10,7 +11,7 @@ import { ConfirmedButton } from '../ConfirmedButton' const ModalContentWrapper = styled(ContentWrapper)` flex: 1; padding: 1.5rem; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); border-radius: 1.5rem; ` @@ -20,7 +21,7 @@ const Description = styled.p` ` const Warning = styled.strong` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ` export interface ConfirmationModalProps { diff --git a/apps/cowswap-frontend/src/common/pure/ConfirmationModal/ConfirmationModalHeader.tsx b/apps/cowswap-frontend/src/common/pure/ConfirmationModal/ConfirmationModalHeader.tsx index 4fca4186c4..f3a21bd1b2 100644 --- a/apps/cowswap-frontend/src/common/pure/ConfirmationModal/ConfirmationModalHeader.tsx +++ b/apps/cowswap-frontend/src/common/pure/ConfirmationModal/ConfirmationModalHeader.tsx @@ -3,6 +3,8 @@ import { ReactNode } from 'react' import { X as CloseIcon } from 'react-feather' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + const Container = styled.header` display: flex; width: 100%; @@ -10,7 +12,7 @@ const Container = styled.header` padding: 0 0 16px; margin: 0 0 24px; border-bottom: 1px solid ${({ theme }) => theme.grey1}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ` const Title = styled.b` @@ -30,7 +32,7 @@ const Close = styled(CloseIcon)` } > line { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/styled.tsx b/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/styled.tsx index e25f01b343..2e725a3030 100644 --- a/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/styled.tsx +++ b/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/styled.tsx @@ -5,6 +5,8 @@ import styled, { css } from 'styled-components/macro' import { RowBetween } from 'legacy/components/Row' import { CloseIcon, ExternalLink } from 'legacy/theme' +import { UI } from 'common/constants/theme' + export const Wrapper = styled.div` width: 100%; padding: 0; @@ -32,7 +34,7 @@ export const Header = styled.div` flex-direction: row; justify-content: space-between; align-items: center; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); position: sticky; top: 0; left: 0; @@ -105,7 +107,7 @@ export const GPModalHeader = styled(RowBetween)` left: 0; width: 100%; padding: 16px 0; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); z-index: 20; ` @@ -144,7 +146,7 @@ export const ButtonCustom = styled.button` border-radius: 16px; min-height: 52px; border: 1px solid ${({ theme }) => theme.border2}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); background: transparent; outline: 0; padding: 8px 16px; @@ -171,7 +173,7 @@ export const UpperSection = styled.div` display: flex; flex-flow: column wrap; padding: 16px 16px 32px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 16px 16px 0 0; ${({ theme }) => theme.mediaWidth.upToSmall` @@ -236,7 +238,7 @@ export const StepsIconWrapper = styled.div` height: 100%; width: 100%; padding: 18px; - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } @keyframes spin { @@ -294,7 +296,7 @@ export const StepsWrapper = styled.div` flex: 1 1 auto; height: 2px; border: 0; - background: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_TEXT1}); margin: auto; position: absolute; width: 100%; @@ -309,7 +311,7 @@ export const StepsWrapper = styled.div` content: ''; height: 4px; width: 100%; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); display: block; margin: 0; animation: Shrink 1s forwards linear; diff --git a/apps/cowswap-frontend/src/common/pure/ConfirmedButton/ConfirmedButton.tsx b/apps/cowswap-frontend/src/common/pure/ConfirmedButton/ConfirmedButton.tsx index 43665d4c35..cd4e60769a 100644 --- a/apps/cowswap-frontend/src/common/pure/ConfirmedButton/ConfirmedButton.tsx +++ b/apps/cowswap-frontend/src/common/pure/ConfirmedButton/ConfirmedButton.tsx @@ -4,6 +4,8 @@ import styled from 'styled-components/macro' import { ButtonError } from 'legacy/components/Button' +import { UI } from 'common/constants/theme' + const Container = styled.div`` const Instruction = styled.p` margin: 0; @@ -17,7 +19,7 @@ const Input = styled.input` padding: 10px; border-radius: 4px; background: ${({ theme }) => theme.bg3}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); outline: none; font-size: 15px; diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/styled.tsx b/apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/styled.tsx index 580d59cca5..edd284c7c9 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/styled.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/styled.tsx @@ -1,6 +1,8 @@ import { ArrowDown } from 'react-feather' import styled, { css } from 'styled-components/macro' +import { UI } from 'common/constants/theme' + import { loadingAnimationMixin } from './style-mixins' export const Box = styled.div<{ withRecipient: boolean; isCollapsed: boolean; hasSeparatorLine?: boolean }>` @@ -42,7 +44,7 @@ export const LoadingWrapper = styled.div<{ isLoading: boolean; border?: boolean transition: transform 0.25s; border: ${({ border, theme }) => (border ? `1px solid ${theme.grey1}` : '0')}; box-shadow: 0px 0px 0px 3px ${({ theme }) => theme.bg1}; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 8px; width: var(--size); margin: auto; @@ -57,7 +59,7 @@ export const LoadingWrapper = styled.div<{ isLoading: boolean; border?: boolean export const ArrowDownIcon = styled(ArrowDown)` display: block; margin: auto; - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); stroke-width: 3px; padding: 0; height: 100%; diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/index.cosmos.tsx index bc90130c79..35211285a6 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/index.cosmos.tsx @@ -27,10 +27,7 @@ function useCustomProps(): Partial { options: [Field.INPUT, Field.OUTPUT], defaultValue: Field.INPUT, }) - const [priceImpactError] = useSelect('priceImpactParams.error', { - options: ['fetch-quote-error', 'insufficient-liquidity', 'fee-exceeds-sell-amount'], - defaultValue: 'fetch-quote-error', - }) + const [priceImpactRaw] = useValue('priceImpactParams.priceImpact', { defaultValue: 2 }) const balance = CurrencyAmount.fromRawAmount(currency, balanceAmountRaw * 10 ** 18) diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/styled.tsx b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/styled.tsx index 461d57261e..b1f0e394a7 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/styled.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/styled.tsx @@ -4,6 +4,7 @@ import styled from 'styled-components/macro' import { loadingOpacityMixin } from 'legacy/components/Loader/styled' import Input from 'legacy/components/NumericalInput' +import { UI } from 'common/constants/theme' import { TokenAmount } from 'common/pure/TokenAmount' export const OuterWrapper = styled.div` @@ -72,7 +73,7 @@ export const NumericalInput = styled(Input)<{ $loading: boolean }>` background: none; font-size: 28px; font-weight: 500; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); &::placeholder { color: ${({ theme }) => transparentize(0.3, theme.text1)}; @@ -88,7 +89,7 @@ export const NumericalInput = styled(Input)<{ $loading: boolean }>` export const TokenAmountStyled = styled(TokenAmount)` font-size: 28px; font-weight: 500; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ${({ theme }) => theme.mediaWidth.upToSmall` font-size: 26px; diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyLogo/index.tsx b/apps/cowswap-frontend/src/common/pure/CurrencyLogo/index.tsx index 55a83b19d6..e4d58c4152 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyLogo/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencyLogo/index.tsx @@ -4,7 +4,7 @@ import { Currency } from '@uniswap/sdk-core' import styled from 'styled-components/macro' -import Logo from 'legacy/components/Logo' +import Logo from 'legacy/components/Loader/Logo' import useCurrencyLogoURIs from './hooks/useCurrencyLogoURIs' diff --git a/apps/cowswap-frontend/src/common/pure/ExpertModeModal/index.tsx b/apps/cowswap-frontend/src/common/pure/ExpertModeModal/index.tsx index 4c122fd84f..9f4bcfca3a 100644 --- a/apps/cowswap-frontend/src/common/pure/ExpertModeModal/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/ExpertModeModal/index.tsx @@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro' import { X } from 'react-feather' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' import { Modal } from 'common/pure/Modal' import { ConfirmedButton } from '../ConfirmedButton' @@ -12,8 +13,8 @@ const ModalContentWrapper = styled.div` align-items: center; justify-content: center; padding: 24px; - color: ${({ theme }) => theme.text2}; - background-color: ${({ theme }) => theme.bg1}; + color: var(${UI.COLOR_TEXT2}); + background-color: var(${UI.COLOR_CONTAINER_BG_01}); border-radius: 24px; > p { @@ -22,7 +23,7 @@ const ModalContentWrapper = styled.div` } > p > strong { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ` @@ -33,7 +34,7 @@ const Header = styled.div` padding: 0 0 16px; margin: 0 0 24px; border-bottom: 1px solid ${({ theme }) => theme.grey1}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); > b { font-size: 21px; @@ -53,7 +54,7 @@ const StyledCloseIcon = styled(X)` } > line { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/common/pure/FiatValue/index.tsx b/apps/cowswap-frontend/src/common/pure/FiatValue/index.tsx index c469e46736..97f0064c87 100644 --- a/apps/cowswap-frontend/src/common/pure/FiatValue/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/FiatValue/index.tsx @@ -5,6 +5,7 @@ import { Nullish } from 'types' import { PriceImpact } from 'legacy/hooks/usePriceImpact' +import { UI } from 'common/constants/theme' import { FiatAmount } from 'common/pure/FiatAmount' import { PriceImpactIndicator } from '../PriceImpactIndicator' @@ -12,7 +13,7 @@ import { PriceImpactIndicator } from '../PriceImpactIndicator' const FiatValueWrapper = styled.div<{ hasValue$: boolean }>` display: inline-block; font-size: 14px; - color: ${({ theme, hasValue$ }) => (hasValue$ ? theme.text1 : theme.text4)}; + color: ${({ theme, hasValue$ }) => (hasValue$ ? `var(${UI.COLOR_TEXT1})` : theme.text4)}; ` export function FiatValue({ diff --git a/apps/cowswap-frontend/src/common/pure/IconSpinner/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/IconSpinner/index.cosmos.tsx new file mode 100644 index 0000000000..12ec959113 --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/IconSpinner/index.cosmos.tsx @@ -0,0 +1,47 @@ +import styled from 'styled-components/macro'; + +import { MOCK_TOKEN, IMAGE_ACCOUNT } from 'common/constants/cosmos'; +import { UI } from 'common/constants/theme' + +import { IconSpinner} from './index'; + +const Wrapper = styled.div` + width: 400px; + height: 400px; + background: var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: var(${UI.BORDER_RADIUS_NORMAL}); + display: flex; + align-items: center; + justify-content: center; + margin: 100px; +`; + +const SpinnerFixtures = { + 'token image / default size': ( + + + + ), + 'token image / custom size': ( + + + + ), + 'token image / custom size + spinnerWidth': ( + + + + ), + 'regular image / custom size': ( + + + + ), + 'no children': ( + + + + ), +}; + +export default SpinnerFixtures; diff --git a/apps/cowswap-frontend/src/common/pure/IconSpinner/index.tsx b/apps/cowswap-frontend/src/common/pure/IconSpinner/index.tsx new file mode 100644 index 0000000000..a9b678d3bb --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/IconSpinner/index.tsx @@ -0,0 +1,91 @@ +import { Currency } from '@uniswap/sdk-core' + +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' +import { CurrencyLogo } from 'common/pure/CurrencyLogo' + +interface IconSpinnerProps { + currency?: Currency | null + image?: string + size?: number + children?: React.ReactNode + bgColor?: UI + spinnerWidth?: number +} + +const Wrapper = styled.div<{ size: number; spinnerWidth: number; bgColor: UI }>` + --bgColor: ${({ bgColor }) => `var(${bgColor})`}; + display: flex; + position: relative; + align-items: center; + justify-content: center; + width: ${({ size }) => size}px; + height: ${({ size }) => size}px; + min-width: ${({ size }) => size}px; + min-height: ${({ size }) => size}px; + border-radius: ${({ size }) => size}px; + + &:before { + content: ""; + position: absolute; + top: calc(-1 * ${({ spinnerWidth }) => spinnerWidth}px); + left: calc(-1 * ${({ spinnerWidth }) => spinnerWidth}px); + width: calc(100% + 2 * ${({ spinnerWidth }) => spinnerWidth}px); + height: calc(100% + 2 * ${({ spinnerWidth }) => spinnerWidth}px); + border-radius: 50%; + background: conic-gradient(from 0deg at 50% 50%, var(${UI.COLOR_BORDER}) 0%, var(${UI.COLOR_LINK}) 100%); + animation: spin 2s linear infinite; + z-index: 1; + } + + > img, + > svg, + > span { + object-fit: contain; + z-index: 2; + position: relative; + border: ${({ spinnerWidth }) => spinnerWidth}px solid var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: ${({ size }) => size}px; + background-color: var(--bgColor); + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + } + + @keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } + } +` + +export function IconSpinner({ + currency, + image, + size = 24, + children, + bgColor = UI.COLOR_CONTAINER_BG_01, + spinnerWidth = 2 +}: IconSpinnerProps) { + + return ( + + {(() => { + if (currency) { + return + } else if (image) { + return Spinning icon + } else if (children) { + return {children} + } + return + })()} + + ) +} diff --git a/apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx new file mode 100644 index 0000000000..3630b46c01 --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx @@ -0,0 +1,99 @@ +import ICON_ARROW from 'assets/icon/arrow.svg' +import SVG from 'react-inlinesvg' +import styled from 'styled-components/macro' + +import { MOCK_TOKEN, IMAGE_ACCOUNT } from 'common/constants/cosmos'; +import { UI } from 'common/constants/theme' +import { IconSpinner } from 'common/pure/IconSpinner' +import { Stepper } from 'common/pure/Stepper' + +import { Modal, CowModal, NewModal, NewModalContentTop, NewModalContentBottom } from './index' + +const Wrapper = styled.div` + width: 100vw; + height: 100vh; +` + +const ArrowRight = styled(SVG)` + --size: 12px; + width: var(--size); + height: var(--size); + margin: auto; + + > path { + fill: var(${UI.COLOR_TEXT2}); + } +` + +const ModalFixtures = { + 'default modal': ( + + console.log("Dismissed")}> + Default modal content here + + + ), + 'modal with minHeight and maxHeight': ( + + console.log("Dismissed")} minHeight={50} maxHeight={80}> + Modal with minHeight and maxHeight + + + ), + 'cow modal': ( + + console.log("Cow Modal Dismissed")} maxWidth={400}> + Cow Modal Content + + + ), + 'cow modal with background color': ( + + console.log("Cow Modal Dismissed")} maxWidth={400} backgroundColor="pink"> + Cow Modal with Pink Background + + + ), + 'new modal + content top/bottom': ( + + + + +

Approve spending AAVE
on CoW Swap

+
+ + +

Sign (gas-free!) in your wallet...

+ +
+
+
+ ), + 'new modal + content top/bottom 2': ( + + + + + +

Confirm Swap

+

10 AAVE 564.7202 DAI

+
+
+ + +

Sign (gas-free!) in your wallet...

+ +
+
+
+ ), + 'new modal + heading title': ( + + + - New Modal - + + + ), +} + +export default ModalFixtures diff --git a/apps/cowswap-frontend/src/common/pure/Modal/index.tsx b/apps/cowswap-frontend/src/common/pure/Modal/index.tsx index b0aec21d42..3e82c46166 100644 --- a/apps/cowswap-frontend/src/common/pure/Modal/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/Modal/index.tsx @@ -2,12 +2,18 @@ import React from 'react' import { useSpringValue, useTransition } from '@react-spring/web' import { useGesture } from '@use-gesture/react' +import CLOSE_ICON from 'assets/icon/x.svg' +import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' import { isMobile } from 'legacy/utils/userAgent' +import { UI } from 'common/constants/theme' + import { CloseIcon, ContentWrapper, HeaderRow, HoverText, StyledDialogContent, StyledDialogOverlay } from './styled' + + export * from './styled' interface ModalProps { @@ -61,9 +67,9 @@ export function Modal({ `translateY(${(y as number) > 0 ? y : 0}px)`) }, - } + ...bind(), + style: { transform: y.interpolate((y) => `translateY(${(y as number) > 0 ? y : 0}px)`) }, + } : {})} aria-label="dialog content" $minHeight={minHeight} @@ -83,14 +89,14 @@ export function Modal({ ) } -export const CowModal = styled(Modal)<{ +export const CowModal = styled(Modal) <{ maxWidth?: number | string backgroundColor?: string border?: string padding?: string }>` > [data-reach-dialog-content] { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); width: 100%; max-width: ${({ maxWidth = 500 }) => `${maxWidth}px`}; border: ${({ border = 'inherit' }) => `${border}`}; @@ -98,7 +104,7 @@ export const CowModal = styled(Modal)<{ padding: ${({ padding = '0px' }) => `${padding}`}; margin: auto; transition: max-width 0.4s ease; - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); overflow: hidden; ${({ theme }) => theme.mediaWidth.upToSmall` @@ -116,7 +122,7 @@ export const CowModal = styled(Modal)<{ left: 0; width: 100%; padding: 16px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); z-index: 20; `} } @@ -141,3 +147,169 @@ export const CowModal = styled(Modal)<{ } } ` + +// New Modal to be used going forward ================================= +const ModalInner = styled.div` + display: flex; + flex-direction: column; + width: 100%; + height: auto; + margin: auto; + background: var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: var(${UI.BORDER_RADIUS_NORMAL}); + box-shadow: var(${UI.BOX_SHADOW_NORMAL}); + padding: 0; + + ${({ theme }) => theme.mediaWidth.upToSmall` + margin: 8vh 0 0; + border-radius: 0; + border-top-left-radius: var(${UI.BORDER_RADIUS_NORMAL}); + border-top-right-radius: var(${UI.BORDER_RADIUS_NORMAL}); + box-shadow: none; + `} +` + +const NewCowModal = styled.div<{ maxWidth?: number | string; minHeight?: number | string }>` + display: flex; + width: 100%; + height: 100%; + margin: auto; + background: var(${UI.MODAL_BACKDROP}); + overflow-y: auto; + + ${ModalInner} { + max-width: ${({ maxWidth }) => maxWidth ? `${maxWidth}px` : '100%'}; + min-height: ${({ minHeight }) => minHeight ? `${minHeight}px` : '100%'}; + + ${({ theme }) => theme.mediaWidth.upToSmall` + max-width: 100%; + min-height: initial; + height: auto; + `} + } +` + +const Heading = styled.h2` + display: flex; + justify-content: space-between; + width: 100%; + height: auto; + padding: 18px; + margin: 0; + font-size: var(${UI.FONT_SIZE_MEDIUM}); + + ${({ theme }) => theme.mediaWidth.upToSmall` + position: sticky; + top: 0; + `} +` + +const IconX = styled.div` + position: fixed; + top: 18px; + right: 18px; + cursor: pointer; + opacity: 0.6; + transition: opacity 0.2s ease-in-out; + margin: 0 0 0 auto; + + > svg { + width: var(${UI.ICON_SIZE_NORMAL}); + height: var(${UI.ICON_SIZE_NORMAL}); + fill: var(${UI.ICON_COLOR_NORMAL}); + } + + &:hover { + opacity: 1; + } +` + +const NewModalContent = styled.div<{ paddingTop?: number}>` + display: flex; + align-items: center; + justify-content: center; + flex-flow: column wrap; + flex: 1; + width: 100%; + height: 100%; + padding: 0 var(${UI.PADDING_NORMAL}) var(${UI.PADDING_NORMAL}); + + h1, + h2, + h3 { + width: 100%; + font-size: var(${UI.FONT_SIZE_LARGER}); + font-weight: var(${UI.FONT_WEIGHT_BOLD}); + text-align: center; + line-height: 1.4; + margin: 0 auto; + } + + p { + font-size: var(${UI.FONT_SIZE_NORMAL}); + font-weight: var(${UI.FONT_WEIGHT_NORMAL}); + color: var(${UI.COLOR_TEXT2}); + margin: 0 auto; + padding: 0; + } +` + +export const NewModalContentTop = styled.div<{ paddingTop?: number }>` + display: flex; + flex-flow: column wrap; + align-items: center; + justify-content: center; + width: 100%; + margin: 0 0 auto; + padding: ${({ paddingTop = 0 }) => `${paddingTop}px`} 0 0; + gap: 24px; + + > span { + gap: 6px; + display: flex; + flex-flow: column wrap; + } + + p { + font-size: var(${UI.FONT_SIZE_MEDIUM}); + } +` + +export const NewModalContentBottom = styled(NewModalContentTop)` + margin: auto 0 0; + + p { + font-size: var(${UI.FONT_SIZE_NORMAL}); + } +` +interface NewModalProps { + maxWidth?: number + minHeight?: number + title?: string + onDismiss?: () => void + children?: React.ReactNode +} + +export function NewModal({ + maxWidth = 450, + minHeight = 450, + title, + children, + onDismiss, +}: NewModalProps) { + + return ( + + + + {title && {title}} + + {children} + + + + onDismiss && onDismiss()}> + + + ) +} diff --git a/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx b/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx index 29ef71105b..486755c464 100644 --- a/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx +++ b/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx @@ -5,6 +5,8 @@ import { animated } from '@react-spring/web' import { transparentize } from 'polished' import styled, { css } from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const HeaderRow = styled.div` ${({ theme }) => theme.flexRowNoWrap}; padding: 1rem 1rem; @@ -27,7 +29,7 @@ export const CloseIcon = styled.div` export const HoverText = styled.div` text-decoration: none; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); display: flex; align-items: center; @@ -38,7 +40,7 @@ export const HoverText = styled.div` export const ContentWrapper = styled.div` /* background-color: ${({ theme }) => theme.bg0}; */ - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); padding: 0 1rem 1rem 1rem; border-bottom-left-radius: 20px; border-bottom-right-radius: 20px; diff --git a/apps/cowswap-frontend/src/common/pure/NetworksList/styled.tsx b/apps/cowswap-frontend/src/common/pure/NetworksList/styled.tsx index 9b85e9d168..e79310176b 100644 --- a/apps/cowswap-frontend/src/common/pure/NetworksList/styled.tsx +++ b/apps/cowswap-frontend/src/common/pure/NetworksList/styled.tsx @@ -2,6 +2,8 @@ import { transparentize } from 'polished' import { ArrowDownCircle } from 'react-feather' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const ActiveRowWrapper = styled.div` background-color: ${({ theme }) => transparentize(0.4, theme.bg4)}; border-radius: 8px; @@ -17,7 +19,7 @@ export const ActiveRowLinkList = styled.div` & > a { align-items: center; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); display: flex; flex-direction: row; font-size: 14px; diff --git a/apps/cowswap-frontend/src/common/pure/OrderExecutionStatusList/RateTooltipHeader.tsx b/apps/cowswap-frontend/src/common/pure/OrderExecutionStatusList/RateTooltipHeader.tsx index bd2ee27daf..6da6a4630e 100644 --- a/apps/cowswap-frontend/src/common/pure/OrderExecutionStatusList/RateTooltipHeader.tsx +++ b/apps/cowswap-frontend/src/common/pure/OrderExecutionStatusList/RateTooltipHeader.tsx @@ -1,5 +1,7 @@ import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + import { OrderExecutionStatusList } from './index' const Content = styled.div` @@ -16,7 +18,7 @@ const Content = styled.div` line-height: 1.5; padding: 0; margin: 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } > h3 { diff --git a/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx b/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx index 9f84c1d116..814085e487 100644 --- a/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx @@ -9,6 +9,7 @@ import { Repeat } from 'react-feather' import styled from 'styled-components/macro' import { Nullish } from 'types' +import { UI } from 'common/constants/theme' import { usePrice } from 'common/hooks/usePrice' import { FiatAmount } from 'common/pure/FiatAmount' import { TokenAmount } from 'common/pure/TokenAmount' @@ -60,7 +61,7 @@ const RateLabel = styled.div` color: ${({ theme }) => transparentize(0.2, theme.text1)}; &:hover { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ` @@ -68,7 +69,7 @@ const InvertIcon = styled.div` --size: 17px; cursor: pointer; background: ${({ theme }) => transparentize(0.9, theme.text1)}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); width: var(--size); height: var(--size); min-width: var(--size); diff --git a/apps/cowswap-frontend/src/common/pure/SelectDropdown/index.tsx b/apps/cowswap-frontend/src/common/pure/SelectDropdown/index.tsx index 4782f378d4..76fe96f85b 100644 --- a/apps/cowswap-frontend/src/common/pure/SelectDropdown/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/SelectDropdown/index.tsx @@ -1,5 +1,7 @@ import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const SelectDropdown = styled.select` border-radius: 12px; padding: 8px 34px 8px 8px; @@ -9,21 +11,21 @@ export const SelectDropdown = styled.select` transition: background 0.2s ease-in-out; width: 100%; outline: none; - border: 1px solid var(--cow-color-border); - color: var(--cow-color-text1); - background: linear-gradient(45deg, transparent 50%, var(--cow-color-lightBlue) 50%) calc(100% - 13px) calc(13px) / 5px + border: 1px solid var(${UI.COLOR_BORDER}); + color: var(${UI.COLOR_TEXT1}); + background: linear-gradient(45deg, transparent 50%, var(${UI.COLOR_LIGHT_BLUE}) 50%) calc(100% - 13px) calc(13px) / 5px 5px no-repeat, - linear-gradient(135deg, var(--cow-color-lightBlue) 50%, transparent 50%) calc(100% - 8px) calc(13px) / 5px 5px + linear-gradient(135deg, var(${UI.COLOR_LIGHT_BLUE}) 50%, transparent 50%) calc(100% - 8px) calc(13px) / 5px 5px no-repeat, - linear-gradient(to right, var(--cow-color-lightBlue-opacity-90), var(--cow-color-lightBlue-opacity-90)) 100% 0 / + linear-gradient(to right, var(${UI.COLOR_LIGHT_BLUE_OPACITY_90}), var(${UI.COLOR_LIGHT_BLUE_OPACITY_90})) 100% 0 / 26px 100% no-repeat; &:hover { - background: linear-gradient(45deg, transparent 50%, var(--cow-color-lightBlue) 50%) calc(100% - 13px) calc(13px) / + background: linear-gradient(45deg, transparent 50%, var(${UI.COLOR_LIGHT_BLUE}) 50%) calc(100% - 13px) calc(13px) / 5px 5px no-repeat, - linear-gradient(135deg, var(--cow-color-lightBlue) 50%, transparent 50%) calc(100% - 8px) calc(13px) / 5px 5px + linear-gradient(135deg, var(${UI.COLOR_LIGHT_BLUE}) 50%, transparent 50%) calc(100% - 8px) calc(13px) / 5px 5px no-repeat, - linear-gradient(to right, var(--cow-color-lightBlue-opacity-80), var(--cow-color-lightBlue-opacity-80)) 100% 0 / + linear-gradient(to right, var(${UI.COLOR_LIGHT_BLUE_OPACITY_80}), var(${UI.COLOR_LIGHT_BLUE_OPACITY_80})) 100% 0 / 26px 100% no-repeat; } ` diff --git a/apps/cowswap-frontend/src/common/pure/Stepper/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/Stepper/index.cosmos.tsx new file mode 100644 index 0000000000..9b62a26e3f --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/Stepper/index.cosmos.tsx @@ -0,0 +1,62 @@ +import styled from 'styled-components/macro'; + +import { UI } from 'common/constants/theme' + +import { Stepper } from './index'; + +const Wrapper = styled.div` + width: 90%; + height: 120px; + background: var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: var(${UI.BORDER_RADIUS_NORMAL}); + display: flex; + align-items: center; + justify-content: center; +`; + +const StepperFixtures = { + 'Stepper start': ( + + + + ), + '2 Stepper with active step': ( + + + + ), + 'Stepper with error state': ( + + + + ), + 'Stepper with loading state': ( + + + + ), +}; + +export default StepperFixtures; diff --git a/apps/cowswap-frontend/src/common/pure/Stepper/index.tsx b/apps/cowswap-frontend/src/common/pure/Stepper/index.tsx new file mode 100644 index 0000000000..f3a9ee9957 --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/Stepper/index.tsx @@ -0,0 +1,138 @@ +import ICON_CHECK from 'assets/icon/check.svg' +import SVG from 'react-inlinesvg' +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' +import { IconSpinner } from 'common/pure/IconSpinner' + +type StepState = 'active' | 'finished' | 'disabled' | 'error' | 'loading' | 'open' + +interface StepProps { + stepState: StepState + stepNumber: number + label: string + dotSize?: number + dotBorderColor?: UI +} + +interface StepStyles { + dotBackground: UI + dotColor: UI + labelColor: UI +} + +const stateStyles: Record = { + active: { dotBackground: UI.COLOR_LINK, dotColor: UI.COLOR_CONTAINER_BG_01, labelColor: UI.COLOR_TEXT1 }, + finished: { dotBackground: UI.COLOR_LINK_OPACITY_10, dotColor: UI.COLOR_LINK, labelColor: UI.COLOR_TEXT1 }, + disabled: { dotBackground: UI.COLOR_TEXT1_OPACITY_25, dotColor: UI.COLOR_TEXT1_OPACITY_25, labelColor: UI.COLOR_TEXT1_OPACITY_25 }, + error: { dotBackground: UI.COLOR_DANGER_BG, dotColor: UI.COLOR_DANGER, labelColor: UI.COLOR_DANGER }, + loading: { dotBackground: UI.COLOR_LINK, dotColor: UI.COLOR_CONTAINER_BG_01, labelColor: UI.COLOR_LINK }, + open: { dotBackground: UI.COLOR_TEXT1_OPACITY_10, dotColor: UI.COLOR_TEXT2, labelColor: UI.COLOR_TEXT2 }, +} + +const Step = styled.div` + display: flex; + position: relative; + align-items: center; + margin: 0; + padding: 0; + font-size: var(${UI.FONT_SIZE_SMALL}); + background: transparent; + color: ${({ stepState }) => `var(${stateStyles[stepState].labelColor})`}; + gap: 8px; + flex: 1 0 auto; + + i { + display: flex; + align-items: center; + justify-content: center; + width: var(--dotSize); + height: var(--dotSize); + max-width: var(--dotSize); + max-height: var(--dotSize); + border-radius: var(--dotSize); + border: 1px solid ${({ dotBorderColor = UI.COLOR_CONTAINER_BG_01 }) => `var(${dotBorderColor})`}; + background: ${({ stepState }) => `var(${stateStyles[stepState].dotBackground})`}; + color: ${({ stepState }) => `var(${stateStyles[stepState].dotColor})`}; + flex: 0 0 auto; + z-index: 1; + position: relative; + font-style: normal; + font-size: inherit; + line-height: 1; + + > svg { + width: 50%; + height: 50%; + margin: auto; + } + + > svg > path { + fill: var(${UI.COLOR_LINK}); + } + } + + > small { + flex: 0 0 auto; + font-size: inherit; + } + + > hr { + width: 100%; + height: 1px; + border: 0; + background: ${({ stepState }) => stepState === 'error' ? `var(${stateStyles['error'].dotBackground})` : stepState === 'finished' ? `var(${stateStyles['finished'].dotBackground})` : `var(${UI.COLOR_TEXT1_OPACITY_25})`}; + border-radius: var(${UI.BORDER_RADIUS_NORMAL}); + } + + &&:last-child { + flex: 0; + } + + &:last-child > hr { + display: none; + } +` + +const Wrapper = styled.div<{ maxWidth?: string; dotSize?: number }>` + --dotSize: ${({ dotSize }) => `${dotSize}px`}; + width: ${({ maxWidth }) => maxWidth ? maxWidth : '100%'}; + display: flex; + align-items: center; + justify-content: space-between; + position: relative; + gap: 10px; + padding: 24px; + margin: 0 auto; +` + +interface StepperProps { + steps: StepProps[] + maxWidth?: string + dotSize?: number +} + +export function Stepper({ steps, maxWidth, dotSize = 21 }: StepperProps) { + return ( + + {steps.map((step, index) => ( + + {step.stepState === 'loading' ? ( + + {step.stepNumber} + + ) : + {step.stepState === 'finished' ? ( + + ) : ( + step.stepNumber + )} + + } + {step.label} +
+
+ ))} +
+ ) +} diff --git a/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.cosmos.tsx index 990d8e3e55..1d221cf1a3 100644 --- a/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.cosmos.tsx @@ -1,11 +1,13 @@ import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + import { TransactionErrorContent } from './index' const Wrapper = styled.div` width: 560px; margin: 0 auto; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); ` const fixtures = { diff --git a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx index 487ecf1fe9..2446e9c6a2 100644 --- a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx +++ b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx @@ -12,6 +12,7 @@ import twitterImage from 'legacy/assets/cow-swap/twitter.svg' import { Order } from 'legacy/state/orders/actions' import { ExternalLink } from 'legacy/theme' +import { UI } from 'common/constants/theme' import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue' import { FiatAmount } from 'common/pure/FiatAmount' import { TokenAmount, SymbolElement } from 'common/pure/TokenAmount' @@ -59,7 +60,7 @@ export const Wrapper = styled.div` --size: 28px; width: var(--size); height: var(--size); - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border-radius: 50%; width: var(--size); height: var(--size); @@ -121,7 +122,7 @@ export const Wrapper = styled.div` width: 70%; margin: 34px auto; padding: 0; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); } ` diff --git a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/styled.tsx b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/styled.tsx index 6e0fedede7..ac318fc56c 100644 --- a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/styled.tsx +++ b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/styled.tsx @@ -2,6 +2,8 @@ import styled from 'styled-components/macro' import { CloseIcon } from 'legacy/theme' +import { UI } from 'common/constants/theme' + export const ButtonCustom = styled.button` display: flex; flex: 1 1 auto; @@ -11,7 +13,7 @@ export const ButtonCustom = styled.button` border-radius: 16px; min-height: 52px; border: 1px solid ${({ theme }) => theme.border2}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); background: transparent; outline: 0; padding: 8px 16px; diff --git a/apps/cowswap-frontend/src/cosmos.decorator.tsx b/apps/cowswap-frontend/src/cosmos.decorator.tsx index 3460702d23..f4afab8001 100644 --- a/apps/cowswap-frontend/src/cosmos.decorator.tsx +++ b/apps/cowswap-frontend/src/cosmos.decorator.tsx @@ -21,6 +21,7 @@ import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from 'legacy/theme import { injectedConnection } from 'modules/wallet/web3-react/connection/injected' +import { UI } from 'common/constants/theme' import { BlockNumberProvider } from 'lib/hooks/useBlockNumber' import { WalletUpdater } from './modules/wallet' @@ -82,7 +83,7 @@ export const DemoContainer = styled.div` display: flex; flex-flow: column wrap; gap: 6px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border: none; border-radius: 16px; box-shadow: ${({ theme }) => theme.boxShadow1}; diff --git a/apps/cowswap-frontend/src/legacy/assets/images/arrow-down-grey.svg b/apps/cowswap-frontend/src/legacy/assets/images/arrow-down-grey.svg index 886808296c..de465dc630 100644 --- a/apps/cowswap-frontend/src/legacy/assets/images/arrow-down-grey.svg +++ b/apps/cowswap-frontend/src/legacy/assets/images/arrow-down-grey.svg @@ -1,3 +1,10 @@ - - + + + + + + + + + diff --git a/apps/cowswap-frontend/src/legacy/assets/styles/styled.ts b/apps/cowswap-frontend/src/legacy/assets/styles/styled.ts index ac5a1d2343..8273f079f6 100644 --- a/apps/cowswap-frontend/src/legacy/assets/styles/styled.ts +++ b/apps/cowswap-frontend/src/legacy/assets/styles/styled.ts @@ -1,5 +1,7 @@ import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + // with font size convert to rems export const Txt = styled.span<{ fontSize?: number @@ -14,6 +16,6 @@ export const Txt = styled.span<{ font-size: ${({ fontSize }) => `${fontSize ? fontSize : 12}px`}; font-weight: ${({ fontWeight }) => (fontWeight ? fontWeight : 'normal')}; line-height: ${({ lineHeight }) => (lineHeight ? `${lineHeight}px` : 1.2)}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); gap: ${({ gap }) => (gap ? `${gap}px` : 0)}; ` diff --git a/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx b/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx index f75bb1abd8..fd885621d9 100644 --- a/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx @@ -11,13 +11,14 @@ import { getBlockExplorerUrl as getExplorerLink } from 'legacy/utils' import { useWalletInfo } from 'modules/wallet' +import { UI } from 'common/constants/theme' import { autofocus } from 'common/utils/autofocus' const InputPanel = styled.div` ${({ theme }) => theme.flexColumnNoWrap} position: relative; border-radius: 16px; - background-color: ${({ theme }) => theme.grey1}; + background-color: var(${UI.COLOR_GREY}); z-index: 1; width: 100%; ` @@ -28,7 +29,7 @@ const ContainerRow = styled.div<{ error: boolean }>` align-items: center; border-radius: 16px; border: 0; - background-color: ${({ theme }) => theme.grey1}; + background-color: var(${UI.COLOR_GREY}); ` export const InputContainer = styled.div` @@ -50,7 +51,7 @@ const Input = styled.input<{ error?: boolean }>` width: 100%; &&::placeholder { - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); } &:focus::placeholder { diff --git a/apps/cowswap-frontend/src/legacy/components/Button/ButtonMod.tsx b/apps/cowswap-frontend/src/legacy/components/Button/ButtonMod.tsx index ea5f8c448a..2d8d4f2559 100644 --- a/apps/cowswap-frontend/src/legacy/components/Button/ButtonMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Button/ButtonMod.tsx @@ -7,6 +7,8 @@ import { RowBetween } from 'legacy/components/Row' import useTheme from 'legacy/hooks/useTheme' import { ButtonSize } from 'legacy/theme/enum' +import { UI } from 'common/constants/theme' + type ButtonProps = Omit export const BaseButton = styled(RebassButton)< @@ -103,7 +105,7 @@ export const ButtonLight = styled(BaseButton)` export const ButtonGray = styled(BaseButton)` background-color: ${({ theme }) => theme.bg3}; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); font-size: 16px; // font-weight: 500; @@ -151,7 +153,7 @@ export const ButtonSecondary = styled(BaseButton)` export const ButtonOutlined = styled(BaseButton)` border: 1px solid ${({ theme }) => theme.bg2}; background-color: transparent; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); &:focus { box-shadow: 0 0 0 1px ${({ theme }) => theme.bg4}; } @@ -234,13 +236,13 @@ export const ButtonText = styled(BaseButton)` export const ButtonConfirmedStyle = styled(BaseButton)` background-color: ${({ theme }) => theme.bg3}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); /* border: 1px solid ${({ theme }) => theme.green1}; */ &:disabled { /* opacity: 50%; */ background-color: ${({ theme }) => theme.bg2}; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); cursor: auto; } ` diff --git a/apps/cowswap-frontend/src/legacy/components/Button/index.tsx b/apps/cowswap-frontend/src/legacy/components/Button/index.tsx index 9749f9bbb0..c9ce823a1e 100644 --- a/apps/cowswap-frontend/src/legacy/components/Button/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Button/index.tsx @@ -9,6 +9,8 @@ import { RowBetween } from 'legacy/components/Row' import useTheme from 'legacy/hooks/useTheme' import { ButtonSize } from 'legacy/theme/enum' +import { UI } from 'common/constants/theme' + import { // Import only the basic buttons ButtonPrimary as ButtonPrimaryMod, @@ -49,7 +51,7 @@ export const ButtonPrimary = styled(ButtonPrimaryMod)` } &:disabled { - background-color: ${({ theme }) => theme.grey1}; + background-color: var(${UI.COLOR_GREY}); color: ${({ theme }) => transparentize(0.4, theme.text1)}; background-image: none; border: 0; @@ -166,7 +168,7 @@ export const ButtonOutlined = styled(ButtonOutlinedMod)` export const ButtonConfirmedStyle = styled(ButtonConfirmedStyleMod)` // CSS overrides background-color: ${({ theme }) => theme.disabled}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); background-image: none; border: 0; cursor: auto; @@ -178,14 +180,14 @@ export const ButtonConfirmedStyle = styled(ButtonConfirmedStyleMod)` export const ButtonErrorStyle = styled(ButtonPrimary)` // CSS overrides background: ${({ theme }) => theme.red1}; - color: ${({ theme }) => theme.bg1}; + color: var(${UI.COLOR_CONTAINER_BG_01}); transition: background 0.15s ease-in-out; &:focus, &:hover, &:active { background: ${({ theme }) => theme.red1}; - color: ${({ theme }) => theme.bg1}; + color: var(${UI.COLOR_CONTAINER_BG_01}); } &:hover { diff --git a/apps/cowswap-frontend/src/legacy/components/Card/index.tsx b/apps/cowswap-frontend/src/legacy/components/Card/index.tsx index 723d473ed2..d1bb1601c1 100644 --- a/apps/cowswap-frontend/src/legacy/components/Card/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Card/index.tsx @@ -1,6 +1,8 @@ import { Box } from 'rebass/styled-components' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + const Card = styled(Box)<{ width?: string; padding?: string; border?: string; $borderRadius?: string }>` width: ${({ width }) => width ?? '100%'}; padding: ${({ padding }) => padding ?? '1rem'}; @@ -11,7 +13,7 @@ export default Card export const LightCard = styled(Card)` border: 1px solid ${({ theme }) => theme.bg2}; - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); ` export const LightGreyCard = styled(Card)` diff --git a/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx b/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx index db283a7f7c..0d1a40bc8d 100644 --- a/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx @@ -8,8 +8,9 @@ import { TransactionStatusText } from 'legacy/components/Copy/index' import useCopyClipboard from 'legacy/hooks/useCopyClipboard' import { LinkStyledButton } from 'legacy/theme' -// MOD imports +import { UI } from 'common/constants/theme' +// MOD imports export const CopyIcon = styled(LinkStyledButton)` color: ${({ theme }) => theme.text3}; flex-shrink: 0; @@ -27,7 +28,7 @@ export const CopyIcon = styled(LinkStyledButton)` :active, :focus { text-decoration: none; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); } ` diff --git a/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx b/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx index 3222ba17da..83d5564e8a 100644 --- a/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx @@ -6,11 +6,12 @@ import styled, { css } from 'styled-components/macro' import CowProtocolLogo from 'legacy/components/CowProtocolLogo' import { useCombinedBalance } from 'legacy/state/cowToken/hooks' +import { UI } from 'common/constants/theme' import { TokenAmount } from 'common/pure/TokenAmount' export const Wrapper = styled.div<{ isLoading: boolean }>` background-color: transparent; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); padding: 6px 12px; border: 2px solid transparent; font-weight: 500; diff --git a/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx b/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx index a2b4e87679..d4e937e956 100644 --- a/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx +++ b/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx @@ -7,6 +7,7 @@ import styled from 'styled-components/macro' import { V_COW } from 'legacy/constants/tokens' import { useIsDarkMode } from 'legacy/state/user/hooks' +import { UI } from 'common/constants/theme' import { TokenAmount } from 'common/pure/TokenAmount' import { COW_SUBSIDY_DATA } from './constants' @@ -24,7 +25,7 @@ const StyledSubsidyTable = styled.table` } tbody { - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 16px; border: 0; } @@ -49,7 +50,7 @@ const SubsidyTr = styled.tr<{ selected?: boolean; darkMode?: boolean }>` } &:hover > td { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); background: ${({ theme }) => transparentize(0.9, theme.text1)}; } @@ -60,7 +61,7 @@ const SubsidyTr = styled.tr<{ selected?: boolean; darkMode?: boolean }>` > td { font-size: 15px; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); transition: background 0.3s ease-in-out; } diff --git a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx index 6d1c7999e0..33647df010 100644 --- a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx +++ b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx @@ -14,6 +14,8 @@ import { userAgent } from 'legacy/utils/userAgent' import { Title } from 'modules/application/pure/Page' +import { UI } from 'common/constants/theme' + const FlexContainer = styled.div` display: flex; align-items: center; @@ -37,14 +39,14 @@ const StyledParagraph = styled.p` ` const CodeBlockWrapper = styled.div` - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); overflow: auto; white-space: pre; box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), 0px 24px 32px rgba(0, 0, 0, 0.01); border-radius: 16px; padding: 16px; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); /* MOD */ ${({ theme }) => theme.mediaWidth.upToSmall` diff --git a/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx b/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx index 68fab5b798..03f72ca2a4 100644 --- a/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx @@ -4,6 +4,8 @@ import styled from 'styled-components/macro' import CowIcon from 'legacy/assets/cow-swap/cowprotocol.svg' +import { UI } from 'common/constants/theme' + export const LoadingWrapper = styled.div` display: flex; flex-flow: column wrap; @@ -25,7 +27,7 @@ export const LoadingWrapper = styled.div` } > svg > g { - fill: ${({ theme }) => theme.text2}; + fill: var(${UI.COLOR_TEXT2}); } > span { @@ -35,7 +37,7 @@ export const LoadingWrapper = styled.div` font-weight: 500; letter-spacing: 2px; margin: 5px auto 0; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); } @keyframes pulse { diff --git a/apps/cowswap-frontend/src/legacy/components/Header/MobileMenuIcon/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/MobileMenuIcon/index.tsx index 393e7ffe99..b14fe517b5 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/MobileMenuIcon/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/MobileMenuIcon/index.tsx @@ -1,5 +1,7 @@ import styled, { css } from 'styled-components/macro' +import { UI } from 'common/constants/theme' + const Wrapper = styled.div<{ isMobileMenuOpen: boolean; height?: number; width?: number; lineSize?: number }>` z-index: 102; display: flex; @@ -10,7 +12,7 @@ const Wrapper = styled.div<{ isMobileMenuOpen: boolean; height?: number; width?: height: ${({ height = 18 }) => `${height}px`}; span { - background-color: ${({ theme }) => theme.text1}; + background-color: var(${UI.COLOR_TEXT1}); border-radius: 3px; height: ${({ lineSize = 2 }) => `${lineSize}px`}; position: absolute; diff --git a/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx index 3b47456c5c..99243a99e9 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx @@ -16,13 +16,14 @@ import { MEDIA_WIDTHS } from 'legacy/theme' import { useWalletInfo } from 'modules/wallet' import { getIsTallyWallet } from 'modules/wallet/api/utils/connection' +import { UI } from 'common/constants/theme' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet' import { useOnSelectNetwork } from 'common/hooks/useOnSelectNetwork' import { NetworksList } from 'common/pure/NetworksList' const FlyoutHeader = styled.div` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-weight: 400; ` @@ -43,7 +44,7 @@ const FlyoutMenu = styled.div` const FlyoutMenuContents = styled.div` align-items: flex-start; - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); border: 1px solid ${({ theme }) => theme.bg0}; box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), 0px 24px 32px rgba(0, 0, 0, 0.01); @@ -82,7 +83,7 @@ const SelectorLabel = styled.div` ` const SelectorControls = styled.div<{ isChainIdUnsupported: boolean }>` align-items: center; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); display: flex; font-weight: 500; justify-content: space-between; diff --git a/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx b/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx index f340cda3f0..0ab10a92fc 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx @@ -16,6 +16,7 @@ import { ExplorerDataType, getExplorerLink } from 'legacy/utils/getExplorerLink' import { useWalletInfo } from 'modules/wallet' +import { UI } from 'common/constants/theme' import useBlockNumber from 'lib/hooks/useBlockNumber' import { ChainConnectivityWarning } from './ChainConnectivityWarning' @@ -103,7 +104,7 @@ export const Spinner = styled.div<{ warning: boolean }>` const Wrapper = styled.div` ${StyledPolling} { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); position: relative; margin: 0; padding: 0; @@ -113,7 +114,7 @@ const Wrapper = styled.div` opacity: 1; a { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); opacity: 0.5; transition: opacity 0.3s ease-in-out; text-decoration: none; @@ -130,7 +131,7 @@ const Wrapper = styled.div` ${StyledPollingNumber} > a { opacity: 1; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); &:hover { opacity: 1; @@ -141,7 +142,7 @@ const Wrapper = styled.div` ${StyledGasDot}, ${StyledPollingDot} { - background: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_TEXT1}); } ${StyledPollingDot} { diff --git a/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx b/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx index 722d706963..23080235dd 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx @@ -9,6 +9,8 @@ import styled, { css } from 'styled-components/macro' import { MenuFlyout, MenuSection, Content as MenuContent, MenuTitle } from 'legacy/components/MenuDropdown/styled' import Row, { RowFixed } from 'legacy/components/Row' +import { UI } from 'common/constants/theme' + const activeClassName = 'active' export const TitleMod = styled.a` @@ -77,7 +79,7 @@ export const StyledNavLinkUni = styled(NavLink)` outline: none; cursor: pointer; text-decoration: none; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); font-size: 1rem; width: fit-content; margin: 0 12px; @@ -85,7 +87,7 @@ export const StyledNavLinkUni = styled(NavLink)` &.${activeClassName} { border-radius: 12px; font-weight: 600; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } :hover, @@ -119,7 +121,7 @@ export const StyledMenuButton = styled.button` margin-top: 2px; } > * { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` @@ -177,7 +179,7 @@ export const StyledNavLink = styled(StyledNavLinkUni)` &:hover, &:focus { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ` @@ -223,7 +225,7 @@ export const HeaderElement = styled(HeaderElementUni)` width: 100%; border-radius: 0; height: 64px; - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); border-top: 1px solid ${({ theme }) => theme.grey1}; backdrop-filter: blur(21px); padding: 10px 16px; @@ -253,7 +255,7 @@ export const Wrapper = styled.div<{ isMobileMenuOpen: boolean }>` width: 100%; display: flex; height: 60px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); position: fixed; top: 0; left: 0; @@ -283,7 +285,7 @@ export const HeaderModWrapper = styled(HeaderMod)`` export const Title = styled(TitleMod)<{ isMobileMenuOpen: boolean }>` margin: 0; text-decoration: none; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ${({ theme, isMobileMenuOpen }) => theme.mediaWidth.upToLarge` ${ @@ -315,7 +317,7 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }> cursor: pointer; background: transparent; transition: background 0.15s ease-in-out, color 0.15s ease-in-out; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); ${({ theme }) => theme.mediaWidth.upToLarge` width: 100%; @@ -324,17 +326,17 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }> font-weight: 600; font-size: 17px; padding: 28px 10px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); border-bottom: 1px solid ${({ theme }) => transparentize(0.9, theme.text1)}; `}; > svg > path { - fill: ${({ theme }) => theme.text2}; + fill: var(${UI.COLOR_TEXT2}); transition: fill 0.15s ease-in-out; } &:hover { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); background: ${({ theme }) => transparentize(0.95, theme.text1)}; ${({ theme }) => theme.mediaWidth.upToLarge` @@ -342,7 +344,7 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }> `}; > svg > path { - fill: ${({ theme }) => theme.text1}; + fill: var(${UI.COLOR_TEXT1}); } } @@ -357,7 +359,7 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }> } &.ACTIVE { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-weight: 600; } } @@ -407,7 +409,7 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }> left: 0; bottom: 0; z-index: 3; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); outline: 0; padding: 60px 8px; overflow-x: hidden; @@ -447,11 +449,11 @@ export const TwitterLink = styled(StyledMenuButton)` } > a > svg > path { - fill: ${({ theme }) => theme.text1}; + fill: var(${UI.COLOR_TEXT1}); } > a:hover > svg > path { - fill: ${({ theme }) => theme.text1}; + fill: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx b/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx index 739716c0c2..79645741e0 100644 --- a/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx @@ -5,9 +5,11 @@ import styled from 'styled-components/macro' import { MouseoverTooltipContent, TooltipContainer } from 'legacy/components/Tooltip' +import { UI } from 'common/constants/theme' + const StyledInfoIcon = styled(Info)` opacity: 0.5; - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); line-height: 0; vertical-align: middle; transition: opacity 0.2s ease-in-out; diff --git a/apps/cowswap-frontend/src/legacy/components/ListLogo/index.tsx b/apps/cowswap-frontend/src/legacy/components/ListLogo/index.tsx index f74c6891cc..f14a5d1def 100644 --- a/apps/cowswap-frontend/src/legacy/components/ListLogo/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/ListLogo/index.tsx @@ -2,8 +2,9 @@ import React from 'react' import styled from 'styled-components/macro' +import Logo from 'legacy/components/Loader/Logo' + import useHttpLocations from '../../hooks/useHttpLocations' -import Logo from '../Logo' export const StyledListLogo = styled(Logo)<{ size: string }>` width: ${({ size }) => size}; diff --git a/apps/cowswap-frontend/src/legacy/components/Logo/index.tsx b/apps/cowswap-frontend/src/legacy/components/Loader/Logo/index.tsx similarity index 95% rename from apps/cowswap-frontend/src/legacy/components/Logo/index.tsx rename to apps/cowswap-frontend/src/legacy/components/Loader/Logo/index.tsx index 1608d514b0..dacadaf187 100644 --- a/apps/cowswap-frontend/src/legacy/components/Logo/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Loader/Logo/index.tsx @@ -3,7 +3,7 @@ import { useState } from 'react' import { Slash } from 'react-feather' import { ImageProps } from 'rebass' -import useTheme from '../../hooks/useTheme' +import useTheme from 'legacy/hooks/useTheme' const BAD_SRCS: { [tokenAddress: string]: true } = {} diff --git a/apps/cowswap-frontend/src/legacy/components/MenuDropdown/styled.ts b/apps/cowswap-frontend/src/legacy/components/MenuDropdown/styled.ts index 5ce1c5fa51..a772f40a3f 100644 --- a/apps/cowswap-frontend/src/legacy/components/MenuDropdown/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/MenuDropdown/styled.ts @@ -1,6 +1,8 @@ import { transparentize } from 'polished' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const MenuFlyout = styled.ol` display: flex; padding: 0; @@ -50,7 +52,7 @@ export const Content = styled.div` left: 0; border-radius: 16px; border: 1px solid ${({ theme }) => transparentize(0.6, theme.white)}; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); box-shadow: ${({ theme }) => theme.boxShadow2}; padding: 32px; gap: 62px; @@ -107,7 +109,7 @@ export const MenuSection = styled.div` font-weight: 500; margin: 0; padding: 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); opacity: 0.8; transition: opacity 0.15s ease-in-out; @@ -118,11 +120,11 @@ export const MenuSection = styled.div` max-height: 21px; margin: 0 7px 0 0; object-fit: contain; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } > svg > path { - fill: ${({ theme }) => theme.text1}; + fill: var(${UI.COLOR_TEXT1}); } &:hover { diff --git a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx index c277515592..28ae411cf6 100644 --- a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx +++ b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx @@ -13,6 +13,8 @@ import { ExternalLink, HideSmall } from 'legacy/theme' import { useWalletInfo } from 'modules/wallet' +import { UI } from 'common/constants/theme' + const L2Icon = styled.img` width: 24px; height: 24px; @@ -74,19 +76,19 @@ const ContentWrapper = styled.div<{ chainId: NetworkAlertChains; darkMode: boole ${BodyText}, ${StyledArrowUpRight} { - color: ${({ theme }) => theme.text2}; - stroke: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); + stroke: var(${UI.COLOR_TEXT2}); text-decoration: none; transition: transform 0.2s ease-in-out, stroke 0.2s ease-in-out, color 0.2s ease-in-out; } &:hover { - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); ${BodyText}, ${StyledArrowUpRight} { - color: ${({ theme }) => theme.text1}; - stroke: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); + stroke: var(${UI.COLOR_TEXT1}); transform: rotate(0); } diff --git a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts index 9241855a54..bc150fbc24 100644 --- a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts +++ b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts @@ -2,7 +2,9 @@ import styled from 'styled-components/macro' import { ExternalLink } from 'legacy/theme' +import { UI } from 'common/constants/theme' + export const ReadMoreLink = styled(ExternalLink)` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); text-decoration: underline; ` diff --git a/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx b/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx index 6d63de857e..a462ca229a 100644 --- a/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx @@ -2,6 +2,7 @@ import React from 'react' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' import { autofocus } from 'common/utils/autofocus' import { escapeRegExp } from '../../utils' @@ -14,7 +15,7 @@ const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: s outline: none; border: none; flex: 1 1 auto; - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); font-size: ${({ fontSize }) => fontSize ?? '28px'}; text-align: ${({ align }) => align && align}; white-space: nowrap; diff --git a/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts b/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts index b0d1f9cf8d..abe234b096 100644 --- a/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts @@ -5,6 +5,8 @@ import styled from 'styled-components/macro' import CowProtocolLogo from 'legacy/assets/cow-swap/cowprotocol.svg' import { ExternalLink } from 'legacy/theme' +import { UI } from 'common/constants/theme' + export const ProgressBarWrapper = animated(styled.div` display: flex; flex-direction: column; @@ -16,8 +18,8 @@ export const ProgressBarWrapper = animated(styled.div` flex-flow: column wrap; border-radius: 12px; padding: 20px 20px 0; - color: ${({ theme }) => theme.text1}; - background-color: ${({ theme }) => theme.grey1}; + color: var(${UI.COLOR_TEXT1}); + background-color: var(${UI.COLOR_GREY}); transition: height 0.2s ease; ${({ theme }) => theme.mediaWidth.upToSmall` @@ -205,7 +207,7 @@ export const StatusWrapper = styled.div` export const StatusMsg = styled.p` font-size: 0.85rem; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); margin: 0; ${({ theme }) => theme.mediaWidth.upToSmall` font-size: 0.835rem; @@ -217,7 +219,7 @@ export const StatusMsg = styled.p` ` export const StyledCoWLink = styled(ExternalLink)` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); text-decoration: underline; opacity: 1 !important; diff --git a/apps/cowswap-frontend/src/legacy/components/Popover/PopoverMod.tsx b/apps/cowswap-frontend/src/legacy/components/Popover/PopoverMod.tsx index 1f09819ff3..a9e44ca4c1 100644 --- a/apps/cowswap-frontend/src/legacy/components/Popover/PopoverMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Popover/PopoverMod.tsx @@ -6,6 +6,7 @@ import { transparentize } from 'polished' import { usePopper } from 'react-popper' import styled, { DefaultTheme, StyledComponent } from 'styled-components/macro' +import { UI } from 'common/constants/theme' import useInterval from 'lib/hooks/useInterval' // MOD imports @@ -17,10 +18,10 @@ export const PopoverContainer = styled.div<{ show: boolean }>` visibility: ${(props) => (props.show ? 'visible' : 'hidden')}; opacity: ${(props) => (props.show ? 1 : 0)}; transition: visibility 150ms linear, opacity 150ms linear; - /* color: ${({ theme }) => theme.text2}; */ + /* color: var(${UI.COLOR_TEXT2}); */ /* MOD */ - color: ${({ theme }) => theme.text1}; - background: ${({ theme }) => theme.bg1}; + color: var(${UI.COLOR_TEXT1}); + background: var(${UI.COLOR_CONTAINER_BG_01}); border: 1px solid ${({ theme }) => theme.bg3}; box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.9, theme.shadow1)}; border-radius: 8px; @@ -44,7 +45,7 @@ export const Arrow = styled.div` content: ''; border: 1px solid ${({ theme }) => theme.bg3}; transform: rotate(45deg); - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); } &.arrow-top { diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/styled.ts b/apps/cowswap-frontend/src/legacy/components/Popups/styled.ts index e2c42b455d..c730ac9988 100644 --- a/apps/cowswap-frontend/src/legacy/components/Popups/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/Popups/styled.ts @@ -2,6 +2,8 @@ import { animated } from '@react-spring/web' import { X } from 'react-feather' import styled, { DefaultTheme, FlattenInterpolation, ThemeProps } from 'styled-components/macro' +import { UI } from 'common/constants/theme' + const Fader = styled.div` position: absolute; bottom: 0px; @@ -15,7 +17,7 @@ export const PopupWrapper = styled.div<{ css?: FlattenInterpolation theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); position: relative; border-radius: 10px; padding: 20px 35px 20px 20px; diff --git a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx index de88370b2f..f734b09742 100644 --- a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx @@ -21,7 +21,7 @@ import { QuestionWrapper } from './index' border-radius: 36px; font-size: 12px; background-color: ${({ theme }) => theme.bg2}; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); :hover, :focus { diff --git a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx index ddb73d7b88..89711c44d5 100644 --- a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx @@ -6,6 +6,8 @@ import styled from 'styled-components/macro' import QuestionImage from 'legacy/assets/svg/question.svg' import { renderTooltip } from 'legacy/components/Tooltip' +import { UI } from 'common/constants/theme' + import QuestionHelperMod, { QuestionHelperProps } from './QuestionHelperMod' const QuestionMark = () => @@ -24,7 +26,7 @@ export const QuestionWrapper = styled.div` background-color: transparent; > svg > path { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx index 1f3ccbb4e5..8e4a427df0 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx @@ -65,6 +65,7 @@ function Balance({ balance }: { balance: CurrencyAmount }) { export const TagContainer = styled.div` display: flex; justify-content: flex-end; + flex-flow: row wrap; ` export const TokenListLogoWrapper = styled.img` @@ -92,8 +93,13 @@ function TokenTags({ currency }: { currency: Currency }) { return ( - {tag.name} + + {tag.icon && {tag.name}} + {tag.name} + + + {/* If there are more than one tag, show the first one and a '...' tag */} {tags.length > 1 ? ( isUnsupported: boolean // gp-added + isPermitCompatible: boolean // gp-added allTokens: { [address: string]: Token } // gp-added BalanceComponent?: (params: { balance: CurrencyAmount }) => JSX.Element // gp-swap added - TokenTagsComponent?: (params: { currency: Currency; isUnsupported: boolean }) => JSX.Element // gp-swap added + TokenTagsComponent?: (params: { currency: Currency; isUnsupported: boolean; isPermitCompatible: boolean }) => JSX.Element // gp-swap added }) { const { account } = useWalletInfo() const key = currencyKey(currency) @@ -170,7 +178,7 @@ function CurrencyRow({ {/* */} - + {showCurrencyAmount && ( {balance ? : account ? : null} @@ -336,6 +344,7 @@ export default function CurrencyList({ const showImport = index > currencies.length const isUnsupported = !!isUnsupportedToken(token?.address) + const isPermitCompatible = false // TODO: Make dynamic if (isLoading) { return ( @@ -361,6 +370,7 @@ export default function CurrencyList({ BalanceComponent={BalanceComponent} // gp-swap added TokenTagsComponent={TokenTagsComponent} // gp-swap added isUnsupported={isUnsupported} + isPermitCompatible={isPermitCompatible} // gp-swap added showCurrencyAmount={showCurrencyAmount} eventProperties={formatAnalyticsEventProperties(token, index, data, searchQuery, isAddressSearch)} /> diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx index 22c4363b78..d176f7e1a5 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx @@ -1,99 +1,41 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' // eslint-disable-next-line no-restricted-imports -import { t } from '@lingui/macro' -import { transparentize } from 'polished' +// import { t } from '@lingui/macro' +import ICON_GAS_FREE from 'assets/icon/gas-free.svg' import { HashLink } from 'react-router-hash-link' import styled from 'styled-components/macro' -import { LightGreyCard } from 'legacy/components/Card' -import Column from 'legacy/components/Column' -import { RowFixed } from 'legacy/components/Row' + import { MenuItem as MenuItemMod } from 'legacy/components/SearchModal/styleds' import { MouseoverTooltip } from 'legacy/components/Tooltip' import { UNSUPPORTED_TOKENS_FAQ_URL } from 'legacy/constants' import { TagInfo } from 'legacy/state/lists/wrappedTokenInfo' -import { StyledLogo } from 'common/pure/CurrencyLogo' import { TokenAmount } from 'common/pure/TokenAmount' import CurrencyListMod, { StyledBalanceText, TagContainer } from './CurrencyListMod' -import { Tag as TagMod } from './styled' +import { Wrapper, Tag, TagLink } from './styled' + +enum Tags { + UNSUPPORTED = '0', + GAS_FREE = '1', +} -const UNSUPPORTED_TOKEN_TAG = [ - { +const TOKEN_TAGS: Record = { + [Tags.UNSUPPORTED]: { name: 'Unsupported', description: 'This token is unsupported as it does not operate optimally with CoW Protocol. Please refer to the FAQ for more information.', id: '0', }, -] - -const Tag = styled(TagMod)<{ tag?: TagInfo }>` - // Todo: Prevent usage of !important - background: ${({ tag, theme }) => (tag?.id === '0' ? transparentize(0.85, theme.danger) : theme.grey1)}; - color: ${({ tag, theme }) => (tag?.id === '0' ? theme.danger : theme.text1)}!important; - max-width: 6.1rem; -` - -const TagLink = styled(Tag)` - display: flex; - align-items: center; - font-size: x-small; - a { - color: inherit; - font-weight: bold; - } -` - -const Wrapper = styled.div` - ${Column} { - > div { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - max-width: 220px; - width: 100%; - - // Token symbol name - &:first-of-type { - color: ${({ theme }) => theme.text1}; - } - - // Token full name - &:last-of-type { - color: ${({ theme }) => theme.text2}; - font-weight: 400; - } - - ${({ theme }) => theme.mediaWidth.upToSmall` - max-width: 140px; - `}; - } + [Tags.GAS_FREE]: { + name: 'Gas-free approval', + icon: ICON_GAS_FREE, + description: 'This token can be approved without spending gas, using the token Permit.', + id: '1', } - - ${StyledLogo} { - height: 36px; - width: 36px; - border-radius: 36px; - } - - ${TagMod} { - color: ${({ theme }) => theme.text2}; - } - - ${TagLink} { - color: ${({ theme }) => theme.text1}; - } - - ${LightGreyCard} { - background: ${({ theme }) => theme.bg1}; - } - - ${LightGreyCard} ${RowFixed} > div { - color: ${({ theme }) => theme.text1}; - } -` +}; export const MenuItem = styled(MenuItemMod)` &:hover { @@ -101,53 +43,52 @@ export const MenuItem = styled(MenuItemMod)` } ` -function TagDescriptor({ tags, children }: { children?: React.ReactNode; tags: TagInfo[]; bg?: string }) { - const tag = tags[0] - return ( - - - - {tag.name} - - - {tags.length > 1 ? ( - t`${name}: ${description}`) - .join('; \n')} - > - ... - - ) : null} - {children} - - ) -} +function TokenTags({ + isUnsupported, + isPermitCompatible +}: { + isUnsupported: boolean; + isPermitCompatible?: boolean; +}) { + const tagsToShow: TagInfo[] = []; -function TokenTags({ /* currency, */ isUnsupported }: { /* currency: Currency; */ isUnsupported: boolean }) { if (isUnsupported) { - return ( - + tagsToShow.push(TOKEN_TAGS[Tags.UNSUPPORTED]); + } else if (isPermitCompatible) { + tagsToShow.push(TOKEN_TAGS[Tags.GAS_FREE]); + } + + if (tagsToShow.length === 0) { + return ; + } + + return ( + + {isUnsupported && ( e.stopPropagation()}> FAQ - - ) - } - - return // MOD: return only UnsupportedToken tags - - /* if (!(currency instanceof WrappedTokenInfo)) { - return - } - - const tags = currency.tags - if (!tags || tags.length === 0) return + )} + + ); +} - return */ +function TagDescriptor({ tags, children }: { children?: React.ReactNode; tags: TagInfo[]; }) { + return ( + + {tags.map(tag => ( + + + {tag.icon ? {tag.name} : null} + {tag.name} + + + ))} + {children} + + ); } export function Balance({ balance }: { balance: CurrencyAmount }) { diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts index 83165c1e07..e140b9fa12 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts @@ -1,15 +1,81 @@ import styled from 'styled-components/macro' -export const Tag = styled.div` - background-color: ${({ theme }) => theme.bg3}; - color: ${({ theme }) => theme.text2}; - font-size: 14px; +import { LightGreyCard } from 'legacy/components/Card' +import Column from 'legacy/components/Column' +import { RowFixed } from 'legacy/components/Row' +import { TagInfo } from 'legacy/state/lists/wrappedTokenInfo' + +import { UI } from 'common/constants/theme' +import { StyledLogo } from 'common/pure/CurrencyLogo' + +export const Tag = styled.div<{ tag?: TagInfo }>` + display: flex; + align-items: center; + background: ${({ tag }) => (tag?.id === '0' ? `var(${UI.COLOR_DANGER_BG})` : tag?.id === '1' ? `var(${UI.COLOR_SUCCESS_BG})` : `var(${UI.COLOR_GREY})`)}; + color: ${({ tag }) => (tag?.id === '0' ? `var(${UI.COLOR_DANGER_TEXT})` : tag?.id === '1' ? `var(${UI.COLOR_SUCCESS_TEXT})` : `var(${UI.COLOR_TEXT1})`)}; + font-size: 12px; + font-weight: var(${UI.FONT_WEIGHT_MEDIUM}); border-radius: 4px; - padding: 0.25rem 0.3rem 0.25rem 0.3rem; - max-width: 6rem; + padding: 4px 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; justify-self: flex-end; - margin-right: 4px; + margin: 0 4px 0 0; + + > img { + --size: 14px; + display: inline-block; + margin: 0 5px 0 0; + width: var(--size); + height: var(--size); + } +` + +export const TagLink = styled(Tag)` + a { + color: inherit; + font-weight: inherit; + } +` + +export const Wrapper = styled.div` + ${Column} { + > div { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + max-width: 220px; + width: 100%; + + // Token symbol name + &:first-of-type { + color: var(${UI.COLOR_TEXT1}); + } + + // Token full name + &:last-of-type { + color: var(${UI.COLOR_TEXT2}); + font-weight: 400; + } + + ${({ theme }) => theme.mediaWidth.upToSmall` + max-width: 140px; + `}; + } + } + ${StyledLogo} { + height: 36px; + width: 36px; + border-radius: 36px; + } + ${TagLink} { + color: var(${UI.COLOR_TEXT1}); + } + ${LightGreyCard} { + background: var(${UI.COLOR_CONTAINER_BG_01}); + } + ${LightGreyCard} ${RowFixed} > div { + color: var(${UI.COLOR_TEXT1}); + } ` diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx index 500ca4483c..867e383947 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx @@ -29,6 +29,7 @@ import { isAddress } from 'legacy/utils' import { useWalletInfo } from 'modules/wallet' +import { UI } from 'common/constants/theme' import { useExternalTokenSearch } from 'common/hooks/useExternalTokenSearch' import useNativeCurrency from 'lib/hooks/useNativeCurrency' import { getTokenFilter } from 'lib/hooks/useTokenList/filtering' @@ -42,7 +43,7 @@ export const Footer = styled.div` padding: 20px; border-top-left-radius: 0; border-top-right-radius: 0; - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); ` export interface CurrencySearchProps { diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx index 7174b3c087..82732aaf5f 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx @@ -9,6 +9,8 @@ import { RowFixed } from 'legacy/components/Row' import { Separator } from 'legacy/components/SearchModal/styleds' import { IconWrapper, ThemedText } from 'legacy/theme' +import { UI } from 'common/constants/theme' + import { CurrencySearch as CurrencySearchMod, CurrencySearchProps } from './CurrencySearchMod' export const ContentWrapper = styled(Column)` @@ -19,8 +21,8 @@ export const ContentWrapper = styled(Column)` > input { border: none; transition: background 0.3s ease-in-out; - background: ${({ theme }) => theme.bg1}; - color: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1}); } > input::placeholder { @@ -33,7 +35,7 @@ export const ContentWrapper = styled(Column)` } ${Separator} { - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); // Target the token list container + div { diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx index 38d8522d74..a45c3c4679 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx @@ -8,6 +8,8 @@ import { ButtonPrimary } from 'legacy/components/Button' import { StyledListLogo } from 'legacy/components/ListLogo' import { AutoRow } from 'legacy/components/Row' +import { UI } from 'common/constants/theme' + import ImportRowMod, { TokenSection } from './ImportRowMod' interface ImportRowProps { @@ -31,7 +33,7 @@ const Wrapper = styled.div` } ${TokenSection} > svg { - stroke: ${({ theme }) => theme.text2}; + stroke: var(${UI.COLOR_TEXT2}); } ${TokenSection} ${AutoRow} { @@ -40,7 +42,7 @@ const Wrapper = styled.div` } ${AutoRow} > div { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); margin: 0; } diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx index 1d2312a50b..8d82573728 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx @@ -14,6 +14,7 @@ import { ThemedText } from 'legacy/theme' import { ExternalLink } from 'legacy/theme/components' import { getEtherscanLink as getExplorerLink } from 'legacy/utils' +import { UI } from 'common/constants/theme' import { CurrencyLogo } from 'common/pure/CurrencyLogo' import { AddressText, ImportProps, ImportToken as ImportTokenMod, WarningWrapper } from './ImportTokenMod' @@ -48,7 +49,7 @@ const Wrapper = styled.div` ${({ theme }) => theme.mediaWidth.upToSmall` position: sticky; top: 0; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); `} } ` diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx index 51da5e661a..cb60a324c5 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx @@ -8,6 +8,8 @@ import { RowBetween } from 'legacy/components/Row' import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal' import { SearchInput, Separator } from 'legacy/components/SearchModal/styleds' +import { UI } from 'common/constants/theme' + import ManageMod from './ManageMod' export const Wrapper = styled.div` @@ -19,7 +21,7 @@ export const Wrapper = styled.div` ${SearchInput} { border: none; transition: background 0.3s ease-in-out; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); } ${SearchInput}::placeholder { @@ -50,7 +52,7 @@ const ToggleOption = styled.div<{ active?: boolean }>` border-radius: 12px; font-weight: 600; background-color: ${({ theme, active }) => (active ? theme.bg1 : theme.bg1)}; - color: ${({ theme, active }) => (active ? theme.text1 : theme.disabled)}; + color: ${({ theme, active }) => (active ? `var(${UI.COLOR_TEXT1})` : theme.disabled)}; user-select: none; :hover { diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx index b60e1a86f5..88fcd11ae3 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx @@ -27,6 +27,7 @@ import listVersionLabel from 'legacy/utils/listVersionLabel' import { useWalletInfo } from 'modules/wallet' +import { UI } from 'common/constants/theme' import { useConfirmationRequest } from 'common/hooks/useConfirmationRequest' import parseENSAddress from 'lib/utils/parseENSAddress' import uriToHttp from 'lib/utils/uriToHttp' @@ -53,7 +54,7 @@ export const PopoverContainer = styled.div<{ show: boolean }>` border: 1px solid ${({ theme }) => theme.bg3}; box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), 0px 24px 32px rgba(0, 0, 0, 0.01); - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); border-radius: 0.5rem; padding: 1rem; display: grid; diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx index 04a9ea8889..bd59cb5673 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx @@ -13,6 +13,8 @@ import { acceptListUpdate, removeList, disableList, enableList } from 'legacy/st import { useWalletInfo } from 'modules/wallet' +import { UI } from 'common/constants/theme' + import { ManageLists as ManageListsMod, ListContainer, PopoverContainer } from './ManageListsMod' export interface ListRowProps { @@ -33,12 +35,12 @@ const Wrapper = styled.div` svg > path, svg > circle { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } } ${PopoverContainer} { - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); } ` @@ -54,18 +56,18 @@ export const RowWrapper = styled(Row)<{ bgColor: string; active: boolean; hasAct ${Row}, ${RowFixed}, ${RowBetween} { > div { - color: ${({ active, theme }) => (active ? theme.text1 : theme.text2)}; + color: ${({ active, theme }) => (active ? `var(${UI.COLOR_TEXT1})` : theme.text2)}; } } ` export const Card = styled(CardUni)` - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); ${Row}, ${Row} > div > div, ${Row} > div > div > div { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ${Row} > img { @@ -76,7 +78,7 @@ export const Card = styled(CardUni)` } ${TextDot} { - background: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_TEXT1}); } ${ButtonPrimary} { diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx index 5180018406..d8a85d6550 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx @@ -10,6 +10,8 @@ import ImportRow from 'legacy/components/SearchModal/ImportRow' import { Separator } from 'legacy/components/SearchModal/styleds' import { ButtonText, LinkIcon } from 'legacy/theme' +import { UI } from 'common/constants/theme' + import ManageTokensMod, { ManageTokensProps, Footer } from './ManageTokensMod' export type ImportTokensRowProps = Omit & { @@ -31,7 +33,7 @@ export const Wrapper = styled.div` } ${RowBetween} > div { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } // Custom Tokens Title @@ -41,7 +43,7 @@ export const Wrapper = styled.div` // Token name ${RowBetween} > div > a > div { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ${RowFixed} > svg, diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx index 814ce124a4..09e2077735 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx @@ -2,13 +2,15 @@ import styled from 'styled-components/macro' import { LoadingRows as BaseLoadingRows } from 'legacy/components/Loader/styled' +import { UI } from 'common/constants/theme' + import { AutoColumn } from '../Column' import { RowBetween } from '../Row' export const TextDot = styled.div` height: 3px; width: 3px; - background-color: ${({ theme }) => theme.text2}; + background-color: var(${UI.COLOR_TEXT2}); border-radius: 50%; ` @@ -52,7 +54,7 @@ export const SearchInput = styled.input` border: none; outline: none; border-radius: 20px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); border-style: solid; border: 1px solid ${({ theme }) => theme.bg3}; -webkit-appearance: none; diff --git a/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx b/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx index 63913309a9..5da1bdf8ff 100644 --- a/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx @@ -21,6 +21,7 @@ import { ApplicationModal } from 'legacy/state/application/reducer' import { useExpertModeManager, useRecipientToggleManager } from 'legacy/state/user/hooks' import { ThemedText } from 'legacy/theme' +import { UI } from 'common/constants/theme' import { ExpertModeModal } from 'common/pure/ExpertModeModal' import { SettingsTabProp } from './index' @@ -30,7 +31,7 @@ export const StyledMenuIcon = styled(Settings)` width: 20px; > * { - stroke: ${({ theme }) => theme.text2}; + stroke: var(${UI.COLOR_TEXT2}); } :hover { diff --git a/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx b/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx index d3e255ac47..6b054b3bc2 100644 --- a/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx @@ -6,14 +6,16 @@ import { WithClassName } from 'types' import { RowFixed } from 'legacy/components/Row' +import { UI } from 'common/constants/theme' + import SettingsMod, { StyledMenuButton, MenuFlyout, StyledMenuIcon, EmojiWrapper } from './SettingsMod' const Settings = styled(SettingsMod)` ${MenuFlyout} { box-shadow: ${({ theme }) => theme.boxShadow2}; border: 1px solid ${({ theme }) => transparentize(0.95, theme.white)}; - background-color: ${({ theme }) => theme.bg1}; - color: ${({ theme }) => theme.text1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1}); padding: 0; margin: 0; top: 36px; @@ -23,7 +25,7 @@ const Settings = styled(SettingsMod)` ${RowFixed} { > div { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); opacity: 0.85; } } @@ -42,7 +44,7 @@ const Settings = styled(SettingsMod)` &:focus { cursor: pointer; outline: none; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } svg { @@ -57,7 +59,7 @@ const Settings = styled(SettingsMod)` &:hover svg > path, &:hover svg > circle { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } } diff --git a/apps/cowswap-frontend/src/legacy/components/SideMenu/index.tsx b/apps/cowswap-frontend/src/legacy/components/SideMenu/index.tsx index ca314064a2..600010d723 100644 --- a/apps/cowswap-frontend/src/legacy/components/SideMenu/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SideMenu/index.tsx @@ -1,6 +1,8 @@ import { transparentize } from 'polished' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const SideMenu = styled.div<{ isAccountPage?: boolean }>` display: flex; flex-flow: column wrap; @@ -8,7 +10,7 @@ export const SideMenu = styled.div<{ isAccountPage?: boolean }>` font-weight: 500; line-height: 1; margin: 0 24px 0 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); height: max-content; position: sticky; top: 0; diff --git a/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx b/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx index c86fdc0f68..6afc897e6b 100644 --- a/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx @@ -3,6 +3,8 @@ import styled from 'styled-components/macro' import CheckCircle from 'legacy/assets/cow-swap/check.svg' +import { UI } from 'common/constants/theme' + export const Wrapper = styled.div<{ totalSteps: number }>` width: 100%; display: grid; @@ -84,7 +86,7 @@ export const Step = styled.div<{ > b { color: ${({ isActiveStep, completedStep, theme }) => - completedStep ? theme.text1 : isActiveStep ? theme.text1 : transparentize(0.4, theme.text1)}; + completedStep ? `var(${UI.COLOR_TEXT1})` : isActiveStep ? `var(${UI.COLOR_TEXT1})` : transparentize(0.4, theme.text1)}; font-weight: ${({ isActiveStep, completedStep }) => (completedStep ? '300' : isActiveStep ? 'bold' : '300')}; text-align: center; diff --git a/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx b/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx index 557df61a87..598cac262a 100644 --- a/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx @@ -12,6 +12,8 @@ import { useIsDarkMode } from 'legacy/state/user/hooks' import { StyledInfoIcon } from 'modules/swap/pure/styled' +import { UI } from 'common/constants/theme' + import { AuxInformationContainer } from '../swap/styleds' interface HighFeeContainerProps { @@ -52,7 +54,7 @@ const WarningContainer = styled(AuxInformationContainer).attrs((props) => ({ : LOW_TIER_FEE ? theme.alert : theme.info}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); padding: ${({ padding = '16px' }) => padding}; width: ${({ width = '100%' }) => width}; border-radius: 16px; diff --git a/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx b/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx index 57779b537f..661c779e98 100644 --- a/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx @@ -4,6 +4,8 @@ import { darken, transparentize } from 'polished' import styled, { keyframes } from 'styled-components/macro' import { WithClassName } from 'types' +import { UI } from 'common/constants/theme' + const turnOnToggle = keyframes` from { margin-left: 0em; @@ -54,7 +56,7 @@ export const ToggleElement = styled.span<{ isActive?: boolean; bgColor?: string; const Wrapper = styled.button<{ isActive?: boolean; activeElement?: boolean }>` align-items: center; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); background: ${({ theme, isActive }) => (isActive ? theme.bg2 : theme.grey1)}; border: none; border-radius: 20px; diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx index fee13ac2fb..a08ef71254 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx @@ -8,6 +8,8 @@ import { ButtonStar } from 'legacy/components/Button' import useTheme from 'legacy/hooks/useTheme' import { useFavouriteTokens, useToggleFavouriteToken } from 'legacy/state/user/hooks' +import { UI } from 'common/constants/theme' + export const StyledButtonStar = styled(ButtonStar)` z-index: 9; ` @@ -38,7 +40,7 @@ export default function FavouriteTokenButton({ tokenData }: FavouriteTokenButton return ( ) diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts b/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts index 942abb6dae..f27f6a8c10 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts @@ -5,6 +5,7 @@ import styled from 'styled-components/macro' import { BaseButton } from 'legacy/components/Button' +import { UI } from 'common/constants/theme' import { CurrencyLogo } from 'common/pure/CurrencyLogo' export const TokenSearchInput = styled.input` @@ -14,7 +15,7 @@ export const TokenSearchInput = styled.input` width: 100%; align-self: flex-end; box-shadow: none; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border: 1px solid ${({ theme }) => theme.bg1}; border-radius: 21px; transition: background 0.2s ease-in-out, max-width 0.2s ease-in-out; @@ -25,7 +26,7 @@ export const TokenSearchInput = styled.input` &:focus { max-width: 500px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); outline: 0; ${({ theme }) => theme.mediaWidth.upToMedium` @@ -59,7 +60,7 @@ export const Wrapper = styled.div` width: 100%; border: none; padding: 0; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border-radius: 16px; display: grid; ` @@ -80,8 +81,8 @@ export const ResponsiveLogo = styled(CurrencyLogo)` width: 28px; height: 28px; border-radius: 28px; - background: ${({ theme }) => theme.bg1}; - color: ${({ theme }) => theme.text1}!important; // TODO: prevent styles override + background: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1})!important; // TODO: prevent styles override ${({ theme }) => theme.mediaWidth.upToMedium` width: 21px; @@ -166,7 +167,7 @@ export const ArrowButton = styled.button` ` export const Arrow = styled.div<{ faded: boolean }>` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); opacity: ${(props) => (props.faded ? 0.3 : 1)}; padding: 0 10px; user-select: none; @@ -207,7 +208,7 @@ export const Row = styled.div` `} &:hover { - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); } ` @@ -248,11 +249,11 @@ export const Cell = styled.div` transition: text-decoration-color 0.2s ease-in-out; overflow: hidden; display: flex; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); &:hover { - color: ${({ theme }) => theme.text1}; - text-decoration-color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); + text-decoration-color: var(${UI.COLOR_TEXT1}); } } ` @@ -263,7 +264,7 @@ export const IndexNumber = styled.span` ` export const BalanceValue = styled.span<{ hasBalance: boolean }>` - color: ${({ hasBalance, theme }) => (hasBalance ? theme.text1 : transparentize(0.3, theme.text1))}; + color: ${({ hasBalance, theme }) => (hasBalance ? `var(${UI.COLOR_TEXT1})` : transparentize(0.3, theme.text1))}; font-weight: 500; font-size: 14px; white-space: nowrap; @@ -297,7 +298,7 @@ export const TableButton = styled(BaseButton)<{ color?: string; outlined?: boole max-height: 100%; > path { - fill: ${({ theme }) => theme.text1}; + fill: var(${UI.COLOR_TEXT1}); } } @@ -416,7 +417,7 @@ export const FiatValue = styled.div` ` export const InfoCircle = styled(HelpCircle)` - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); width: 15px; height: 15px; margin-left: 5px; diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/styled.ts b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/styled.ts index 4bf7292f56..16e407a371 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/styled.ts @@ -6,6 +6,8 @@ import { AutoColumn } from 'legacy/components/Column' import { RowBetween } from 'legacy/components/Row' import { CloseIcon, ExternalLink } from 'legacy/theme' +import { UI } from 'common/constants/theme' + export const Wrapper = styled.div` width: 100%; padding: 0; @@ -42,7 +44,7 @@ export const Header = styled.div` flex-direction: row; justify-content: space-between; align-items: center; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); position: sticky; top: 0; left: 0; @@ -115,7 +117,7 @@ export const GPModalHeader = styled(RowBetween)` left: 0; width: 100%; padding: 16px 0; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); z-index: 20; ` @@ -154,7 +156,7 @@ export const ButtonCustom = styled.button` border-radius: 16px; min-height: 52px; border: 1px solid ${({ theme }) => theme.border2}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); background: transparent; outline: 0; padding: 8px 16px; @@ -181,7 +183,7 @@ export const UpperSection = styled.div` display: flex; flex-flow: column wrap; padding: 16px 16px 32px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 16px 16px 0 0; ${({ theme }) => theme.mediaWidth.upToSmall` @@ -246,7 +248,7 @@ export const StepsIconWrapper = styled.div` height: 100%; width: 100%; padding: 18px; - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } @keyframes spin { @@ -304,7 +306,7 @@ export const StepsWrapper = styled.div` flex: 1 1 auto; height: 2px; border: 0; - background: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_TEXT1}); margin: auto; position: absolute; width: 100%; @@ -319,7 +321,7 @@ export const StepsWrapper = styled.div` content: ''; height: 4px; width: 100%; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); display: block; margin: 0; animation: Shrink 1s forwards linear; diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx index ae8541430c..e688df1d64 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx @@ -30,6 +30,7 @@ import { getNativeOrderDeadlineTooltip, getNonNativeOrderDeadlineTooltip } from import { getNativeSlippageTooltip, getNonNativeSlippageTooltip } from 'modules/swap/pure/Row/RowSlippageContent' import { useWalletInfo } from 'modules/wallet' +import { UI } from 'common/constants/theme' import useNativeCurrency from 'lib/hooks/useNativeCurrency' import QuestionHelper from '../QuestionHelper' @@ -47,7 +48,7 @@ enum DeadlineError { } export const FancyButton = styled.button` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); align-items: center; height: 2rem; border-radius: 36px; @@ -57,7 +58,7 @@ export const FancyButton = styled.button` /* border: 1px solid ${({ theme }) => theme.bg3}; */ border: 0; // mod outline: none; - /* background: ${({ theme }) => theme.bg1}; */ + /* background: var(${UI.COLOR_CONTAINER_BG_01}); */ background: ${({ theme }) => theme.bg2}; // mod :hover { /* border: 1px solid ${({ theme }) => theme.bg4}; */ @@ -84,7 +85,7 @@ const Option = styled(FancyButton)<{ active: boolean }>` ` export const Input = styled.input` - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); font-size: 16px; width: auto; outline: none; @@ -301,7 +302,7 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction fontSize: '14px', paddingTop: '7px', // color: slippageError ? 'red' : '#F3841E', - color: slippageError ? theme.danger : theme.warning, // MOD + color: slippageError ? `var(${UI.COLOR_DANGER})` : theme.warning, // MOD }} > {slippageError ? ( diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx index 34734c77d9..42b5906924 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx @@ -3,6 +3,8 @@ import styled from 'styled-components/macro' import { RowBetween, RowFixed } from 'legacy/components/Row' +import { UI } from 'common/constants/theme' + import SlippageTabsMod, { TransactionSettingsProps, OptionCustom } from './TransactionSettingsMod' const Wrapper = styled.div` @@ -15,7 +17,7 @@ const Wrapper = styled.div` } ${OptionCustom} { - background-color: ${({ theme }) => theme.grey1}; + background-color: var(${UI.COLOR_GREY}); border: 0; > div > input { @@ -27,18 +29,18 @@ const Wrapper = styled.div` > div > input::placeholder { opacity: 0.5; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } } ${RowFixed} { > div { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); opacity: 0.85; } > button { - background-color: ${({ theme }) => theme.grey1}; + background-color: var(${UI.COLOR_GREY}); border: 0; } @@ -49,7 +51,7 @@ const Wrapper = styled.div` > button > input::placeholder { background: transparent; opacity: 0.5; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } } ` diff --git a/apps/cowswap-frontend/src/legacy/components/Version/index.tsx b/apps/cowswap-frontend/src/legacy/components/Version/index.tsx index 42d2e7f177..401903fc4a 100644 --- a/apps/cowswap-frontend/src/legacy/components/Version/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Version/index.tsx @@ -10,6 +10,8 @@ import { getEtherscanLink } from 'legacy/utils' import { useWalletInfo } from 'modules/wallet' +import { UI } from 'common/constants/theme' + // eslint-disable-next-line @nx/enforce-module-boundaries import pkg from '../../../../../../package.json' @@ -67,7 +69,7 @@ const StyledPolling = styled.div` flex-flow: column nowrap; align-items: flex-start; padding: 16px 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); gap: 10px; ` diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx index 47485e4672..5d9614d370 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx @@ -7,9 +7,11 @@ import SettingsTab from 'legacy/components/Settings' import { TradeWidgetLinks } from 'modules/application/containers/TradeWidgetLinks' +import { UI } from 'common/constants/theme' + const StyledSwapHeader = styled.div` width: 100%; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); ` export default function SwapHeader({ allowedSlippage, className }: { allowedSlippage: Percent; className?: string }) { diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx index 054e7ddd5a..22f3794a3b 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx @@ -9,10 +9,12 @@ import { AutoRow, RowBetween, RowFixed } from 'legacy/components/Row' import { SwapCallbackError } from 'legacy/components/swap/styleds' import { ButtonSize } from 'legacy/theme/enum' +import { UI } from 'common/constants/theme' + const Wrapper = styled.div` ${RowBetween} > div, ${RowFixed} > div { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx index 802cc6b9e0..a017dec668 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx @@ -10,10 +10,12 @@ import { HighFeeWarning as HighFeeWarningBase } from 'legacy/components/SwapWarn import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning' import { useWalletDetails } from 'modules/wallet' +import { UI } from 'common/constants/theme' + import SwapModalHeaderMod, { SwapModalHeaderProps } from './SwapModalHeaderMod' const LightCard = styled(LightCardUni)<{ flatBorder?: boolean }>` - background-color: ${({ theme }) => theme.grey1}; + background-color: var(${UI.COLOR_GREY}); border: none; ${({ flatBorder = false }) => flatBorder && `border-radius: 20px 20px 0 0;`}; ` @@ -40,7 +42,7 @@ const Wrapper = styled.div` } svg { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx index f6c24ca0fc..e3e614b5c7 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx @@ -15,6 +15,7 @@ import { getEtherscanLink } from 'legacy/utils' import { useWalletInfo } from 'modules/wallet' +import { UI } from 'common/constants/theme' import { CurrencyLogo } from 'common/pure/CurrencyLogo' import { Modal } from 'common/pure/Modal' @@ -28,7 +29,7 @@ export const DetailsFooter = styled.div<{ show: boolean }>` max-width: 400px; border-bottom-left-radius: 20px; border-bottom-right-radius: 20px; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); background-color: ${({ theme }) => theme.advancedBG}; z-index: ${Z_INDEX.deprecated_zero}; diff --git a/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx b/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx index c95220e200..60a67186db 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx @@ -8,6 +8,8 @@ import styled, { css } from 'styled-components/macro' import { TooltipContainer } from 'legacy/components/Tooltip' import { ThemedText } from 'legacy/theme' +import { UI } from 'common/constants/theme' + import { FeeInformationTooltipWrapper } from './FeeInformationTooltip' import { AutoColumn } from '../Column' @@ -30,7 +32,7 @@ export const ArrowWrapper = styled.div<{ clickable: boolean }>` margin-top: -14px; margin-bottom: -14px; left: 16px; - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); z-index: 2; ${({ clickable }) => clickable @@ -183,7 +185,7 @@ export const AuxInformationContainer = styled.div<{ showAux?: boolean }>` border: 1px solid ${({ theme, hideInput }) => (hideInput ? ' transparent' : theme.bg2)}; - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); width: ${({ hideInput }) => (hideInput ? '100%' : 'initial')}; :focus, diff --git a/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts b/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts index 6ca86f5fd9..069fb3cee5 100644 --- a/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts +++ b/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts @@ -6,6 +6,7 @@ import { isAddress } from '../../utils' type TagDetails = Tags[keyof Tags] export interface TagInfo extends TagDetails { id: string + icon?: string } /** * Token instances created from token info on a token list. diff --git a/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx b/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx index 546a74ea30..bee9e3bd97 100644 --- a/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx +++ b/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx @@ -1,4 +1,4 @@ -import { transparentize, lighten, darken } from 'polished' +import { transparentize, darken, lighten } from 'polished' import { createGlobalStyle, css } from 'styled-components/macro' import Cursor1 from 'legacy/assets/cow-swap/cursor1.gif' @@ -9,6 +9,8 @@ import { colorsUniswap } from 'legacy/theme/colorsUniswap' import { ButtonSize } from 'legacy/theme/enum' import { Colors } from 'legacy/theme/styled' +import { UI } from 'common/constants/theme' + // TODO: This shouldn't be in the base theme // Modal override items // import { HeaderText } from 'legacy/components/WalletModal/Option' @@ -387,45 +389,82 @@ export const UniFixedGlobalStyle = css` export const UniThemedGlobalStyle = css` :root { - // CSS Variables =============================== - // Colors - --cow-color-white: ${({ theme }) => theme.white}; - --cow-color-blue: ${({ theme }) => theme.blueDark2}; - --cow-color-border: ${({ theme }) => theme.grey1}; - --cow-color-lightBlue: ${({ theme }) => theme.information}; - --cow-color-lightBlue-opacity-90: ${({ theme }) => transparentize(0.1, theme.information)}; // 90% opacity - --cow-color-lightBlue-opacity-80: ${({ theme }) => transparentize(0.2, theme.information)}; // 80% opacity - --cow-color-yellow: ${({ theme }) => theme.alert}; - --cow-color-yellow-light: ${({ theme }) => theme.alert2}; - --cow-color-green: ${({ theme }) => theme.success}; - - // States - --cow-color-information: var(--cow-color-lightBlue); - --cow-color-information-bg: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.information) : transparentize(0.85, theme.information))}; - --cow-color-information-text: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.information) : darken(0.2, theme.information))}; - - --cow-color-alert: var(--cow-color-yellow); - --cow-color-alert-bg: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.alert) : transparentize(0.85, theme.alert))}; - --cow-color-alert-text: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.alert) : darken(0.2, theme.alert))}; - - --cow-color-alert2: var(--cow-color-yellow-light); - --cow-color-alert2-bg: var(--cow-color-alert2); - --cow-color-alert2-text: var(--cow-color-blue); - - --cow-color-success: var(--cow-color-green); - --cow-color-success-bg: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.success) : transparentize(0.85, theme.success))}; - --cow-color-success-text: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.success) : darken(0.1, theme.success))}; - + ${UI.COLOR_WHITE}: ${({ theme }) => theme.white}; + ${UI.COLOR_BLUE}: ${({ theme }) => theme.blueDark2}; + ${UI.COLOR_GREY}: ${({ theme }) => theme.grey1}; + ${UI.COLOR_LIGHT_BLUE}: ${({ theme }) => theme.blueLight1}; + ${UI.COLOR_LIGHT_BLUE_OPACITY_90}: ${({ theme }) => theme.information}; + ${UI.COLOR_LIGHT_BLUE_OPACITY_80}: ${({ theme }) => transparentize(0.2, theme.information)}; // 80% opacity + ${UI.COLOR_YELLOW}: ${({ theme }) => theme.alert}; + ${UI.COLOR_YELLOW_LIGHT}: ${({ theme }) => theme.alert2}; + ${UI.COLOR_GREEN}: ${({ theme }) => theme.success}; + ${UI.COLOR_RED}: ${({ theme }) => theme.danger}; + + // Base + ${UI.COLOR_BORDER}: var(${UI.COLOR_GREY}); + ${UI.COLOR_CONTAINER_BG_01}: ${({ theme }) => theme.bg1}; + ${UI.COLOR_CONTAINER_BG_02}: ${({ theme }) => theme.bg2}; + ${UI.MODAL_BACKDROP}: var(${UI.COLOR_TEXT1}); + ${UI.BORDER_RADIUS_NORMAL}: 24px; + ${UI.PADDING_NORMAL}: 24px; + ${UI.BOX_SHADOW_NORMAL}: 0 1.5rem 1rem #00000008,0 .75rem .75rem #0000000a,0 .25rem .375rem #0000000d; + + // Icons + ${UI.ICON_SIZE_NORMAL}: 24px; + ${UI.ICON_COLOR_NORMAL}: var(${UI.COLOR_TEXT1}); + + // [STATE] Information (light blue) + ${UI.COLOR_INFORMATION}: var(${UI.COLOR_LIGHT_BLUE}); + ${UI.COLOR_INFORMATION_BG}: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.information) : transparentize(0.85, theme.information))}; + ${UI.COLOR_INFORMATION_TEXT}: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.information) : darken(0.2, theme.information))}; + + // [STATE] Alert (yellow) + ${UI.COLOR_ALERT}: var(${UI.COLOR_YELLOW}); + ${UI.COLOR_ALERT_BG}: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.alert) : transparentize(0.85, theme.alert))}; + ${UI.COLOR_ALERT_TEXT}: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.alert) : darken(0.2, theme.alert))}; + + // [STATE] Alert2 (yellow lighter) + ${UI.COLOR_ALERT2}: var(${UI.COLOR_YELLOW_LIGHT}); + ${UI.COLOR_ALERT2_BG}: var(${UI.COLOR_YELLOW_LIGHT}); + ${UI.COLOR_ALERT2_TEXT}: var(${UI.COLOR_BLUE}); + + // [STATE] Success (green) + ${UI.COLOR_SUCCESS}: var(${UI.COLOR_GREEN}); + ${UI.COLOR_SUCCESS_BG}: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.success) : transparentize(0.85, theme.success))}; + ${UI.COLOR_SUCCESS_TEXT}: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.success) : darken(0.1, theme.success))}; + + + // [STATE] Danger (red) + ${UI.COLOR_DANGER}: var(${UI.COLOR_RED}); + ${UI.COLOR_DANGER_BG}: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.danger) : transparentize(0.85, theme.danger))}; + ${UI.COLOR_DANGER_TEXT}: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.danger) : darken(0.2, theme.danger))}; + // Text - --cow-color-text1: ${({ theme }) => theme.text1}; - --cow-color-text1-inactive: ${({ theme }) => transparentize(0.4, theme.text1)}; - --cow-color-text1-opacity-25: ${({ theme }) => transparentize(0.75, theme.text1)}; + ${UI.COLOR_TEXT1}: ${({ theme }) => theme.text1}; + ${UI.COLOR_TEXT1_INACTIVE}: ${({ theme }) => transparentize(0.4, theme.text1)}; + ${UI.COLOR_TEXT1_OPACITY_25}: ${({ theme }) => transparentize(0.75, theme.text1)}; + ${UI.COLOR_TEXT1_OPACITY_10}: ${({ theme }) => transparentize(0.9, theme.text1)}; + ${UI.COLOR_TEXT2}: ${({ theme }) => transparentize(0.3, theme.text1)}; + ${UI.COLOR_LINK}: ${({ theme }) => theme.text3}; + ${UI.COLOR_LINK_OPACITY_10}: ${({ theme }) => transparentize(0.9, theme.text3)}; + + // Font Weights & Sizes + ${UI.FONT_WEIGHT_NORMAL}: 400; + ${UI.FONT_WEIGHT_MEDIUM}: 500; + ${UI.FONT_WEIGHT_BOLD}: 600; + ${UI.FONT_SIZE_SMALLER}: 10px; + ${UI.FONT_SIZE_SMALL}: 12px; + ${UI.FONT_SIZE_NORMAL}: 14px; + ${UI.FONT_SIZE_MEDIUM}: 16px; + ${UI.FONT_SIZE_LARGE}: 18px; + ${UI.FONT_SIZE_LARGER}: 20px; + ${UI.FONT_SIZE_LARGEST}: 24px; } html { - color: ${({ theme }) => theme.text1}; - background-color: ${({ theme }) => theme.bg2}; + color: var(${UI.COLOR_TEXT1}); + background-color: var(${UI.COLOR_CONTAINER_BG_02}) } body { min-height: 100vh; @@ -443,7 +482,7 @@ export const ThemedGlobalStyle = createGlobalStyle` ${UniThemedGlobalStyle} html { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ${({ theme }) => theme.body.background} } @@ -457,8 +496,8 @@ export const ThemedGlobalStyle = createGlobalStyle` } ::selection { - background: ${({ theme }) => theme.bg2}; - color: ${({ theme }) => theme.white}; + background: var(${UI.COLOR_CONTAINER_BG_02}); + color: var(${UI.COLOR_WHITE}); } // TODO: Can be removed once we control this component diff --git a/apps/cowswap-frontend/src/legacy/theme/components.tsx b/apps/cowswap-frontend/src/legacy/theme/components.tsx index fb1e72b95b..3b1b36f7af 100644 --- a/apps/cowswap-frontend/src/legacy/theme/components.tsx +++ b/apps/cowswap-frontend/src/legacy/theme/components.tsx @@ -7,6 +7,8 @@ import styled, { keyframes } from 'styled-components/macro' import { externalLinkAnalytics, outboundLink } from 'legacy/components/analytics' import { anonymizeLink } from 'legacy/utils/anonymizeLink' +import { UI } from 'common/constants/theme' + export const ButtonText = styled.button` outline: none; border: none; @@ -250,7 +252,7 @@ export const Spinner = styled.img` ` const BackArrowLink = styled(StyledInternalLink)` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ` export function BackArrow({ to }: { to: string }) { return ( diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx index 71afd9cda3..e1792c5d96 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx @@ -6,11 +6,13 @@ import { ExternalLink } from 'legacy/theme' import { useUsdAmount } from 'modules/usdAmount' +import { UI } from 'common/constants/theme' import { FiatAmount } from 'common/pure/FiatAmount' import { TokenAmount } from 'common/pure/TokenAmount' import { useTotalSurplus } from 'common/state/totalSurplusState' import useNativeCurrency from 'lib/hooks/useNativeCurrency' + import { InfoCard } from './styled' export function SurplusCard() { @@ -90,7 +92,7 @@ export function SurplusCard() { } ${InfoCard} > div > span > p { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ${InfoCard} > div > span > b { diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts index 5130334565..158dee73d6 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts +++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts @@ -7,6 +7,8 @@ import { CopyIcon, TransactionStatusText } from 'legacy/components/Copy' import { QuestionWrapper } from 'legacy/components/QuestionHelper' import { ExternalLink, StyledLink } from 'legacy/theme' +import { UI } from 'common/constants/theme' + import { StatusLabelWrapper, Summary, @@ -82,7 +84,7 @@ export const AddressLink = styled(ExternalLink)<{ hasENS: boolean; isENS: boolea font-size: 0.825rem; display: flex; :hover { - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); } ` @@ -127,7 +129,7 @@ export const WalletNameAddress = styled.div` export const Wrapper = styled.div` display: block; width: 100%; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); padding: 0; height: 100%; margin: 0 24px; @@ -141,7 +143,7 @@ export const Wrapper = styled.div` ${AddressLink}, ${CopyIcon}, ${WalletAction} { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); opacity: 0.85; transition: color 0.2s ease-in-out, opacity 0.2s ease-in-out; margin: auto; @@ -168,7 +170,7 @@ export const Wrapper = styled.div` margin: 0 0 0 8px; align-self: center; font-size: 21px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ${WalletName} { @@ -266,7 +268,7 @@ export const InfoCard = styled.div` justify-content: space-between; border-radius: 16px; padding: 24px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); &:not(:first-child) { margin: 24px 0; @@ -282,7 +284,7 @@ export const InfoCard = styled.div` ` export const AccountSection = styled.div` - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); padding: 0; ${({ theme }) => theme.mediaWidth.upToMedium`padding: 0;`}; ` @@ -290,7 +292,7 @@ export const AccountSection = styled.div` export const AccountGroupingRow = styled.div` justify-content: space-between; align-items: center; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); div { ${({ theme }) => theme.flexRowNoWrap} @@ -312,7 +314,7 @@ export const AccountGroupingRow = styled.div` export const NoActivityMessage = styled.p` font-size: 14px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); width: 100%; padding: 24px 0 0; text-align: center; @@ -329,7 +331,7 @@ export const LowerSection = styled.div` > span { display: flex; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); justify-content: space-between; padding: 0 0 12px; @@ -367,7 +369,7 @@ export const LowerSection = styled.div` } > span > ${StyledLink} { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); text-decoration: underline; font-size: 14px; @@ -448,8 +450,8 @@ const NetworkCardUni = styled(YellowCard)` ` export const NetworkCard = styled(NetworkCardUni)` - background-color: ${({ theme }) => theme.bg1}; - color: ${({ theme }) => theme.text1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1}); padding: 6px 8px; font-size: 13px; margin: 0; @@ -532,7 +534,7 @@ export const SurplusCardWrapper = styled.div` } ${InfoCard} > div > span > p { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ${InfoCard} > div > span > b { @@ -584,7 +586,7 @@ export const WalletIconWrapper = styled.div` } > svg > path { - --color: var(--cow-color-text1); + --color: var(${UI.COLOR_TEXT1}); fill: var(--color); stroke: var(--color); stroke-width: 0.5px; @@ -607,7 +609,7 @@ export const WalletSelector = styled.div` isHardWareWallet && ` cursor: pointer; - border: 1px solid var(--cow-color-text1-opacity-25); + border: 1px solid var(${UI.COLOR_TEXT1_OPACITY_25}); background: transparent; padding: 6px 10px; @@ -618,14 +620,14 @@ export const WalletSelector = styled.div` height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; - border-top: 4px solid var(--cow-color-text1); + border-top: 4px solid var(${UI.COLOR_TEXT1}); margin-left: 8px; opacity: 0.5; transition: opacity 0.2s ease-in-out; } &:hover { - background: var(--cow-color-text1-opacity-25); + background: var(${UI.COLOR_TEXT1_OPACITY_25}); } &:hover::after { diff --git a/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx index 3917bfd50f..c16a7c4b6c 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx @@ -8,6 +8,7 @@ import { useToggleWalletModal } from 'legacy/state/application/hooks' import { toggleAccountSelectorModalAtom, useWalletDetails, useWalletInfo } from 'modules/wallet' +import { UI } from 'common/constants/theme' import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity' import { AccountDetails } from '../AccountDetails' @@ -32,7 +33,7 @@ const SideBar = styled.div` cursor: default; overflow-y: hidden; box-shadow: ${({ theme }) => theme.boxShadow1}; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); ${({ theme }) => theme.mediaWidth.upToMedium` width: 100%; @@ -64,8 +65,8 @@ const Header = styled.div` padding: 20px 30px; align-items: center; transition: opacity 0.2s ease-in-out; - color: ${({ theme }) => theme.text1}; - background: ${({ theme }) => theme.bg1}; + color: var(${UI.COLOR_TEXT1}); + background: var(${UI.COLOR_CONTAINER_BG_01}); position: sticky; top: 0; left: 0; @@ -79,7 +80,7 @@ const Header = styled.div` position: sticky; left: 0; height: 52px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); `}; &:hover { @@ -100,7 +101,7 @@ const Header = styled.div` const CloseIcon = styled(Close)` opacity: 0.6; transition: opacity 0.3s ease-in-out; - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); width: 24px; height: 24px; diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts b/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts index b490e65c95..71f4752e66 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts +++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts @@ -5,6 +5,7 @@ import { StyledSVG } from 'legacy/components/Loader' import { RowFixed } from 'legacy/components/Row' import { ExternalLink, LinkStyledButton, StyledLink } from 'legacy/theme' +import { UI } from 'common/constants/theme' import { StyledLogo } from 'common/pure/CurrencyLogo' import { FiatAmount } from 'common/pure/FiatAmount' import { RateWrapper } from 'common/pure/RateInfo' @@ -88,7 +89,7 @@ export const Summary = styled.div` padding: 22px; grid-template-rows: 1fr; grid-template-columns: 80px auto min-content; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ${({ theme }) => theme.mediaWidth.upToSmall` display: flex; @@ -152,7 +153,7 @@ export const SummaryInner = styled.div` } > a { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); text-decoration: underline; font-size: 14px; @@ -345,12 +346,12 @@ export const StatusLabelBelow = styled.div<{ isCancelling?: boolean }>` font-size: 12px; line-height: 1.1; margin: 7px auto 0; - color: ${({ isCancelling, theme }) => (isCancelling ? theme.text1 : 'inherit')}; + color: ${({ isCancelling }) => (isCancelling ? `var(${UI.COLOR_TEXT1})` : 'inherit')}; > ${LinkStyledButton} { margin: 2px 0; opacity: 1; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ` @@ -396,7 +397,7 @@ export const CancellationSummary = styled.span` padding: 12px; margin: 0; border-radius: 6px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); ` export const TransactionInnerDetail = styled.div` @@ -404,7 +405,7 @@ export const TransactionInnerDetail = styled.div` flex-flow: column wrap; border-radius: 12px; padding: 20px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); margin: 24px auto 0 0; border: 1px solid ${({ theme }) => theme.card.border}; diff --git a/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/styled.ts b/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/styled.ts index 7bbd4a0e52..660e51fe25 100644 --- a/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/styled.ts +++ b/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/styled.ts @@ -2,22 +2,24 @@ import { transparentize } from 'polished' import { NavLink } from 'react-router-dom' import styled, { css } from 'styled-components/macro' +import { UI } from 'common/constants/theme' + import { BadgeType } from '.' const badgeBackgrounds: Record = { - information: 'var(--cow-color-information-bg)', - alert: 'var(--cow-color-alert-bg)', - alert2: 'var(--cow-color-alert2-bg)', - success: 'var(--cow-color-success-bg)', + information: `var(${UI.COLOR_INFORMATION_BG})`, + alert: `var(${UI.COLOR_ALERT_BG})`, + alert2: `var(${UI.COLOR_ALERT2_BG})`, + success: `var(${UI.COLOR_SUCCESS_BG})`, default: 'transparent', // text only }; const badgeColors: Record = { - information: 'var(--cow-color-information-text)', - alert: 'var(--cow-color-alert-text)', - alert2: 'var(--cow-color-alert2-text)', - success: 'var(--cow-color-success-text)', - default: 'var(--cow-color-text1-inactive)', // text only + information: `var(${UI.COLOR_INFORMATION_TEXT})`, + alert: `var(${UI.COLOR_ALERT_TEXT})`, + alert2: `var(${UI.COLOR_ALERT2_TEXT})`, + success: `var(${UI.COLOR_SUCCESS_TEXT})`, + default: `var(${UI.COLOR_TEXT1_INACTIVE})`, // text only }; export const Badge = styled.div<{ type?: BadgeType }>` @@ -82,13 +84,13 @@ export const MenuItem = styled.div<{ isActive?: boolean }>` background: transparent; transition: background 0.2 ease-in-out; - ${({ isActive, theme }) => + ${({ isActive }) => isActive && css` - background: ${theme.grey1}; + background: var(${UI.COLOR_GREY}); ${Link} { - color: ${theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ${Link} > ${Badge} { diff --git a/apps/cowswap-frontend/src/modules/application/pure/Page/index.tsx b/apps/cowswap-frontend/src/modules/application/pure/Page/index.tsx index 72dda63979..e57911bff9 100644 --- a/apps/cowswap-frontend/src/modules/application/pure/Page/index.tsx +++ b/apps/cowswap-frontend/src/modules/application/pure/Page/index.tsx @@ -7,6 +7,8 @@ import { WithClassName } from 'legacy/types' import { Widget } from 'modules/application/pure/Widget' +import { UI } from 'common/constants/theme' + export const PageWrapper = styled(Widget)` padding: 0 24px 24px; max-width: ${({ theme }) => theme.appBody.maxWidth.content}; @@ -16,7 +18,7 @@ export const PageWrapper = styled(Widget)` export const Title = styled.h1` font-size: 32px; margin: 24px 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); text-shadow: ${({ theme }) => theme.textShadow1}; font-weight: 500; @@ -170,7 +172,7 @@ export const GdocsListStyle = css` ol { margin: 24px 0; padding: 12px 48px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 12px; > li { diff --git a/apps/cowswap-frontend/src/modules/application/pure/Widget/index.tsx b/apps/cowswap-frontend/src/modules/application/pure/Widget/index.tsx index bc476793c1..42bd2a222a 100644 --- a/apps/cowswap-frontend/src/modules/application/pure/Widget/index.tsx +++ b/apps/cowswap-frontend/src/modules/application/pure/Widget/index.tsx @@ -2,8 +2,10 @@ import styled from 'styled-components/macro' import { BodyWrapper as BodyWrapperMod } from 'legacy/pages/AppBody' +import { UI } from 'common/constants/theme' + const Wrapper = styled(BodyWrapperMod)` - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border: 0; border-radius: 16px; box-shadow: ${({ theme }) => theme.boxShadow1}; diff --git a/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx b/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx index b37ccdba8e..4b86b52fff 100644 --- a/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx @@ -22,6 +22,7 @@ import { updateOpenFortuneAtom, } from 'modules/fortune/state/fortuneStateAtom' +import { UI } from 'common/constants/theme' import useInterval from 'lib/hooks/useInterval' import { SuccessBanner } from 'pages/Claim/styled' @@ -119,7 +120,7 @@ const FortuneBanner = styled.div` left: 0; bottom: 0; z-index: 501; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); padding: 0; animation: open 0.3s ease-in-out forwards; overflow: hidden; @@ -182,7 +183,7 @@ const FortuneTitle = styled.h2` font-size: 21px; text-align: center; font-weight: 700; - color: ${({ theme }) => theme.text2}; + color: var(${UI.COLOR_TEXT2}); > i { font-size: 16px; @@ -226,7 +227,7 @@ const FortuneText = styled.h3` &:before, &:after { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: 100px; position: absolute; z-index: 1; @@ -242,11 +243,11 @@ const FortuneContent = styled.div` align-items: center; width: 100%; max-width: 500px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ` const StyledExternalLink = styled(ExternalLink)` - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 24px; ` @@ -255,7 +256,7 @@ const HeaderElement = styled.div` align-items: center; justify-content: space-between; width: 100%; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); position: fixed; padding: 0 16px; top: 0; @@ -282,7 +283,7 @@ const StyledCloseIcon = styled(X)` } > line { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts b/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts index 170eee1146..866f62721d 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts @@ -4,8 +4,10 @@ import styled from 'styled-components/macro' import Loader from 'legacy/components/Loader' import Input from 'legacy/components/NumericalInput' +import { UI } from 'common/constants/theme' + export const Wrapper = styled.div` - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 16px; padding: 10px 16px; flex: 1 1 70%; @@ -30,8 +32,8 @@ export const Header = styled.div` ` export const MarketPriceButton = styled.button` - background: ${({ theme }) => theme.bg1}; - color: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1}); white-space: nowrap; border: none; font-weight: 500; @@ -82,7 +84,7 @@ export const ActiveCurrency = styled.button` ` export const ActiveSymbol = styled.span` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: 13px; font-weight: 500; text-align: right; @@ -91,8 +93,8 @@ export const ActiveSymbol = styled.span` export const ActiveIcon = styled.div` --size: 20px; - background-color: ${({ theme }) => theme.bg1}; - color: ${({ theme }) => theme.text1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1}); width: var(--size); min-width: var(--size); height: var(--size); @@ -117,7 +119,7 @@ export const EstimatedRate = styled.div` font-size: 13px; border-radius: 0 0 16px 16px; font-weight: 400; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border: 2px solid ${({ theme }) => theme.grey1}; > b { diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/styled.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/styled.tsx index 6c89ca55be..28a6f9e1ef 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/styled.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/styled.tsx @@ -3,8 +3,10 @@ import { transparentize } from 'polished' import { X } from 'react-feather' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const Wrapper = styled.div<{ inline?: boolean; minHeight?: string }>` - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 16px; padding: 10px 16px; min-height: ${({ minHeight }) => minHeight || '80px'}; @@ -38,7 +40,7 @@ export const Label = styled.span` ` export const Current = styled(MenuButton)<{ $custom?: boolean }>` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: ${({ $custom }) => ($custom ? '12px' : '100%')}; letter-spacing: ${({ $custom }) => ($custom ? '-0.3px' : '0')}; font-weight: 500; @@ -75,7 +77,7 @@ export const Current = styled(MenuButton)<{ $custom?: boolean }>` export const ListWrapper = styled(MenuList)` display: block; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); box-shadow: ${({ theme }) => theme.boxShadow2}; margin: 15px 0 0 0; padding: 10px 15px; @@ -88,7 +90,7 @@ export const ListWrapper = styled(MenuList)` ` export const ListItem = styled(MenuItem)` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); background: none; border: 0; outline: none; @@ -111,17 +113,17 @@ export const CustomInput = styled.input` border-radius: 8px; width: 100%; border: 1px solid ${({ theme }) => transparentize(0.7, theme.text1)}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); padding: 4px 8px; outline: 0; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); &::-webkit-calendar-picker-indicator { filter: ${({ theme }) => (theme.darkMode ? 'invert(1)' : 'invert(0)')}; } &::-webkit-datetime-edit { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } &::-webkit-datetime-edit[disabled] { @@ -177,7 +179,7 @@ export const ModalContent = styled.div` align-items: flex-start; justify-content: center; padding: 16px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 12px; ` @@ -193,6 +195,6 @@ export const CloseIcon = styled(X)` } > line { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/styled.ts b/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/styled.ts index beea28b1ad..fa195df8dd 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/styled.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/styled.ts @@ -1,12 +1,14 @@ import { transparentize } from 'polished' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const FeeTooltipWrapper = styled.div` display: flex; flex-flow: column wrap; align-items: center; justify-content: center; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ` export const FeeItem = styled.div<{ highlighted?: boolean; borderTop?: boolean }>` diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/styled.ts b/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/styled.ts index fe70965313..8c51cd42aa 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/styled.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/styled.ts @@ -2,6 +2,8 @@ import { transparentize, lighten } from 'polished' import { X } from 'react-feather' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const InfoPopup = styled.div` display: flex; position: relative; @@ -34,7 +36,7 @@ export const InfoPopup = styled.div` } .content > a { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); text-decoration: underline; &::after { diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx index 91644315f6..f7aa0ceb4f 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx @@ -20,6 +20,7 @@ import { calculateLimitOrdersDeadline } from 'modules/limitOrders/utils/calculat import { ordersTableFeatures } from 'common/constants/featureFlags' import { DEFAULT_DATE_FORMAT } from 'common/constants/intl' +import { UI } from 'common/constants/theme' import { ExecutionPrice } from 'common/pure/ExecutionPrice' import { RateInfoParams } from 'common/pure/RateInfo' import { formatInputAmount } from 'utils/amountFormat' @@ -29,7 +30,7 @@ import * as styledEl from './styled' const Wrapper = styled.div` font-size: 13px; font-weight: 400; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); padding: 8px; ` @@ -37,7 +38,7 @@ const ArrowDownRight = styled.div` display: flex; opacity: 0.3; margin: 0 3px 0 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ` export interface LimitOrdersDetailsProps { rateInfoParams: RateInfoParams diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/styled.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/styled.tsx index 4d77475eab..5cb898a3ef 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/styled.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/styled.tsx @@ -2,6 +2,7 @@ import styled from 'styled-components/macro' import { QuestionWrapper } from 'legacy/components/QuestionHelper' +import { UI } from 'common/constants/theme' import { RateInfo } from 'common/pure/RateInfo' export const DetailsRow = styled.div` @@ -41,7 +42,7 @@ export const DetailsRow = styled.div` export const StyledRateInfo = styled(RateInfo)` font-size: 13px; font-weight: 400; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); min-height: 24px; gap: 3px; ` diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/styled.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/styled.tsx index 7bc48d569f..1360ee5f78 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/styled.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/styled.tsx @@ -3,12 +3,14 @@ import { transparentize } from 'polished' import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const Wrapper = styled.div` position: relative; ` export const LabelText = styled.span` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); transition: color 0.15s ease-in-out; ` @@ -19,7 +21,7 @@ export const StyledSVG = styled(SVG)` height: var(--size); > path { - fill: ${({ theme }) => theme.text1}; + fill: var(${UI.COLOR_TEXT1}); transition: fill 0.15s ease-in-out; } @@ -54,7 +56,7 @@ export const StyledMenuButton = styled(MenuButton)` export const StyledMenuList = styled(MenuList)` box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.95, theme.shadow1)}; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border-radius: 8px; z-index: 2; min-width: 100%; @@ -67,7 +69,7 @@ export const StyledMenuList = styled(MenuList)` export const StyledMenuItem = styled(MenuItem)` padding: 6px 12px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: 13px; cursor: pointer; border-radius: 8px; diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx index c6eef7184d..aa10f40114 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx @@ -7,6 +7,7 @@ import { MouseoverTooltipContent } from 'legacy/components/Tooltip' import { LOW_RATE_THRESHOLD_PERCENT } from 'modules/limitOrders/const/trade' +import { UI } from 'common/constants/theme' import { TokenSymbol } from 'common/pure/TokenSymbol' interface RateImpactProps { @@ -21,8 +22,8 @@ const PercentBox = styled.span<{ isPositive: boolean; isTooLowRate: boolean }>` display: inline-flex; align-items: center; gap: 2px; - color: ${({ isPositive, isTooLowRate, theme }) => - isPositive ? theme.success : isTooLowRate ? theme.danger : theme.text1}; + color: ${({ isPositive, isTooLowRate }) => + isPositive ? `var(${UI.COLOR_SUCCESS})` : isTooLowRate ? `var(${UI.COLOR_DANGER})` : `var(${UI.COLOR_TEXT1})`}; ` const ImpactTooltip = styled.span` display: block; diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx index 3a831ed7fc..fb62d0415c 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx @@ -6,6 +6,7 @@ import styled from 'styled-components/macro' import { LOW_RATE_THRESHOLD_PERCENT } from 'modules/limitOrders/const/trade' +import { UI } from 'common/constants/theme' import { TokenSymbol } from 'common/pure/TokenSymbol' interface RateImpactAcknowledge { @@ -41,7 +42,7 @@ const ReadMoreLink = styled.a` text-decoration: underline; &:hover { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts index aea0048814..96535ebbba 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts @@ -1,10 +1,12 @@ import { transparentize } from 'polished' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const SettingsTitle = styled.h3` font-weight: 600; font-size: 14px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); margin: 0 0 12px 0; ` @@ -14,8 +16,8 @@ export const SettingsContainer = styled.div` border-radius: 12px; box-shadow: ${({ theme }) => theme.boxShadow2}; border: 1px solid ${({ theme }) => transparentize(0.95, theme.white)}; - background: ${({ theme }) => theme.bg1}; - color: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1}); ` export const SettingsBox = styled.div<{ disabled: boolean }>` @@ -35,7 +37,7 @@ export const SettingsBoxTitle = styled.div` display: flex; align-items: center; font-weight: 400; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: 14px; opacity: 0.85; margin-right: 2rem; diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx index cb738c2a21..1c76ec5bc4 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx @@ -7,6 +7,7 @@ import styled from 'styled-components/macro' import { useWalletDetails } from 'modules/wallet' +import { UI } from 'common/constants/theme' import { useMultipleOrdersCancellation } from 'common/hooks/useMultipleOrdersCancellation' import { ordersToCancelAtom, updateOrdersToCancelAtom } from 'common/hooks/useMultipleOrdersCancellation/state' import { isOrderOffChainCancellable } from 'common/utils/isOrderOffChainCancellable' @@ -61,7 +62,7 @@ const ActionButton = styled.button` const TextButton = styled.button` display: inline-block; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: 13px; padding: 5px 10px; cursor: pointer; diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderContextMenu.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderContextMenu.tsx index 08f2b3c49d..2ebd2ab942 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderContextMenu.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/OrderContextMenu.tsx @@ -5,6 +5,8 @@ import { transparentize } from 'polished' import { FileText, Link2, MoreVertical, Trash2 } from 'react-feather' import styled, { ThemeContext } from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const ContextMenuButton = styled(MenuButton)` background: none; border: 0; @@ -26,7 +28,7 @@ export const ContextMenuButton = styled(MenuButton)` } ` export const ContextMenuList = styled(MenuList)` - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border-radius: 12px; overflow: hidden; position: relative; @@ -47,7 +49,7 @@ export const ContextMenuItem = styled(MenuItem)<{ $red?: boolean }>` align-items: center; font-size: 15px; font-weight: 500; - color: ${({ theme, $red }) => ($red ? theme.danger : theme.text1)}; + color: ${({ theme, $red }) => ($red ? `var(${UI.COLOR_DANGER})` : theme.text1)}; &:hover { background: ${({ theme }) => transparentize(0.8, theme.text3)}; diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx index c2fa958234..ec9f87962c 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx @@ -1,6 +1,7 @@ import { transparentize } from 'polished' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' import { RateWrapper } from 'common/pure/RateInfo' export const WarningIndicator = styled.button<{ hasBackground?: boolean }>` @@ -285,7 +286,7 @@ export const ToggleExpandButton = styled.div<{ isCollapsed?: boolean }>` margin: 0 0 0 6px; cursor: pointer; outline: none; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); transition: color 0.2s ease-out; position: relative; height: var(--height); diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx index 4e34e84f23..59da992d15 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx @@ -27,6 +27,7 @@ import { OrderActions } from 'modules/ordersTable/pure/OrdersTableContainer/type import { BalancesAndAllowances } from 'modules/tokens' import { ordersTableFeatures } from 'common/constants/featureFlags' +import { UI } from 'common/constants/theme' import { OrderExecutionStatusList, RateTooltipHeader } from 'common/pure/OrderExecutionStatusList' import { InvertRateControl } from 'common/pure/RateInfo' import { CancellableOrder } from 'common/utils/isOrderCancellable' @@ -150,7 +151,7 @@ const StyledCloseIcon = styled(X)` } > line { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx index e4519ba642..e5e7519a93 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTablePagination.tsx @@ -2,6 +2,8 @@ import { transparentize } from 'polished' import { Link } from 'react-router-dom' import styled, { css } from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export interface OrdersTablePaginationProps { getPageUrl?(index: number): Partial<{ pathname: string; search: string }> onPageChange?(index: number): void @@ -28,7 +30,7 @@ const PaginationBox = styled.div` const pageButtonStyles = css<{ $active?: boolean }>` background: ${({ theme, $active }) => ($active ? transparentize(0.9, theme.text3) : 'transparent')}; - color: ${({ theme, $active }) => ($active ? theme.text1 : transparentize(0.2, theme.text1))}; + color: ${({ theme, $active }) => ($active ? `var(${UI.COLOR_TEXT1})` : transparentize(0.2, theme.text1))}; border: 0; outline: 0; padding: 5px 10px; @@ -39,8 +41,8 @@ const pageButtonStyles = css<{ $active?: boolean }>` text-decoration: none; &:hover { - background: ${({ theme }) => theme.bg1}; - color: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTabs.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTabs.tsx index 0b228fe113..b12867c0bf 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTabs.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTabs.tsx @@ -5,6 +5,8 @@ import styled from 'styled-components/macro' import { buildOrdersTableUrl } from 'modules/ordersTable/utils/buildOrdersTableUrl' +import { UI } from 'common/constants/theme' + import { OrderTab } from '../../const/tabs' const Tabs = styled.div` @@ -24,7 +26,7 @@ const Tabs = styled.div` const TabButton = styled(Link)<{ active: string }>` display: inline-block; background: ${({ theme, active }) => (active === 'true' ? transparentize(0.88, theme.text3) : 'transparent')}; - color: ${({ theme, active }) => (active === 'true' ? theme.text1 : transparentize(0.2, theme.text1))}; + color: ${({ theme, active }) => (active === 'true' ? `var(${UI.COLOR_TEXT1})` : transparentize(0.2, theme.text1))}; font-weight: ${({ active }) => (active === 'true' ? '600' : '400')}; text-decoration: none; font-size: 13px; @@ -39,8 +41,8 @@ const TabButton = styled(Link)<{ active: string }>` `}; &:hover { - background: ${({ theme }) => theme.bg1}; - color: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/styled.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/styled.tsx index bfa9c7de84..bc97fc4c2a 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/styled.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/styled.tsx @@ -1,6 +1,7 @@ import { transparentize } from 'polished' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' import { RateWrapper } from 'common/pure/RateInfo' export const TableHeader = styled.div<{ isOpenOrdersTab: boolean; isRowSelectable: boolean }>` @@ -118,7 +119,7 @@ export const TableRowCheckbox = styled.input` outline: 0; &:checked { - background-color: ${({ theme }) => theme.text1}; + background-color: var(${UI.COLOR_TEXT1}); } &:checked + ${CheckboxCheckmark}::after { @@ -126,7 +127,7 @@ export const TableRowCheckbox = styled.input` } &:indeterminate { - border-color: ${({ theme }) => theme.text1}; + border-color: var(${UI.COLOR_TEXT1}); } &:indeterminate + ${CheckboxCheckmark}::after { diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts index 836c5be695..6f92e99b9d 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts @@ -2,8 +2,10 @@ import styled from 'styled-components/macro' import { AutoRow } from 'legacy/components/Row' +import { UI } from 'common/constants/theme' + export const Wrapper = styled.div` - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); width: 100%; margin: 0 0 14px; overflow-y: auto; @@ -24,7 +26,7 @@ export const Header = styled.div` justify-content: space-between; align-items: center; padding: 0 16px 16px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); position: sticky; top: 0; left: 0; @@ -69,7 +71,7 @@ export const Field = styled.div` justify-content: space-between; align-items: center; padding: 12px 16px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); width: 100%; font-size: 13px; @@ -88,7 +90,7 @@ export const CurrencyField = styled.div` flex-direction: column; align-items: flex-start; padding: 16px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); width: 100%; border-radius: 16px; margin: 0 0 10px; diff --git a/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx index 603d9a73f7..6508b41056 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx @@ -10,15 +10,17 @@ import useCowBalanceAndSubsidy from 'legacy/hooks/useCowBalanceAndSubsidy' import { StyledInfoIcon } from 'modules/swap/pure/styled' import { LowerSectionWrapper } from 'modules/swap/pure/styled' +import { UI } from 'common/constants/theme' + interface FeesDiscountProps extends BoxProps { theme: DefaultTheme } const DarkSpan = styled.span` padding: 2px 8px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 5px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); transition: background 0.2s ease-in-out, color 0.2s ease-in-out; &:hover { diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts index 99a597f61b..b6c635fe47 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts @@ -3,6 +3,8 @@ import styled from 'styled-components/macro' import { ButtonPrimary } from 'legacy/components/Button' +import { UI } from 'common/constants/theme' + export const BannerWrapper = styled.div` display: flex; flex-flow: column wrap; @@ -36,7 +38,7 @@ export const ClosedBannerWrapper = styled.div` cursor: pointer; > path { - fill: ${({ theme }) => theme.text1}; + fill: var(${UI.COLOR_TEXT1}); } } @@ -45,7 +47,7 @@ export const ClosedBannerWrapper = styled.div` } &:hover > svg:last-child { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent.tsx index be5dba945a..fc0d0a5445 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent.tsx @@ -4,6 +4,8 @@ import styled from 'styled-components/macro' import { EthFlowState } from 'modules/swap/services/ethFlow/types' +import { UI } from 'common/constants/theme' + const ModalMessage = styled.div` display: flex; flex-flow: row wrap; @@ -25,7 +27,7 @@ const ModalMessage = styled.div` const LowBalanceMessage = styled(ModalMessage)` margin: 0 0 10px; background: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.alert) : transparentize(0.85, theme.alert))}; - color: ${({ theme }) => (theme.darkMode ? theme.alert : darken(0.2, theme.alert))}; + color: ${({ theme }) => (theme.darkMode ? `var(${UI.COLOR_ALERT})` : darken(0.2, theme.alert))}; padding: 16px; border-radius: 16px; width: 100%; diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.tsx index 85f7e02e7c..543dcf6803 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.tsx @@ -3,6 +3,8 @@ import React from 'react' import { transparentize } from 'polished' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + import { StatusIconState } from './StatusIcon' import { Progress1 } from './steps/Progress1' import { Progress2 } from './steps/Progress2' @@ -72,7 +74,7 @@ const Wrapper = styled.div` width: 100%; padding: 22px; border-radius: 0 0 12px 12px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); font-size: 15px; line-height: 1; @@ -117,7 +119,7 @@ export const Progress = styled.div` transition: width 0.3s ease-in-out, background 0.2s ease-in-out; width: ${({ value }) => (value ? `${value}%` : '0%')}; background: ${({ status, theme }) => - status === 'error' ? theme.danger : status === 'success' ? theme.success : theme.text3}; + status === 'error' ? `var(${UI.COLOR_DANGER})` : status === 'success' ? `var(${UI.COLOR_SUCCESS})` : theme.text3}; border-radius: var(--height); ${({ theme }) => theme.mediaWidth.upToSmall` diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx index d7b5871985..e89d8047e6 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx @@ -7,11 +7,13 @@ import Exclamation from 'legacy/assets/cow-swap/exclamation.svg' import Finish from 'legacy/assets/cow-swap/finish.svg' import Refund from 'legacy/assets/cow-swap/refund.svg' +import { UI } from 'common/constants/theme' + import { EthFlowStepperProps, SmartOrderStatus } from '..' import { Step, StepProps, ExplorerLinkStyled } from '../Step' const RefundMessage = styled.span` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-weight: 500; ` diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/styled.tsx index 93b00ba3cf..e85f4b6ab5 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/styled.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/styled.tsx @@ -1,5 +1,7 @@ import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const WrapCardWrapper = styled.div` ${({ theme }) => theme.flexColumnNoWrap} align-items: center; @@ -38,14 +40,14 @@ export const WrappingPreviewContainer = styled.div` border: 1px solid ${({ theme }) => theme.bg3}; &:nth-of-type(1) { - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); border-radius: 16px 0 0 16px; border-right: 0; } &:nth-of-type(2) { - color: ${({ theme }) => theme.text1}; - background-color: ${({ theme }) => theme.grey1}; + color: var(${UI.COLOR_TEXT1}); + background-color: var(${UI.COLOR_GREY}); border: 1px solid ${({ theme }) => theme.grey1}; border-radius: 0 16px 16px 0; } @@ -65,8 +67,8 @@ export const WrappingPreviewContainer = styled.div` bottom: 0; right: 0; margin: auto; - background: ${({ theme }) => theme.grey1}; - stroke: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_GREY}); + stroke: var(${UI.COLOR_TEXT1}); width: 32px; height: 32px; border-radius: 32px; diff --git a/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmount/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmount/styled.tsx index 40319ea55e..94a7f7b9a4 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmount/styled.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmount/styled.tsx @@ -2,6 +2,8 @@ import styled from 'styled-components/macro' import QuestionHelper from 'legacy/components/QuestionHelper' +import { UI } from 'common/constants/theme' + export const ReceiveAmountBox = styled.div` display: flex; justify-content: space-between; @@ -9,7 +11,7 @@ export const ReceiveAmountBox = styled.div` border-radius: 0 0 16px 16px; font-size: 14px; font-weight: 600; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border: 2px solid ${({ theme }) => theme.grey1}; ${({ theme }) => theme.mediaWidth.upToSmall` diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts b/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts index 7be251e7e4..cdebb05f46 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts +++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts @@ -5,6 +5,8 @@ import styled from 'styled-components/macro' import { RowBetween, RowFixed } from 'legacy/components/Row' import { MouseoverTooltipContent } from 'legacy/components/Tooltip' +import { UI } from 'common/constants/theme' + import { RowStyleProps } from './types' const StyledMouseoverTooltipContent = styled(MouseoverTooltipContent)`` @@ -21,7 +23,7 @@ export const StyledRowBetween = styled(RowBetween)` } ${TextWrapper} { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: ${({ fontSize = 13 }) => fontSize}px; font-weight: ${({ fontWeight = 500 }) => fontWeight}; @@ -30,7 +32,7 @@ export const StyledRowBetween = styled(RowBetween)` font-weight: 400; &:hover { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } } @@ -45,6 +47,6 @@ export const StyledRowBetween = styled(RowBetween)` ${StyledMouseoverTooltipContent} { background-color: ${({ theme }) => theme.bg3}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/styled.tsx index 20b75dc857..9e03f75df1 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/styled.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/styled.tsx @@ -4,6 +4,7 @@ import styled from 'styled-components/macro' import QuestionHelper from 'legacy/components/QuestionHelper' +import { UI } from 'common/constants/theme' import { RateInfo } from 'common/pure/RateInfo' export const Box = styled.div` @@ -15,7 +16,7 @@ export const Row = styled.div` justify-content: space-between; font-size: 13px; font-weight: 400; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); min-height: 24px; gap: 3px; @@ -33,7 +34,7 @@ export const Row = styled.div` transition: color 0.15s ease-in-out; &:hover { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } } @@ -63,8 +64,8 @@ export const Discount = styled.span` display: flex; cursor: pointer; padding: 2px 8px; - background: ${({ theme }) => theme.grey1}; - color: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_GREY}); + color: var(${UI.COLOR_TEXT1}); border-radius: 5px; font-weight: 400; transition: background 0.2s ease-in-out, color 0.2s ease-in-out; diff --git a/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx index 19fe60b682..5c7609a74e 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx @@ -4,6 +4,8 @@ import styled from 'styled-components/macro' import { RowBetween } from 'legacy/components/Row' +import { UI } from 'common/constants/theme' + export const LowerSectionWrapper = styled(RowBetween).attrs((props) => ({ ...props, align: 'center', @@ -26,7 +28,7 @@ export const BottomGrouping = styled.div` div > svg, div > svg > path { - stroke: ${({ theme }) => theme.text2}; + stroke: var(${UI.COLOR_TEXT2}); } ` export const LightGreyText = styled.span` @@ -36,7 +38,7 @@ export const LightGreyText = styled.span` export const StyledInfoIcon = styled(Info)` opacity: 0.5; - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); line-height: 0; vertical-align: middle; transition: opacity 0.2s ease-in-out; diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/styled.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/styled.tsx index 49c68e8dda..e8643f3388 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/styled.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/styled.tsx @@ -2,6 +2,8 @@ import styled from 'styled-components/macro' import { SetRecipient } from 'modules/swap/containers/SetRecipient' +import { UI } from 'common/constants/theme' + export const Container = styled.div` width: 100%; max-width: ${({ theme }) => theme.appBody.maxWidth.swap}; @@ -12,7 +14,7 @@ export const ContainerBox = styled.div` display: flex; flex-flow: column wrap; gap: 10px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border: none; border-radius: 16px; box-shadow: ${({ theme }) => theme.boxShadow1}; diff --git a/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/styled.ts b/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/styled.ts index caa261faef..aef244cb79 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/styled.ts +++ b/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/styled.ts @@ -2,6 +2,8 @@ import styled from 'styled-components/macro' import { StyledRowBetween } from 'modules/swap/pure/Row/styled' +import { UI } from 'common/constants/theme' + export const Wrapper = styled.div` display: flex; align-items: center; @@ -15,7 +17,7 @@ export const Wrapper = styled.div` > svg:first-child { margin: 0 4px 0 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); opacity: 0.5; } diff --git a/apps/cowswap-frontend/src/modules/trade/pure/Settings/styled.ts b/apps/cowswap-frontend/src/modules/trade/pure/Settings/styled.ts index 77fdee8b7f..7c299250e6 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/Settings/styled.ts +++ b/apps/cowswap-frontend/src/modules/trade/pure/Settings/styled.ts @@ -3,10 +3,12 @@ import { transparentize } from 'polished' import { Settings as SettingsIconRaw } from 'react-feather' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const SettingsTitle = styled.h3` font-weight: 600; font-size: 14px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); margin: 0 0 12px 0; ` @@ -16,8 +18,8 @@ export const SettingsContainer = styled.div` border-radius: 12px; box-shadow: ${({ theme }) => theme.boxShadow2}; border: 1px solid ${({ theme }) => transparentize(0.95, theme.white)}; - background: ${({ theme }) => theme.bg1}; - color: ${({ theme }) => theme.text1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(${UI.COLOR_TEXT1}); ` export const SettingsBoxWrapper = styled.div<{ disabled: boolean }>` @@ -37,7 +39,7 @@ export const SettingsBoxTitle = styled.div` display: flex; align-items: center; font-weight: 400; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: 14px; opacity: 0.85; margin-right: 2rem; @@ -116,6 +118,6 @@ export const SettingsIcon = styled(SettingsIconRaw)` &:hover > path, &:hover > circle { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/styled.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/styled.tsx index d79c30c070..b72a62e11d 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/styled.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/styled.tsx @@ -1,5 +1,7 @@ import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const WidgetWrapper = styled.div` width: 100%; padding: 0; @@ -32,7 +34,7 @@ export const Header = styled.div` justify-content: space-between; align-items: center; position: sticky; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); top: 0; left: 0; width: 100%; diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/styled.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/styled.tsx index 7dadb4c6d2..82414cb371 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/styled.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/styled.tsx @@ -3,6 +3,8 @@ import styled from 'styled-components/macro' import Input from 'legacy/components/NumericalInput' +import { UI } from 'common/constants/theme' + export const Suffix = styled.span` margin: 0 0 0 3px; opacity: 0.7; @@ -47,7 +49,7 @@ export const ArrowsWrapper = styled.div` &:hover { > span > svg > path { - fill: ${({ theme }) => theme.text1}; + fill: var(${UI.COLOR_TEXT1}); } } } diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeSelect/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeSelect/index.tsx index ae2eb60d7c..ba783dd588 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/TradeSelect/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeSelect/index.tsx @@ -3,6 +3,8 @@ import { transparentize } from 'polished' import { ChevronDown } from 'react-feather' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + import { TradeWidgetField, TradeWidgetFieldProps } from '../TradeWidgetField' export type TradeSelectItem = { label: string; value: unknown } @@ -15,7 +17,7 @@ export interface TradeSelectProps extends TradeWidgetFieldProps { } const StyledMenuList = styled(MenuList)` - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); box-shadow: ${({ theme }) => theme.boxShadow2}; margin: 15px 0 0 0; padding: 16px; @@ -44,7 +46,7 @@ const StyledMenuButton = styled(MenuButton)` cursor: pointer; width: 100%; justify-content: space-between; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ` const StyledMenuItem = styled(MenuItem)` @@ -53,7 +55,7 @@ const StyledMenuItem = styled(MenuItem)` color: ${({ theme }) => transparentize(0.2, theme.text1)}; &:hover { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } &:not(:last-child) { diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeTextBox/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeTextBox/index.tsx index 7713ddf16c..346624ecbd 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/TradeTextBox/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeTextBox/index.tsx @@ -1,9 +1,11 @@ import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + import { TradeWidgetField, TradeWidgetFieldProps } from '../TradeWidgetField' const StyledTradeWidgetField = styled(TradeWidgetField)` - background-color: ${({ theme }) => theme.bg1}; + background-color: var(${UI.COLOR_CONTAINER_BG_01}); border: 1px solid ${({ theme }) => theme.grey1}; display: flex; flex-flow: column wrap; diff --git a/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/styled.ts b/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/styled.ts index 8572ebdf9b..c2dfd5fc45 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/styled.ts +++ b/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/styled.ts @@ -1,6 +1,8 @@ import { transparentize, darken } from 'polished' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const Container = styled.div` padding: 16px; border-radius: 16px; @@ -10,7 +12,7 @@ export const Container = styled.div` export const TitleSection = styled.div` text-align: center; font-size: 20px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); margin: 24px auto 42px; > h3 { diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormBlankButton/index.tsx b/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormBlankButton/index.tsx index efda5ba520..2a17cc57c0 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormBlankButton/index.tsx +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormBlankButton/index.tsx @@ -4,6 +4,8 @@ import { Trans } from '@lingui/macro' import { lighten, transparentize } from 'polished' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + const LONG_TEXT_LENGTH = 20 const ActionButton = styled.button<{ hasLongText$: boolean }>` @@ -27,7 +29,7 @@ const ActionButton = styled.button<{ hasLongText$: boolean }>` } &:disabled { - background-color: ${({ theme }) => theme.grey1}; + background-color: var(${UI.COLOR_GREY}); color: ${({ theme }) => transparentize(0.4, theme.text1)}; background-image: none; border: 0; diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx index 6b5aa4f0a5..cb4e86ae99 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx @@ -5,6 +5,8 @@ import ShieldImage from 'legacy/assets/cow-swap/protection.svg' import { deadlinePartsDisplay } from 'modules/twap/utils/deadlinePartsDisplay' +import { UI } from 'common/constants/theme' + const IconImage = styled.div` display: flex; align-items: center; @@ -12,7 +14,7 @@ const IconImage = styled.div` > svg { opacity: 0.5; - fill: ${({ theme }) => theme.text1}; + fill: var(${UI.COLOR_TEXT1}); margin: 0 3px 0 0; } ` diff --git a/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx b/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx index 7257c673ac..f1cf057e60 100644 --- a/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx +++ b/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx @@ -6,6 +6,8 @@ import { ButtonSecondary } from 'legacy/components/Button' import { NumericalInput } from 'modules/trade/pure/TradeNumberInput/styled' import { TradeWidgetFieldBox } from 'modules/trade/pure/TradeWidgetField/styled' +import { UI } from 'common/constants/theme' + export const ModalWrapper = styled.div` display: flex; flex-flow: column wrap; @@ -70,18 +72,18 @@ export const CloseIcon = styled(X)` } > line { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` export const CancelButton = styled(ButtonSecondary)` background: transparent; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); border: 1px solid ${({ theme }) => theme.text1}; :hover { background: transparent; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); border: 1px solid ${({ theme }) => theme.text1}; } ` diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/AddToMetamask/index.tsx b/apps/cowswap-frontend/src/modules/wallet/api/pure/AddToMetamask/index.tsx index b85bb4adb7..b326a238c2 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/AddToMetamask/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/api/pure/AddToMetamask/index.tsx @@ -9,6 +9,7 @@ import { RowFixed } from 'legacy/components/Row' import MetaMaskLogo from 'modules/wallet/api/assets/metamask.png' +import { UI } from 'common/constants/theme' import { TokenSymbol } from 'common/pure/TokenSymbol' export const ButtonCustom = styled.button` @@ -20,7 +21,7 @@ export const ButtonCustom = styled.button` border-radius: 16px; min-height: 52px; border: 1px solid ${({ theme }) => theme.border2}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); background: transparent; outline: 0; padding: 8px 16px; diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/ConnectWalletOption/index.tsx b/apps/cowswap-frontend/src/modules/wallet/api/pure/ConnectWalletOption/index.tsx index 3968af2a35..dcda3ee218 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/ConnectWalletOption/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/api/pure/ConnectWalletOption/index.tsx @@ -6,6 +6,8 @@ import styled from 'styled-components/macro' import { MouseoverTooltip } from 'legacy/components/Tooltip' import { ExternalLink } from 'legacy/theme' +import { UI } from 'common/constants/theme' + const InfoCard = styled.button<{ isActive?: boolean }>` background-color: ${({ theme, isActive }) => (isActive ? theme.bg3 : theme.bg2)}; padding: 1rem; @@ -84,7 +86,7 @@ export const HeaderText = styled.div` ` const SubHeader = styled.div` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); margin-top: 10px; font-size: 12px; ` diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/Identicon/index.tsx b/apps/cowswap-frontend/src/modules/wallet/api/pure/Identicon/index.tsx index 2928b03243..0a868e7987 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/Identicon/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/api/pure/Identicon/index.tsx @@ -2,12 +2,14 @@ import React from 'react' import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' + export const StyledIdenticon = styled.div` height: 1rem; width: 1rem; border-radius: 1.125rem; // background-color: ${({ theme }) => theme.bg4}; - background-color: ${({ theme }) => theme.bg1}; // MOD + background-color: var(${UI.COLOR_CONTAINER_BG_01}); // MOD font-size: initial; ` diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/styled.tsx b/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/styled.tsx index 81eff40a82..581ed5c91d 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/styled.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/styled.tsx @@ -3,8 +3,10 @@ import styled from 'styled-components/macro' import { ReactComponent as Close } from 'legacy/assets/images/x.svg' import { ExternalLink } from 'legacy/theme' +import { UI } from 'common/constants/theme' + export const TermsWrapper = styled.div` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ` export const Blurb = styled.div` @@ -76,7 +78,7 @@ export const IconWrapper = styled.div` align-items: center; justify-content: center; background: transparent; - border: 1px solid var(--cow-color-border); + border: 1px solid var(${UI.COLOR_BORDER}); padding: 8px; margin: 0 12px 0 0; @@ -86,7 +88,7 @@ export const IconWrapper = styled.div` } > svg > path { - --color: var(--cow-color-text1); + --color: var(${UI.COLOR_TEXT1}); fill: var(--color); stroke: var(--color); } diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/styled.ts b/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/styled.ts index d82660de22..be29ea94b8 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/styled.ts +++ b/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/styled.ts @@ -4,6 +4,8 @@ import styled, { css } from 'styled-components/macro' import { ButtonSecondary } from 'legacy/components/Button' +import { UI } from 'common/constants/theme' + export const Web3StatusGeneric = styled(ButtonSecondary)`` export const Web3StatusError = styled(Web3StatusGeneric)` @@ -44,14 +46,14 @@ export const Web3StatusConnect = styled(Web3StatusGeneric)<{ faded?: boolean }>` ` export const Web3StatusConnected = styled(Web3StatusGeneric)<{ pending?: boolean; clickDisabled?: boolean }>` - background-color: ${({ theme }) => theme.grey1}; + background-color: var(${UI.COLOR_GREY}); border: 1px solid transparent; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-weight: 500; &:hover { - background-color: ${({ theme }) => theme.grey1}; - color: ${({ theme }) => theme.text1}; + background-color: var(${UI.COLOR_GREY}); + color: var(${UI.COLOR_TEXT1}); } ${({ clickDisabled }) => @@ -81,7 +83,7 @@ export const NetworkIcon = styled(Activity)` ` export const Wrapper = styled.div` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); height: 40px; width: 100%; display: flex; diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts b/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts index a77555abf1..c8d278734d 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts +++ b/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts @@ -3,6 +3,8 @@ import styled from 'styled-components/macro' import { ButtonPrimary } from 'legacy/components/Button' import { ExternalLink } from 'legacy/theme/components' +import { UI } from 'common/constants/theme' + export const Wrapper = styled.div` display: flex; align-items: center; @@ -25,7 +27,7 @@ export const Icon = styled.div` export const Content = styled.div` flex: 1; padding: 0 1rem; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); h4 { margin-bottom: 5px; font-size: 1.1rem; @@ -65,6 +67,6 @@ export const GetZengoButton = styled(ButtonPrimary)` export const HowToUse = styled(ExternalLink)` font-size: 0.8rem; margin-top: 5px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); cursor: pointer; ` diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/styled.tsx b/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/styled.tsx index d5502835d2..b7f2d1a520 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/styled.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/styled.tsx @@ -2,10 +2,12 @@ import styled from 'styled-components/macro' import { ReactComponent as Close } from 'legacy/assets/images/x.svg' +import { UI } from 'common/constants/theme' + export const CloseIcon = styled(Close)` opacity: 0.6; transition: opacity 0.3s ease-in-out; - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); width: 24px; height: 24px; cursor: pointer; diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/index.cosmos.tsx index 82b5a0fc62..81fbcb01b6 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/index.cosmos.tsx @@ -4,6 +4,8 @@ import styled from 'styled-components/macro' import { WETH_GOERLI } from 'legacy/utils/goerli/constants' +import { UI } from 'common/constants/theme' + import { AccountIndexSelect } from './index' const accountsList = [ @@ -25,7 +27,7 @@ const Wrapper = styled.div` margin: 100px auto; padding: 20px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); ` const Fixtures = { diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/styled.tsx b/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/styled.tsx index 3ff7fa9229..e941c67de6 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/styled.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/styled.tsx @@ -1,5 +1,6 @@ import styled from 'styled-components/macro' +import { UI } from 'common/constants/theme' import { ButtonSecondary } from 'common/pure/ButtonSecondary' export const Wrapper = styled.div` @@ -17,7 +18,7 @@ export const LoaderContainer = styled(ButtonSecondary)` &[disabled] { cursor: default; - background: var(--cow-color-lightBlue-opacity-90); + background: var(${UI.COLOR_LIGHT_BLUE_OPACITY_90}); } ` diff --git a/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts b/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts index dfd53aa438..d4f614d7b0 100644 --- a/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts +++ b/apps/cowswap-frontend/src/pages/Account/Tokens/styled.ts @@ -4,6 +4,7 @@ import styled from 'styled-components/macro' import { ThemedText } from 'legacy/theme' +import { UI } from 'common/constants/theme' import { Card } from 'pages/Account/styled' export const MenuWrapper = styled.div` @@ -15,8 +16,8 @@ export const MenuButton = styled.button` outline: none; border: none; cursor: pointer; - color: ${({ theme }) => theme.text1}; - background: ${({ theme }) => theme.bg1}; + color: var(${UI.COLOR_TEXT1}); + background: var(${UI.COLOR_CONTAINER_BG_01}); height: 44px; border-radius: 21px; padding: 0 16px; @@ -86,7 +87,7 @@ export const AccountPageWrapper = styled.div` ` export const MainText = styled(ThemedText.Main)` - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: 14px; ` @@ -130,7 +131,7 @@ export const ClearSearchInput = styled.div` ` export const Overview = styled.div` - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border-radius: 16px; gap: 16px; margin: 0; diff --git a/apps/cowswap-frontend/src/pages/Account/styled.tsx b/apps/cowswap-frontend/src/pages/Account/styled.tsx index 590b6e245a..1a831b8101 100644 --- a/apps/cowswap-frontend/src/pages/Account/styled.tsx +++ b/apps/cowswap-frontend/src/pages/Account/styled.tsx @@ -11,6 +11,7 @@ import { ExternalLink } from 'legacy/theme' import { Page, GdocsListStyle } from 'modules/application/pure/Page' import { ButtonCustom as AddToMetaMask } from 'modules/wallet/api/pure/AddToMetamask' +import { UI } from 'common/constants/theme' import { BannerExplainer } from 'pages/Claim/styled' export const Container = styled.div` @@ -29,7 +30,7 @@ export const Wrapper = styled(Page)` justify-content: flex-end; flex-flow: column wrap; margin: 0; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); box-shadow: ${({ theme }) => theme.boxShadow1}; border: none; @@ -63,7 +64,7 @@ export const ChildWrapper = styled.div` justify-content: center; border-radius: 21px; padding: 20px; - background-color: ${({ theme }) => theme.grey1}; + background-color: var(${UI.COLOR_GREY}); ${({ theme }) => theme.mediaWidth.upToSmall` grid-column-start: 1; @@ -116,7 +117,7 @@ export const ItemTitle = styled.h3` margin: 0 0 16px 0; font-size: 18px; line-height: 1.21; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); gap: 4px; ${({ theme }) => theme.mediaWidth.upToSmall` @@ -271,7 +272,7 @@ export const Card = styled.div<{ showLoader?: boolean }>` flex: 1; min-height: 192px; margin: 0; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); box-shadow: none; padding: 24px; gap: 24px 0; @@ -326,7 +327,7 @@ export const Card = styled.div<{ showLoader?: boolean }>` export const BannerCard = styled(BannerExplainer)` min-height: 192px; border-radius: 16px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); border: none; padding: 0 100px 0 24px; flex: 1; @@ -346,7 +347,7 @@ export const BannerCard = styled(BannerExplainer)` justify-content: space-between; height: 100%; padding: 24px 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ${({ theme }) => theme.mediaWidth.upToSmall` padding: 0; @@ -362,7 +363,7 @@ export const BannerCard = styled(BannerExplainer)` } @supports not (-webkit-background-clip: text) { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ${({ theme }) => theme.mediaWidth.upToSmall` @@ -372,7 +373,7 @@ export const BannerCard = styled(BannerExplainer)` } > small { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: 14px; line-height: 1.5; text-align: left; @@ -402,7 +403,7 @@ export const BannerCard = styled(BannerExplainer)` > span > a, > span > a:link { font-size: 15px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); &:hover { color: ${({ theme }) => theme.text3}; @@ -420,14 +421,14 @@ export const BannerCard = styled(BannerExplainer)` > svg { .stop1 { - stop-color: ${({ theme }) => theme.text1}; + stop-color: var(${UI.COLOR_TEXT1}); } .stop2 { - stop-color: ${({ theme }) => theme.text1}; + stop-color: var(${UI.COLOR_TEXT1}); stop-opacity: 0.8; } .stop3 { - stop-color: ${({ theme }) => theme.text1}; + stop-color: var(${UI.COLOR_TEXT1}); stop-opacity: 0; } } @@ -477,8 +478,8 @@ export const CardActions = styled.div<{ justify?: string; content?: string }>` `}; &:hover { - text-decoration-color: ${({ theme }) => theme.text1}; - color: ${({ theme }) => theme.text1}; + text-decoration-color: var(${UI.COLOR_TEXT1}); + color: var(${UI.COLOR_TEXT1}); } } @@ -588,7 +589,7 @@ export const ConvertWrapper = styled.div` display: grid; grid-template-columns: 1fr 200px; align-items: center; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border-radius: 16px; padding: 16px; width: 100%; @@ -629,7 +630,7 @@ export const VestingBreakdown = styled.div` } > span:last-of-type > p { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ` @@ -666,7 +667,7 @@ export const CardsSpinner = styled(SpinnerLoader)` margin: auto; & path { - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); } ` diff --git a/apps/cowswap-frontend/src/pages/Claim/styled.ts b/apps/cowswap-frontend/src/pages/Claim/styled.ts index 353417bf2b..869f0557bd 100644 --- a/apps/cowswap-frontend/src/pages/Claim/styled.ts +++ b/apps/cowswap-frontend/src/pages/Claim/styled.ts @@ -12,6 +12,8 @@ import { CopyIcon } from 'legacy/components/Copy' import { Icon } from 'legacy/components/CowProtocolLogo' import { Step } from 'legacy/components/Stepper' +import { UI } from 'common/constants/theme' + import ClaimsOnOtherChainsBanner from './ClaimsOnOtherChainsBanner' export const InnerPageWrapper = styled.div` @@ -19,11 +21,11 @@ export const InnerPageWrapper = styled.div` --border-radius-small: 16px; display: flex; flex-flow: column wrap; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); padding: 30px; border: none; box-shadow: ${({ theme }) => theme.boxShadow1}; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); min-height: 450px; justify-content: center; align-items: center; @@ -161,7 +163,7 @@ export const ClaimSummary = styled.div` align-items: center; justify-content: flex-start; padding: 8px; - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); border: 0; border-radius: var(--border-radius); margin: 0 auto 24px; @@ -201,7 +203,7 @@ export const IntroDescription = styled.div<{ center?: boolean }>` } > p > i { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-weight: 600; font-style: normal; } @@ -431,7 +433,7 @@ export const ClaimTable = styled.div` text-align: left; font-weight: normal; font-size: 15px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); position: relative; } @@ -442,7 +444,7 @@ export const ClaimTable = styled.div` td { display: flex; align-items: center; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); word-break: break-word; background: ${({ theme }) => theme.blueShade3}; } @@ -505,7 +507,7 @@ export const ClaimTable = styled.div` > span > b { font-weight: 500; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } } @@ -548,7 +550,7 @@ export const UserMessage = styled.div<{ variant?: string }>` ? transparentize(0.9, theme.blue2) : transparentize(0.9, theme.attention)}; color: ${({ variant, theme }) => - variant === 'danger' ? theme.danger : variant === 'info' ? theme.blue2 : darken(0.1, theme.attention)}; + variant === 'danger' ? `var(${UI.COLOR_DANGER})` : variant === 'info' ? theme.blue2 : darken(0.1, theme.attention)}; margin: 0 auto; align-items: center; font-size: 15px; @@ -571,7 +573,7 @@ export const UserMessage = styled.div<{ variant?: string }>` > svg > path { fill: ${({ variant, theme }) => - variant === 'danger' ? theme.danger : variant === 'info' ? theme.blue2 : darken(0.1, theme.attention)}; + variant === 'danger' ? `var(${UI.COLOR_DANGER})` : variant === 'info' ? theme.blue2 : darken(0.1, theme.attention)}; } > span { @@ -652,7 +654,7 @@ export const ClaimTotal = styled.div` export const ConfirmOrLoadingWrapper = styled.div<{ activeBG: boolean }>` width: 100%; padding: 24px 24px 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); position: relative; display: flex; flex-direction: column; @@ -670,7 +672,7 @@ export const ConfirmOrLoadingWrapper = styled.div<{ activeBG: boolean }>` line-height: 1.2; text-align: center; margin: 0 0 12px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); ${({ theme }) => theme.mediaWidth.upToSmall` font-size: 26px; @@ -751,8 +753,8 @@ export const ClaimBanner = styled.div<{ isClaimed: boolean }>` display: flex; justify-content: center; align-items: center; - background: ${({ theme, isClaimed }) => transparentize(0.9, !isClaimed ? theme.success : theme.blue2)}; - color: ${({ theme, isClaimed }) => (!isClaimed ? theme.success : theme.blue2)}; + background: ${({ theme, isClaimed }) => transparentize(0.9, !isClaimed ? `var(${UI.COLOR_SUCCESS})` : theme.blue2)}; + color: ${({ theme, isClaimed }) => (!isClaimed ? `var(${UI.COLOR_SUCCESS})` : theme.blue2)}; margin: 0 auto 16px; font-weight: 600; @@ -767,7 +769,7 @@ export const ClaimBanner = styled.div<{ isClaimed: boolean }>` height: 21px; > path { - fill: ${({ theme, isClaimed }) => (!isClaimed ? theme.success : theme.blue2)}; + fill: ${({ theme, isClaimed }) => (!isClaimed ? `var(${UI.COLOR_SUCCESS})` : theme.blue2)}; } ${({ theme }) => theme.mediaWidth.upToSmall` @@ -780,7 +782,7 @@ export const InputField = styled.div` padding: 18px 18px 18px 36px; border-radius: var(--border-radius); border: ${({ theme }) => theme.currencyInput?.border}; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); display: flex; flex-flow: row wrap; background: ${({ theme }) => theme.currencyInput?.background}; @@ -792,7 +794,7 @@ export const InputField = styled.div` border: 0; font-size: 24px; outline: 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); width: 100%; } @@ -839,7 +841,7 @@ export const InputField = styled.div` padding: 0; font-size: 22px; font-weight: 600; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } > span { @@ -961,7 +963,7 @@ export const TopNav = styled.div` ${ButtonSecondary} { margin: 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); font-size: 15px; width: auto; } @@ -1198,7 +1200,7 @@ export const UnderlineButton = styled.button` } &:hover { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } &:disabled { @@ -1258,7 +1260,7 @@ export const InvestInput = styled.span<{ disabled: boolean }>` bottom: 0; margin: auto; font-weight: normal; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); background: ${({ theme }) => theme.bg5}; border-radius: 12px; padding: 0 12px; @@ -1271,7 +1273,7 @@ export const InvestInput = styled.span<{ disabled: boolean }>` } > div > label > input { - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); border: none; padding: 12px 70px 0 0; font-size: 26px; @@ -1353,7 +1355,7 @@ export const InvestAvailableBar = styled.div<{ percentage?: number }>` justify-content: flex-start; overflow: hidden; border-radius: 24px; - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); margin: 6px 0; padding: 0; @@ -1376,7 +1378,7 @@ export const InvestAvailableBar = styled.div<{ percentage?: number }>` content: ${({ percentage }) => (percentage ? `'${percentage}%'` : '0%')}; display: block; font-size: 12px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); z-index: 1; height: 100%; width: ${({ percentage }) => (percentage ? `${percentage}%` : '0%')}; @@ -1425,7 +1427,7 @@ export const InvestSummary = styled.div` > span > b { font-weight: 600; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); } ` @@ -1519,7 +1521,7 @@ export const AccountClaimSummary = styled.div` border-radius: var(--iconSize); width: var(--iconSize); height: var(--iconSize); - background: ${({ theme }) => theme.bg1}; + background: var(${UI.COLOR_CONTAINER_BG_01}); ${({ theme }) => theme.mediaWidth.upToSmall` transform: rotate(90deg); @@ -1532,7 +1534,7 @@ export const AccountClaimSummary = styled.div` } > svg > path { - fill: ${({ theme }) => theme.text1}; + fill: var(${UI.COLOR_TEXT1}); } } ` @@ -1589,7 +1591,7 @@ export const CowSpinner = styled.div` height: 94%; width: 94%; padding: 0; - stroke: ${({ theme }) => theme.text1}; + stroke: var(${UI.COLOR_TEXT1}); border-radius: var(--circle-size); z-index: 1; } diff --git a/apps/cowswap-frontend/src/pages/CookiePolicy/index.tsx b/apps/cowswap-frontend/src/pages/CookiePolicy/index.tsx index 5df2fc89c1..d8f788d682 100644 --- a/apps/cowswap-frontend/src/pages/CookiePolicy/index.tsx +++ b/apps/cowswap-frontend/src/pages/CookiePolicy/index.tsx @@ -5,6 +5,8 @@ import { MarkdownPage } from 'legacy/components/Markdown' import { PageTitle } from 'modules/application/containers/PageTitle' import { GdocsListStyle } from 'modules/application/pure/Page' +import { UI } from 'common/constants/theme' + import contentFile from './CookiePolicy.md' const Wrapper = styled(MarkdownPage)` @@ -20,14 +22,14 @@ const Wrapper = styled(MarkdownPage)` width: 100%; min-width: 800px; border-spacing: 1px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); > thead { background: ${({ theme }) => theme.bg3}; } > tbody > tr { - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); } > tbody > tr > td > span[role='img'] { diff --git a/apps/cowswap-frontend/src/pages/Faq/styled.tsx b/apps/cowswap-frontend/src/pages/Faq/styled.tsx index dc510880c2..0a4b92fd8a 100644 --- a/apps/cowswap-frontend/src/pages/Faq/styled.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/styled.tsx @@ -6,6 +6,8 @@ import { ExternalLink as ExternalLinkTheme, StyledInternalLink } from 'legacy/th import { Content } from 'modules/application/pure/Page' +import { UI } from 'common/constants/theme' + export const ExternalLinkFaq = styled(ExternalLinkTheme)` text-decoration: underline; font-weight: normal; @@ -34,14 +36,14 @@ export const Wrapper = styled.div` > table { width: 100%; border-spacing: 1px; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); > thead { background: ${({ theme }) => theme.bg3}; } > tbody > tr { - background: ${({ theme }) => theme.grey1}; + background: var(${UI.COLOR_GREY}); } > tbody > tr > td > span[role='img'] { @@ -119,7 +121,7 @@ export const Menu = styled.div` font-weight: bold; line-height: 1; margin: 0 24px 0 0; - color: ${({ theme }) => theme.text1}; + color: var(${UI.COLOR_TEXT1}); height: max-content; position: sticky; top: 0; diff --git a/apps/cowswap-frontend/yarn.lock b/apps/cowswap-frontend/yarn.lock new file mode 100644 index 0000000000..fb57ccd13a --- /dev/null +++ b/apps/cowswap-frontend/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + From 18a368090c9c094e7bf6d0715638d42f3a9957b2 Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Fri, 8 Sep 2023 21:08:14 +0200 Subject: [PATCH 02/36] chore: refactor and simplify pixel logic (#3118) --- .../analytics/events/transactionEvents.ts | 15 +------ .../analytics/hooks/useAnalyticsReporter.ts | 40 ++++++++++--------- .../components/analytics/pixel/constants.ts | 6 --- .../components/analytics/pixel/facebook.ts | 17 +++++--- .../components/analytics/pixel/index.ts | 9 +++++ .../components/analytics/pixel/linkedin.ts | 17 +++++--- .../components/analytics/pixel/microsoft.ts | 17 +++++--- .../components/analytics/pixel/paved.ts | 17 +++++--- .../components/analytics/pixel/reddit.ts | 17 +++++--- .../analytics/pixel/sendAllPixels.ts | 35 ++++++++++++++++ .../components/analytics/pixel/twitter.ts | 17 +++++--- .../components/analytics/pixel/types.ts | 9 +++++ .../components/analytics/pixel/utils.ts | 7 ++-- 13 files changed, 145 insertions(+), 78 deletions(-) create mode 100644 apps/cowswap-frontend/src/legacy/components/analytics/pixel/index.ts create mode 100644 apps/cowswap-frontend/src/legacy/components/analytics/pixel/sendAllPixels.ts create mode 100644 apps/cowswap-frontend/src/legacy/components/analytics/pixel/types.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/transactionEvents.ts b/apps/cowswap-frontend/src/legacy/components/analytics/events/transactionEvents.ts index 7e220b2591..94ad4d9dc7 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/events/transactionEvents.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/events/transactionEvents.ts @@ -1,13 +1,7 @@ import { OrderClass } from '@cowprotocol/cow-sdk' import { sendEvent } from '../googleAnalytics' -import { PIXEL_EVENTS } from '../pixel/constants' -import { sendFacebookEvent } from '../pixel/facebook' -import { sendLinkedinEvent } from '../pixel/linkedin' -import { sendMicrosoftEvent } from '../pixel/microsoft' -import { sendPavedEvent } from '../pixel/paved' -import { sendRedditEvent } from '../pixel/reddit' -import { sendTwitterEvent } from '../pixel/twitter' +import { PixelEvent, sendAllPixels } from '../pixel' import { AnalyticsOrderType, Category } from '../types' const LABEL_FROM_CLASS: Record = { @@ -86,12 +80,7 @@ export function signTradeAnalytics(orderClass: AnalyticsOrderType, label?: strin export type OrderType = 'Posted' | 'Executed' | 'Canceled' | 'Expired' export function orderAnalytics(action: OrderType, orderClass: AnalyticsOrderType, label?: string) { if (action === 'Posted') { - sendFacebookEvent(PIXEL_EVENTS.POST_TRADE) - sendLinkedinEvent(PIXEL_EVENTS.POST_TRADE) - sendTwitterEvent(PIXEL_EVENTS.POST_TRADE) - sendRedditEvent(PIXEL_EVENTS.POST_TRADE) - sendPavedEvent(PIXEL_EVENTS.POST_TRADE) - sendMicrosoftEvent(PIXEL_EVENTS.POST_TRADE) + sendAllPixels(PixelEvent.POST_TRADE) } sendEvent({ diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts b/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts index 267438612d..075368b58a 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts @@ -17,13 +17,14 @@ import { useGetMarketDimension } from './useGetMarketDimension' import { googleAnalytics } from '../googleAnalytics' import { GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY } from '../index' -import { PIXEL_EVENTS } from '../pixel/constants' -import { sendFacebookEvent } from '../pixel/facebook' -import { sendLinkedinEvent } from '../pixel/linkedin' -import { sendMicrosoftEvent } from '../pixel/microsoft' -import { sendPavedEvent } from '../pixel/paved' -import { sendRedditEvent } from '../pixel/reddit' -import { sendTwitterEvent } from '../pixel/twitter' +import { PixelEvent, sendAllPixels } from '../pixel' +import { + enablePixelFacebook, + enablePixelMicrosoft, + enablePixelPaved, + enablePixelReddit, + enablePixelTwitter, +} from '../pixel' import { Dimensions } from '../types' export function sendTiming(timingCategory: any, timingVar: any, timingValue: any, timingLabel: any) { @@ -87,12 +88,7 @@ export function useAnalyticsReporter() { // Handle pixel tracking on wallet connection if (!prevAccount && account) { - sendFacebookEvent(PIXEL_EVENTS.CONNECT_WALLET) - sendLinkedinEvent(PIXEL_EVENTS.CONNECT_WALLET) - sendTwitterEvent(PIXEL_EVENTS.CONNECT_WALLET) - sendRedditEvent(PIXEL_EVENTS.CONNECT_WALLET) - sendPavedEvent(PIXEL_EVENTS.CONNECT_WALLET) - sendMicrosoftEvent(PIXEL_EVENTS.CONNECT_WALLET) + sendAllPixels(PixelEvent.CONNECT_WALLET) } }, [account, walletName, prevAccount]) @@ -113,12 +109,18 @@ export function useAnalyticsReporter() { // Handle initiate pixel tracking useEffect(() => { if (!initiatedPixel) { - sendFacebookEvent(PIXEL_EVENTS.INIT) - sendLinkedinEvent(PIXEL_EVENTS.INIT) - sendTwitterEvent(PIXEL_EVENTS.INIT) - sendRedditEvent(PIXEL_EVENTS.INIT) - sendPavedEvent(PIXEL_EVENTS.INIT) - sendMicrosoftEvent(PIXEL_EVENTS.INIT) + // Init all pixels + const enablePixelFunctions = [ + enablePixelFacebook, + enablePixelMicrosoft, + enablePixelPaved, + enablePixelReddit, + enablePixelTwitter, + ] + enablePixelFunctions.forEach((enablePixel) => enablePixel()) + + // Sent + sendAllPixels(PixelEvent.INIT) initiatedPixel = true } diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts index ab431341be..03bab33f29 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts @@ -1,9 +1,3 @@ import { isEns, isProd } from 'legacy/utils/environments' export const PIXEL_ENABLED = isProd || isEns - -export enum PIXEL_EVENTS { - INIT = 'init', - CONNECT_WALLET = 'connect_wallet', - POST_TRADE = 'post_trade', -} diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/facebook.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/facebook.ts index 024b01b9b4..250e392cf6 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/facebook.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/facebook.ts @@ -1,12 +1,17 @@ -import { PIXEL_EVENTS } from './constants' +import { enablePixel } from './sendAllPixels' +import { PixelEvent, PixelEventMap } from './types' import { sendPixel } from './utils' -const events = { - [PIXEL_EVENTS.INIT]: 'InitiateCheckout', - [PIXEL_EVENTS.CONNECT_WALLET]: 'Contact', - [PIXEL_EVENTS.POST_TRADE]: 'Lead', +const events: PixelEventMap = { + [PixelEvent.INIT]: 'InitiateCheckout', + [PixelEvent.CONNECT_WALLET]: 'Contact', + [PixelEvent.POST_TRADE]: 'Lead', } -export const sendFacebookEvent = sendPixel((event) => { +const sendFacebookEvent = sendPixel((event) => { window.fbq?.('track', events[event]) }) + +export function enablePixelFacebook() { + enablePixel(events, sendFacebookEvent) +} diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/index.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/index.ts new file mode 100644 index 0000000000..396dd8d9da --- /dev/null +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/index.ts @@ -0,0 +1,9 @@ +export { sendAllPixels } from './sendAllPixels' +export * from './types' + +// Register +export { enablePixelFacebook } from './facebook' +export { enablePixelPaved } from './paved' +export { enablePixelReddit } from './reddit' +export { enablePixelTwitter } from './twitter' +export { enablePixelMicrosoft } from './microsoft' diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/linkedin.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/linkedin.ts index f041dcb559..102d9f4be3 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/linkedin.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/linkedin.ts @@ -1,12 +1,17 @@ -import { PIXEL_EVENTS } from './constants' +import { enablePixel } from './sendAllPixels' +import { PixelEvent, PixelEventMap } from './types' import { sendPixel } from './utils' -const events = { - [PIXEL_EVENTS.INIT]: 10759506, - [PIXEL_EVENTS.CONNECT_WALLET]: 10759514, - [PIXEL_EVENTS.POST_TRADE]: 10759522, +const events: PixelEventMap = { + [PixelEvent.INIT]: 10759506, + [PixelEvent.CONNECT_WALLET]: 10759514, + [PixelEvent.POST_TRADE]: 10759522, } -export const sendLinkedinEvent = sendPixel((event) => { +const sendLinkedinEvent = sendPixel((event) => { window.lintrk?.('track', { conversion_id: events[event] }) }) + +export function enablePixelLinkedin() { + enablePixel(events, sendLinkedinEvent) +} diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/microsoft.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/microsoft.ts index db9ad254b0..618f30e3af 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/microsoft.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/microsoft.ts @@ -1,13 +1,18 @@ -import { PIXEL_EVENTS } from './constants' +import { enablePixel } from './sendAllPixels' +import { PixelEvent, PixelEventMap } from './types' import { sendPixel } from './utils' -const events = { - [PIXEL_EVENTS.INIT]: 'page_view', - [PIXEL_EVENTS.CONNECT_WALLET]: 'begin_checkout', - [PIXEL_EVENTS.POST_TRADE]: 'purchase', +const events: PixelEventMap = { + [PixelEvent.INIT]: 'page_view', + [PixelEvent.CONNECT_WALLET]: 'begin_checkout', + [PixelEvent.POST_TRADE]: 'purchase', } -export const sendMicrosoftEvent = sendPixel((event) => { +const sendMicrosoftEvent = sendPixel((event) => { window.uetq = window.uetq || [] window.uetq.push('event', events[event], {}) }) + +export function enablePixelMicrosoft() { + enablePixel(events, sendMicrosoftEvent) +} diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/paved.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/paved.ts index a26d0eb24c..67b1bccd8b 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/paved.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/paved.ts @@ -1,12 +1,17 @@ -import { PIXEL_EVENTS } from './constants' +import { enablePixel } from './sendAllPixels' +import { PixelEvent, PixelEventMap } from './types' import { sendPixel } from './utils' -const events = { - [PIXEL_EVENTS.INIT]: 'search', - [PIXEL_EVENTS.CONNECT_WALLET]: 'sign_up', - [PIXEL_EVENTS.POST_TRADE]: 'purchase', +const events: PixelEventMap = { + [PixelEvent.INIT]: 'search', + [PixelEvent.CONNECT_WALLET]: 'sign_up', + [PixelEvent.POST_TRADE]: 'purchase', } -export const sendPavedEvent = sendPixel((event: PIXEL_EVENTS) => { +const sendPavedEvent = sendPixel((event) => { window.pvd?.('event', events[event]) }) + +export function enablePixelPaved() { + enablePixel(events, sendPavedEvent) +} diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/reddit.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/reddit.ts index c979b6ee08..eb77a53bd7 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/reddit.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/reddit.ts @@ -1,12 +1,17 @@ -import { PIXEL_EVENTS } from './constants' +import { enablePixel } from './sendAllPixels' +import { PixelEvent, PixelEventMap } from './types' import { sendPixel } from './utils' -const events = { - [PIXEL_EVENTS.INIT]: 'Lead', - [PIXEL_EVENTS.CONNECT_WALLET]: 'SignUp', - [PIXEL_EVENTS.POST_TRADE]: 'Purchase', +const events: PixelEventMap = { + [PixelEvent.INIT]: 'Lead', + [PixelEvent.CONNECT_WALLET]: 'SignUp', + [PixelEvent.POST_TRADE]: 'Purchase', } -export const sendRedditEvent = sendPixel((event) => { +const sendRedditEvent = sendPixel((event) => { window.rdt?.('track', events[event]) }) + +export function enablePixelReddit() { + enablePixel(events, sendRedditEvent) +} diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/sendAllPixels.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/sendAllPixels.ts new file mode 100644 index 0000000000..67eb45570d --- /dev/null +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/sendAllPixels.ts @@ -0,0 +1,35 @@ +import { PixelEvent, PixelEventMap, SendPixel } from './types' + +const sendPixelCallbacks: Map = new Map() + +/** + * Sends all the enabled pixels for the given event + * + * @param event event to send + */ +export function sendAllPixels(event: PixelEvent): void { + const callbacks = sendPixelCallbacks.get(event) + if (!callbacks) return + + callbacks.forEach((callback) => callback(event)) +} + +function _enablePixel(event: PixelEvent, sendPixel: SendPixel) { + let callbacks = sendPixelCallbacks.get(event) + if (!callbacks) { + callbacks = [] + sendPixelCallbacks.set(event, callbacks) + } + + callbacks.push(sendPixel) +} + +/** + * Register a pixel callback for the given set of events events + */ +export function enablePixel(eventMap: PixelEventMap, sendPixel: SendPixel) { + Object.keys(eventMap).forEach((event) => { + const e = event as PixelEvent + _enablePixel(e, sendPixel) + }) +} diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/twitter.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/twitter.ts index 9f5969461d..40acb0f7f1 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/twitter.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/twitter.ts @@ -1,12 +1,17 @@ -import { PIXEL_EVENTS } from './constants' +import { enablePixel } from './sendAllPixels' +import { PixelEvent, PixelEventMap } from './types' import { sendPixel } from './utils' -const events = { - [PIXEL_EVENTS.INIT]: 'tw-oddz2-oddz8', - [PIXEL_EVENTS.CONNECT_WALLET]: 'tw-oddz2-oddza', - [PIXEL_EVENTS.POST_TRADE]: 'tw-oddz2-oddzb', +const events: PixelEventMap = { + [PixelEvent.INIT]: 'tw-oddz2-oddz8', + [PixelEvent.CONNECT_WALLET]: 'tw-oddz2-oddza', + [PixelEvent.POST_TRADE]: 'tw-oddz2-oddzb', } -export const sendTwitterEvent = sendPixel((event: PIXEL_EVENTS) => { +export const sendTwitterEvent = sendPixel((event) => { window.twq?.('event', events[event], {}) }) + +export function enablePixelTwitter() { + enablePixel(events, sendTwitterEvent) +} diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/types.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/types.ts new file mode 100644 index 0000000000..c0a554b750 --- /dev/null +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/types.ts @@ -0,0 +1,9 @@ +export enum PixelEvent { + INIT = 'init', + CONNECT_WALLET = 'connect_wallet', + POST_TRADE = 'post_trade', +} + +export type SendPixel = (event: PixelEvent) => void + +export type PixelEventMap = Record diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/utils.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/utils.ts index 531f144a0c..fecc635b3a 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/utils.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/utils.ts @@ -1,8 +1,7 @@ -import { PIXEL_ENABLED, PIXEL_EVENTS } from './constants' +import { PIXEL_ENABLED } from './constants' +import { SendPixel } from './types' -type SendPixelFn = (event: PIXEL_EVENTS) => void - -export function sendPixel(sendFn: SendPixelFn): SendPixelFn { +export function sendPixel(sendFn: SendPixel): SendPixel { return (event) => { if (!PIXEL_ENABLED) { return From 0cf6fc87ec735d42aa4b09b236618492ef5c2bc6 Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Fri, 8 Sep 2023 21:10:47 +0200 Subject: [PATCH 03/36] chore: remove pixels (#3119) --- apps/cowswap-frontend/index.html | 128 ------------------ .../analytics/hooks/useAnalyticsReporter.ts | 25 ++-- 2 files changed, 9 insertions(+), 144 deletions(-) diff --git a/apps/cowswap-frontend/index.html b/apps/cowswap-frontend/index.html index 672c7f28b6..37517addc5 100644 --- a/apps/cowswap-frontend/index.html +++ b/apps/cowswap-frontend/index.html @@ -36,134 +36,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts b/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts index 075368b58a..4397c75772 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts +++ b/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts @@ -18,13 +18,6 @@ import { useGetMarketDimension } from './useGetMarketDimension' import { googleAnalytics } from '../googleAnalytics' import { GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY } from '../index' import { PixelEvent, sendAllPixels } from '../pixel' -import { - enablePixelFacebook, - enablePixelMicrosoft, - enablePixelPaved, - enablePixelReddit, - enablePixelTwitter, -} from '../pixel' import { Dimensions } from '../types' export function sendTiming(timingCategory: any, timingVar: any, timingValue: any, timingLabel: any) { @@ -109,15 +102,15 @@ export function useAnalyticsReporter() { // Handle initiate pixel tracking useEffect(() => { if (!initiatedPixel) { - // Init all pixels - const enablePixelFunctions = [ - enablePixelFacebook, - enablePixelMicrosoft, - enablePixelPaved, - enablePixelReddit, - enablePixelTwitter, - ] - enablePixelFunctions.forEach((enablePixel) => enablePixel()) + // // Init all pixels + // const enablePixelFunctions = [ + // enablePixelFacebook, + // enablePixelMicrosoft, + // enablePixelPaved, + // enablePixelReddit, + // enablePixelTwitter, + // ] + // enablePixelFunctions.forEach((enablePixel) => enablePixel()) // Sent sendAllPixels(PixelEvent.INIT) From 19b3b8e494fd70ab6f5ba58572347b7b1b2ac8c3 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Mon, 11 Sep 2023 10:55:57 +0600 Subject: [PATCH 04/36] fix(eth-flow): additionally check eth-flow order id in smart-contract (#3103) * fix: trim eth-flow contract abi json file * fix(eth-flow): additionally check eth-flow order id in smart-contract * chore: remove unused ABI * chore: rename checkEthFlowOrderExists --- .../src/legacy/hooks/useContract.ts | 6 +- .../swap/hooks/useCheckEthFlowOrderExists.ts | 39 +++++ .../modules/swap/hooks/useEthFlowContext.ts | 18 +-- .../modules/swap/services/ethFlow/index.ts | 8 +- .../ethFlow/steps/calculateUniqueOrderId.ts | 8 +- .../src/modules/swap/services/types.ts | 3 +- libs/abis/src/abis/CoWSwapEthFlow.json | 152 ++++++++++++++++++ libs/abis/src/index.ts | 6 +- 8 files changed, 211 insertions(+), 29 deletions(-) create mode 100644 apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts create mode 100644 libs/abis/src/abis/CoWSwapEthFlow.json diff --git a/apps/cowswap-frontend/src/legacy/hooks/useContract.ts b/apps/cowswap-frontend/src/legacy/hooks/useContract.ts index 7f68aa81e6..f4f421d9ef 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useContract.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useContract.ts @@ -9,7 +9,6 @@ import { Erc721, Erc1155, Weth, - CoWSwapEthFlowJson, ArgentWalletDetectorAbi, Eip2612Abi, EnsPublicResolverAbi, @@ -26,6 +25,7 @@ import { CoWSwapEthFlow, vCowAbi, UniswapInterfaceMulticall, + CoWSwapEthFlowAbi, } from '@cowswap/abis' import { Contract } from '@ethersproject/contracts' import type { JsonRpcProvider } from '@ethersproject/providers' @@ -114,8 +114,6 @@ export function useInterfaceMulticall() { return useContract(MULTICALL_ADDRESS, MulticallABI, false) as UniswapInterfaceMulticall } -const COWSWAP_ETHFLOW_ABI = CoWSwapEthFlowJson.abi - export function useEthFlowContract(): CoWSwapEthFlow | null { const { chainId } = useWalletInfo() @@ -123,7 +121,7 @@ export function useEthFlowContract(): CoWSwapEthFlow | null { const contractAddress = chainId ? COWSWAP_ETHFLOW_CONTRACT_ADDRESS[contractEnv][chainId] : undefined - return useContract(contractAddress, COWSWAP_ETHFLOW_ABI, true) + return useContract(contractAddress, CoWSwapEthFlowAbi, true) } export function useGP2SettlementContract(): GPv2Settlement | null { diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts new file mode 100644 index 0000000000..5c6226a6e0 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts @@ -0,0 +1,39 @@ +import { useAtomValue } from 'jotai' +import { useCallback } from 'react' + +import { ZERO_ADDRESS } from 'legacy/constants/misc' +import { useEthFlowContract } from 'legacy/hooks/useContract' + +import { ethFlowInFlightOrderIdsAtom } from '../state/EthFlow/ethFlowInFlightOrderIdsAtom' + +export interface EthFlowOrderExistsCallback { + (orderId: string, orderDigest: string): Promise +} + +export function useCheckEthFlowOrderExists(): EthFlowOrderExistsCallback { + const ethFlowInFlightOrderIds = useAtomValue(ethFlowInFlightOrderIdsAtom) + const ethFlowContract = useEthFlowContract() + + return useCallback( + async (orderId: string, orderDigest: string) => { + if (ethFlowInFlightOrderIds.includes(orderId)) { + return true + } + + if (ethFlowContract) { + try { + const { owner } = await ethFlowContract.callStatic.orders(orderDigest) + + return owner.toLowerCase() !== ZERO_ADDRESS + } catch (e) { + console.error('Eth-flow order existing check error: ', e) + + return false + } + } + + return false + }, + [ethFlowInFlightOrderIds, ethFlowContract] + ) +} diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts index 93adb7d077..29fdcaaa2a 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts @@ -1,5 +1,4 @@ -import { useAtomValue, useSetAtom } from 'jotai' -import { useCallback } from 'react' +import { useSetAtom } from 'jotai' import { OrderKind } from '@cowprotocol/cow-sdk' @@ -9,23 +8,18 @@ import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' import { FlowType, getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext' import { EthFlowContext } from 'modules/swap/services/types' -import { - addInFlightOrderIdAtom, - ethFlowInFlightOrderIdsAtom, -} from 'modules/swap/state/EthFlow/ethFlowInFlightOrderIdsAtom' +import { addInFlightOrderIdAtom } from 'modules/swap/state/EthFlow/ethFlowInFlightOrderIdsAtom' + +import { useCheckEthFlowOrderExists } from './useCheckEthFlowOrderExists' export function useEthFlowContext(): EthFlowContext | null { const contract = useEthFlowContract() const baseProps = useBaseFlowContextSetup() const addTransaction = useTransactionAdder() - const ethFlowInFlightOrderIds = useAtomValue(ethFlowInFlightOrderIdsAtom) const addInFlightOrderId = useSetAtom(addInFlightOrderIdAtom) - const checkInFlightOrderIdExists = useCallback( - (orderId: string) => ethFlowInFlightOrderIds.includes(orderId), - [ethFlowInFlightOrderIds] - ) + const checkEthFlowOrderExists = useCheckEthFlowOrderExists() const baseContext = getFlowContext({ baseProps, @@ -39,7 +33,7 @@ export function useEthFlowContext(): EthFlowContext | null { ...baseContext, contract, addTransaction, - checkInFlightOrderIdExists, + checkEthFlowOrderExists, addInFlightOrderId, } } diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts index ba405d9814..0869204e42 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/index.ts @@ -25,7 +25,7 @@ export async function ethFlow( appDataInfo, dispatch, orderParams: orderParamsOriginal, - checkInFlightOrderIdExists, + checkEthFlowOrderExists, addInFlightOrderId, } = ethFlowContext @@ -40,11 +40,7 @@ export async function ethFlow( swapConfirmManager.sendTransaction(context.trade) logTradeFlow('ETH FLOW', 'STEP 3: Get Unique Order Id (prevent collisions)') - const { orderId, orderParams } = await calculateUniqueOrderId( - orderParamsOriginal, - contract, - checkInFlightOrderIdExists - ) + const { orderId, orderParams } = await calculateUniqueOrderId(orderParamsOriginal, contract, checkEthFlowOrderExists) try { logTradeFlow('ETH FLOW', 'STEP 4: sign order') diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts index 7ff21788dd..c8e71b4c9b 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts @@ -10,6 +10,8 @@ import { logTradeFlow } from 'modules/trade/utils/logger' import { MAX_VALID_TO_EPOCH } from 'utils/time' +import { EthFlowOrderExistsCallback } from '../../../hooks/useCheckEthFlowOrderExists' + export interface UniqueOrderIdResult { orderId: string orderParams: PostOrderParams // most cases, will be the same as the ones in the parameter, but it might be modified to make the order unique @@ -33,7 +35,7 @@ function incrementFee(params: PostOrderParams): PostOrderParams { export async function calculateUniqueOrderId( orderParams: PostOrderParams, ethFlowContract: CoWSwapEthFlow, - checkInFlightOrderIdExists: (orderId: string) => boolean + checkEthFlowOrderExists: EthFlowOrderExistsCallback ): Promise { logTradeFlow('ETH FLOW', '[EthFlow::calculateUniqueOrderId] - Calculate unique order Id', orderParams) const { chainId } = orderParams @@ -59,11 +61,11 @@ export async function calculateUniqueOrderId( sellAmount: orderParams.inputAmount.quotient.toString(), fee: orderParams.feeAmount?.quotient.toString(), } - if (checkInFlightOrderIdExists(orderId)) { + if (await checkEthFlowOrderExists(orderId, orderDigest)) { logTradeFlow('ETH FLOW', '[calculateUniqueOrderId] ❌ Collision detected: ' + orderId, logParams) // Recursive call, increment one fee until we get an unique order Id - return calculateUniqueOrderId(incrementFee(orderParams), ethFlowContract, checkInFlightOrderIdExists) + return calculateUniqueOrderId(incrementFee(orderParams), ethFlowContract, checkEthFlowOrderExists) } logTradeFlow('ETH FLOW', '[calculateUniqueOrderId] ✅ Order Id is Unique' + orderId, logParams) diff --git a/apps/cowswap-frontend/src/modules/swap/services/types.ts b/apps/cowswap-frontend/src/modules/swap/services/types.ts index e8c963faba..5dd98add18 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/types.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/types.ts @@ -14,6 +14,7 @@ import { AppDataInfo, UploadAppDataParams } from 'modules/appData' import { SwapConfirmManager } from 'modules/swap/hooks/useSwapConfirmManager' import { SwapFlowAnalyticsContext } from 'modules/trade/utils/analytics' +import { EthFlowOrderExistsCallback } from '../hooks/useCheckEthFlowOrderExists' import { FlowType } from '../hooks/useFlowContext' export interface BaseFlowContext { @@ -47,7 +48,7 @@ export type SwapFlowContext = BaseFlowContext & { export type EthFlowContext = BaseFlowContext & { contract: CoWSwapEthFlow addTransaction: ReturnType - checkInFlightOrderIdExists: (orderId: string) => boolean + checkEthFlowOrderExists: EthFlowOrderExistsCallback addInFlightOrderId: (orderId: string) => void } diff --git a/libs/abis/src/abis/CoWSwapEthFlow.json b/libs/abis/src/abis/CoWSwapEthFlow.json new file mode 100644 index 0000000000..2e76a24b83 --- /dev/null +++ b/libs/abis/src/abis/CoWSwapEthFlow.json @@ -0,0 +1,152 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "contract IERC20", + "name": "buyToken", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sellAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "buyAmount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "appData", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "validTo", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "partiallyFillable", + "type": "bool" + }, + { + "internalType": "int64", + "name": "quoteId", + "type": "int64" + } + ], + "internalType": "struct EthFlowOrder.Data", + "name": "order", + "type": "tuple" + } + ], + "name": "createOrder", + "outputs": [ + { + "internalType": "bytes32", + "name": "orderHash", + "type": "bytes32" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "contract IERC20", + "name": "buyToken", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sellAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "buyAmount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "appData", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "validTo", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "partiallyFillable", + "type": "bool" + }, + { + "internalType": "int64", + "name": "quoteId", + "type": "int64" + } + ], + "internalType": "struct EthFlowOrder.Data", + "name": "order", + "type": "tuple" + } + ], + "name": "invalidateOrder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "orders", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint32", + "name": "validTo", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/libs/abis/src/index.ts b/libs/abis/src/index.ts index 0c312d27c5..7f3cce77fd 100644 --- a/libs/abis/src/index.ts +++ b/libs/abis/src/index.ts @@ -11,6 +11,8 @@ import _MerkleDropAbi from './abis/MerkleDrop.json' import _TokenDistroAbi from './abis/TokenDistro.json' +import _CoWSwapEthFlowAbi from './abis/CoWSwapEthFlow.json' + import _ethFlowBarnJson from '@cowprotocol/ethflowcontract/networks.barn.json' import _ethFlowProdJson from '@cowprotocol/ethflowcontract/networks.prod.json' @@ -20,8 +22,6 @@ import _ArgentWalletContractAbi from './abis-legacy/argent-wallet-contract.json' import _ArgentWalletDetectorAbi from './abis-legacy/argent-wallet-detector.json' -import _CoWSwapEthFlowJson from '@cowprotocol/ethflowcontract/artifacts/CoWSwapEthFlow.sol/CoWSwapEthFlow.json' - import _Eip2612Abi from './abis-legacy/eip_2612.json' import _EnsPublicResolverAbi from './abis-legacy/ens-public-resolver.json' @@ -46,6 +46,7 @@ export const vCowAbi = _vCowAbi export const SignatureVerifierMuxerAbi = _SignatureVerifierMuxerAbi export const MerkleDropAbi = _MerkleDropAbi export const TokenDistroAbi = _TokenDistroAbi +export const CoWSwapEthFlowAbi = _CoWSwapEthFlowAbi export * from './generated/custom' export type { GPv2Order } from './generated/custom/ComposableCoW' @@ -71,7 +72,6 @@ export const ethFlowBarnJson = _ethFlowBarnJson export const ethFlowProdJson = _ethFlowProdJson export const ArgentWalletContractAbi = _ArgentWalletContractAbi export const ArgentWalletDetectorAbi = _ArgentWalletDetectorAbi -export const CoWSwapEthFlowJson = _CoWSwapEthFlowJson export const Eip2612Abi = _Eip2612Abi export const EnsPublicResolverAbi = _EnsPublicResolverAbi export const EnsAbi = _EnsAbi From d45408cf1881db1e9ea74427f262717d12a24b1b Mon Sep 17 00:00:00 2001 From: Leandro Date: Tue, 19 Sep 2023 03:03:41 -0700 Subject: [PATCH 05/36] chore(feature-flags): remove completed feature flags (#3132) * chore: remove ethFlowBundlingEnabled feature flag * chore: remove txBundlingEnabled feature flag * refactor: merge safe bundling of wrap and approval It was fomerly controlled by 2 independent feature flags Now it only needs to know whether the wallet used supports it * chore: remove partialFillsEnabled feature flag * chore: remove advancedOrdersEnabled feature flag * fix: fix unit tests mocking * fix: add TWAP orders back to main menu --- .../useIsEthFlowBundlingEnabled.ts | 11 ---- .../featureFlags/useIsTxBundlingEnabled.ts | 11 ---- .../hooks/useIsAdvancedOrdersEnabled.ts | 7 --- .../src/legacy/components/Header/index.tsx | 8 +-- .../containers/TradeWidgetLinks/index.tsx | 63 ++++++++++--------- .../LimitOrdersConfirmModal/index.tsx | 6 +- .../containers/LimitOrdersWidget/index.tsx | 7 +-- .../limitOrdersPropsChecker.ts | 2 - .../containers/SettingsWidget/index.tsx | 11 +--- .../hooks/useHandleOrderPlacement.test.ts | 23 +++++-- .../hooks/useIsSafeApprovalBundle.ts | 7 ++- .../limitOrders/hooks/useTradeFlowContext.ts | 6 +- .../pure/LimitOrdersDetails/index.cosmos.tsx | 5 +- .../pure/LimitOrdersDetails/index.tsx | 18 +----- .../limitOrders/pure/OrderType/index.tsx | 22 +++---- .../pure/Settings/index.cosmos.tsx | 1 - .../limitOrders/pure/Settings/index.tsx | 6 +- .../modules/mainMenu/constants/mainMenu.tsx | 6 ++ .../src/modules/mainMenu/hooks.ts | 12 ---- .../src/modules/mainMenu/index.ts | 2 - .../modules/mainMenu/pure/MenuTree/index.tsx | 10 +-- .../src/modules/mainMenu/utils.ts | 34 ---------- .../swap/helpers/getSwapButtonState.ts | 13 ++-- .../modules/swap/hooks/useIsSafeEthFlow.ts | 6 +- .../swap/hooks/useSwapButtonContext.ts | 10 +-- .../src/modules/swap/pure/warnings.tsx | 17 +++-- .../hooks/useTradeFormValidationContext.ts | 7 +-- .../services/validateTradeForm.ts | 9 +-- .../src/modules/tradeFormValidation/types.ts | 2 +- .../src/pages/AdvancedOrders/index.tsx | 18 ------ 30 files changed, 113 insertions(+), 247 deletions(-) delete mode 100644 apps/cowswap-frontend/src/common/hooks/featureFlags/useIsEthFlowBundlingEnabled.ts delete mode 100644 apps/cowswap-frontend/src/common/hooks/featureFlags/useIsTxBundlingEnabled.ts delete mode 100644 apps/cowswap-frontend/src/common/hooks/useIsAdvancedOrdersEnabled.ts delete mode 100644 apps/cowswap-frontend/src/modules/mainMenu/hooks.ts delete mode 100644 apps/cowswap-frontend/src/modules/mainMenu/utils.ts diff --git a/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsEthFlowBundlingEnabled.ts b/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsEthFlowBundlingEnabled.ts deleted file mode 100644 index 83e356e127..0000000000 --- a/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsEthFlowBundlingEnabled.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useIsBundlingSupported } from 'modules/wallet' - -import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags' - -export function useIsEthFlowBundlingEnabled(): boolean { - const isBundlingSupported = useIsBundlingSupported() - - const { ethFlowBundlingEnabled } = useFeatureFlags() - - return isBundlingSupported && ethFlowBundlingEnabled -} diff --git a/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsTxBundlingEnabled.ts b/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsTxBundlingEnabled.ts deleted file mode 100644 index d4fc5a328d..0000000000 --- a/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsTxBundlingEnabled.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useIsBundlingSupported } from 'modules/wallet' - -import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags' - -export function useIsTxBundlingEnabled(): boolean { - const isBundlingSupported = useIsBundlingSupported() - - const { txBundlingEnabled } = useFeatureFlags() - - return isBundlingSupported && txBundlingEnabled -} diff --git a/apps/cowswap-frontend/src/common/hooks/useIsAdvancedOrdersEnabled.ts b/apps/cowswap-frontend/src/common/hooks/useIsAdvancedOrdersEnabled.ts deleted file mode 100644 index b5b2f65df5..0000000000 --- a/apps/cowswap-frontend/src/common/hooks/useIsAdvancedOrdersEnabled.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useFeatureFlags } from './featureFlags/useFeatureFlags' - -export function useIsAdvancedOrdersEnabled(): boolean | undefined { - const { advancedOrdersEnabled } = useFeatureFlags() - - return advancedOrdersEnabled -} diff --git a/apps/cowswap-frontend/src/legacy/components/Header/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/index.tsx index 1c217fa842..b2f63f0a63 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/index.tsx @@ -15,7 +15,7 @@ import { addBodyClass, removeBodyClass } from 'legacy/utils/toggleBodyClass' import { OrdersPanel } from 'modules/account/containers/OrdersPanel' import { useInjectedWidgetParams } from 'modules/injectedWidget' -import { MainMenuContext, useMenuItems } from 'modules/mainMenu' +import { MainMenuContext } from 'modules/mainMenu' import { MenuTree } from 'modules/mainMenu/pure/MenuTree' import { useSwapRawState } from 'modules/swap/hooks/useSwapRawState' import { useNativeCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalance' @@ -73,8 +73,6 @@ export default function Header() { !isOrdersPanelOpen && removeBodyClass('noScroll') } - const menuItems = useMenuItems() - const navigate = useNavigate() const isUpToLarge = useMediaQuery(upToLarge) @@ -139,9 +137,7 @@ export default function Header() { )} - {!isInjectedWidgetMode && ( - - )} + {!isInjectedWidgetMode && } diff --git a/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/index.tsx b/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/index.tsx index 2aebee6968..71eba2d6cc 100644 --- a/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/index.tsx +++ b/apps/cowswap-frontend/src/modules/application/containers/TradeWidgetLinks/index.tsx @@ -12,15 +12,15 @@ import { FeatureGuard } from 'common/containers/FeatureGuard' import * as styledEl from './styled' interface MenuItemConfig { - route: RoutesValues; - label: string; - featureGuard?: string; - onClick?: () => void; - badgeText?: string; - badgeType?: BadgeType; + route: RoutesValues + label: string + featureGuard?: string + onClick?: () => void + badgeText?: string + badgeType?: BadgeType } -export type BadgeType = 'information' | 'success' | 'alert' | 'alert2' | 'default'; +export type BadgeType = 'information' | 'success' | 'alert' | 'alert2' | 'default' const MENU_ITEMS: MenuItemConfig[] = [ { route: Routes.SWAP, label: 'Swap' }, @@ -28,15 +28,14 @@ const MENU_ITEMS: MenuItemConfig[] = [ { route: Routes.ADVANCED_ORDERS, label: 'TWAP', - featureGuard: 'advancedOrdersEnabled', badgeText: 'NEW!', - badgeType: 'alert2' + badgeType: 'alert2', }, ] interface TradeWidgetLinksProps { - highlightedBadgeText?: string; - highlightedBadgeType?: BadgeType; + highlightedBadgeText?: string + highlightedBadgeType?: BadgeType } export function TradeWidgetLinks({ highlightedBadgeText, highlightedBadgeType }: TradeWidgetLinksProps) { @@ -45,21 +44,21 @@ export function TradeWidgetLinks({ highlightedBadgeText, highlightedBadgeType }: const buildMenuItem = useCallback( (item: MenuItemConfig) => { - const routePath = parameterizeTradeRoute(tradeContext, item.route); - - const isActive = !!matchPath(location.pathname, routePath); - + const routePath = parameterizeTradeRoute(tradeContext, item.route) + + const isActive = !!matchPath(location.pathname, routePath) + const menuItem = ( - - ); - + ) + return item.featureGuard ? ( {menuItem} @@ -69,17 +68,23 @@ export function TradeWidgetLinks({ highlightedBadgeText, highlightedBadgeType }: ) }, [location.pathname, tradeContext, highlightedBadgeText, highlightedBadgeType] - ); + ) return {MENU_ITEMS.map(buildMenuItem)} } -const MenuItem = ({ routePath, item, isActive, badgeText, badgeType }: { - routePath: string; - item: MenuItemConfig; - isActive: boolean; - badgeText?: string; - badgeType?: BadgeType; +const MenuItem = ({ + routePath, + item, + isActive, + badgeText, + badgeType, +}: { + routePath: string + item: MenuItemConfig + isActive: boolean + badgeText?: string + badgeType?: BadgeType }) => ( diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx index 7416a35a79..96ca662ee9 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx @@ -1,5 +1,4 @@ -import { useAtom } from 'jotai' -import { useAtomValue } from 'jotai' +import { useAtom, useAtomValue } from 'jotai' import React from 'react' import { PriceImpact } from 'legacy/hooks/usePriceImpact' @@ -15,7 +14,6 @@ import { limitRateAtom } from 'modules/limitOrders/state/limitRateAtom' import { partiallyFillableOverrideAtom } from 'modules/limitOrders/state/partiallyFillableOverride' import { TradeConfirmation, TradeConfirmModal, useTradeConfirmActions } from 'modules/trade' -import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags' import { useRateInfoParams } from 'common/hooks/useRateInfoParams' import { CurrencyPreviewInfo } from 'common/pure/CurrencyAmountPreview' import { TokenSymbol } from 'common/pure/TokenSymbol' @@ -38,7 +36,6 @@ export function LimitOrdersConfirmModal(props: LimitOrdersConfirmModalProps) { const executionPrice = useAtomValue(executionPriceAtom) const limitRateState = useAtomValue(limitRateAtom) const partiallyFillableOverride = useAtom(partiallyFillableOverrideAtom) - const { partialFillsEnabled } = useFeatureFlags() const { amount: inputAmount } = inputCurrencyInfo const { amount: outputAmount } = outputCurrencyInfo @@ -83,7 +80,6 @@ export function LimitOrdersConfirmModal(props: LimitOrdersConfirmModalProps) { settingsState={settingsState} executionPrice={executionPrice} partiallyFillableOverride={partiallyFillableOverride} - featurePartialFillsEnabled={partialFillsEnabled} /> diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx index 5bd2561de8..f6443a6725 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx @@ -15,7 +15,6 @@ import { BulletListItem, UnlockWidgetScreen } from 'modules/trade/pure/UnlockWid import { TradeFormValidation, useGetTradeFormValidation } from 'modules/tradeFormValidation' import { useSetTradeQuoteParams, useTradeQuote } from 'modules/tradeQuote' -import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags' import { useRateInfoParams } from 'common/hooks/useRateInfoParams' import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types' @@ -79,7 +78,6 @@ export function LimitOrdersWidget() { const { isLoading: isRateLoading } = useTradeQuote() const rateInfoParams = useRateInfoParams(inputCurrencyAmount, outputCurrencyAmount) const partiallyFillableOverride = useAtom(partiallyFillableOverrideAtom) - const { partialFillsEnabled } = useFeatureFlags() const widgetActions = useLimitOrdersWidgetActions() const { showRecipient, expertMode: isExpertMode } = settingsState @@ -125,7 +123,6 @@ export function LimitOrdersWidget() { isExpertMode, recipient, partiallyFillableOverride, - featurePartialFillsEnabled: partialFillsEnabled, rateInfoParams, priceImpact, tradeContext, @@ -147,7 +144,6 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => { isRateLoading, widgetActions, partiallyFillableOverride, - featurePartialFillsEnabled, showRecipient, isExpertMode, recipient, @@ -169,7 +165,7 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => { return isRateLoading }, [isRateLoading, inputCurrency, outputCurrency]) - const isPartiallyFillable = featurePartialFillsEnabled && settingsState.partialFillsEnabled + const isPartiallyFillable = settingsState.partialFillsEnabled const updateLimitOrdersState = useSetAtom(updateLimitOrdersRawStateAtom) @@ -220,7 +216,6 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => { )} diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts index c2f0aa9d54..1aedd73326 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts @@ -27,7 +27,6 @@ export interface LimitOrdersProps { recipient: string | null partiallyFillableOverride: PartiallyFillableOverrideDispatcherType - featurePartialFillsEnabled: boolean rateInfoParams: RateInfoParams priceImpact: PriceImpact @@ -50,7 +49,6 @@ export function limitOrdersPropsChecker(a: LimitOrdersProps, b: LimitOrdersProps a.recipient === b.recipient && a.widgetActions === b.widgetActions && a.partiallyFillableOverride[0] === b.partiallyFillableOverride[0] && - a.featurePartialFillsEnabled === b.featurePartialFillsEnabled && checkRateInfoParams(a.rateInfoParams, b.rateInfoParams) && checkPriceImpact(a.priceImpact, b.priceImpact) && checkTradeFlowContext(a.tradeContext, b.tradeContext) && diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/SettingsWidget/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/SettingsWidget/index.tsx index b76eba69e7..12a9079572 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/SettingsWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/SettingsWidget/index.tsx @@ -1,12 +1,10 @@ -import { useSetAtom } from 'jotai' -import { useAtomValue } from 'jotai' +import { useAtomValue, useSetAtom } from 'jotai' import React, { useCallback, useState } from 'react' import { Menu, MenuItem } from '@reach/menu-button' import { ExpertModeIndicator, MenuContent, SettingsButton, SettingsIcon } from 'modules/trade/pure/Settings' -import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags' import { ExpertModeModal } from 'common/pure/ExpertModeModal' import { Settings } from '../../pure/Settings' @@ -20,7 +18,6 @@ export function SettingsWidget() { const settingsState = useAtomValue(limitOrdersSettingsAtom) const updateSettingsState = useSetAtom(updateLimitOrdersSettingsAtom) const [showExpertConfirm, setShowExpertConfirm] = useState(false) - const { partialFillsEnabled } = useFeatureFlags() const onStateChanged = useCallback( (state: Partial) => { @@ -60,11 +57,7 @@ export function SettingsWidget() { void 0}> - + diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts index 43660a406d..452b9da788 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts @@ -8,8 +8,8 @@ import { useSafeBundleFlowContext } from 'modules/limitOrders/hooks/useSafeBundl import { safeBundleFlow } from 'modules/limitOrders/services/safeBundleFlow' import { tradeFlow } from 'modules/limitOrders/services/tradeFlow' import { TradeFlowContext } from 'modules/limitOrders/services/types' +import { useIsBundlingSupported } from 'modules/wallet' -import { useIsTxBundlingEnabled } from 'common/hooks/featureFlags/useIsTxBundlingEnabled' import { useNeedsApproval } from 'common/hooks/useNeedsApproval' import { TradeAmounts } from 'common/types' import { withModalProvider } from 'utils/withModalProvider' @@ -25,7 +25,22 @@ jest.mock('modules/limitOrders/services/safeBundleFlow') jest.mock('modules/limitOrders/hooks/useSafeBundleFlowContext') jest.mock('common/hooks/useNeedsApproval') -jest.mock('common/hooks/featureFlags/useIsTxBundlingEnabled') +jest.mock('modules/wallet', () => { + const actual = jest.requireActual('modules/wallet') + + return new Proxy(actual, { + get: (target, property) => { + switch (property) { + case 'useIsBundlingSupported': { + return jest.fn() + } + default: { + return target[property] + } + } + }, + }) +}) jest.mock('legacy/components/analytics/hooks/useAnalyticsReporter.ts') const mockTradeFlow = tradeFlow as jest.MockedFunction @@ -33,7 +48,7 @@ const mockSafeBundleFlow = safeBundleFlow as jest.MockedFunction const mockUseNeedsApproval = useNeedsApproval as jest.MockedFunction -const mockUseIsTxBundlingEnabled = useIsTxBundlingEnabled as jest.MockedFunction +const mockIsBundlingSupported = useIsBundlingSupported as jest.MockedFunction const tradeContextMock = { postOrderParams: { partiallyFillable: true } } as any as TradeFlowContext const priceImpactMock: PriceImpact = { @@ -65,7 +80,7 @@ describe('useHandleOrderPlacement', () => { mockSafeBundleFlow.mockImplementation(() => Promise.resolve('')) mockUseSafeBundleFlowContext.mockImplementation(() => null) mockUseNeedsApproval.mockImplementation(() => false) - mockUseIsTxBundlingEnabled.mockImplementation(() => false) + mockIsBundlingSupported.mockImplementation(() => true) }) it('When a limit order placed, then the recipient value should be deleted', async () => { diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts index aad313adb9..7855d436f6 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts @@ -2,12 +2,13 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { useIsTxBundlingEnabled } from 'common/hooks/featureFlags/useIsTxBundlingEnabled' +import { useIsBundlingSupported } from 'modules/wallet' + import { useNeedsApproval } from 'common/hooks/useNeedsApproval' export function useIsSafeApprovalBundle(amount: Nullish>): boolean { const needsApproval = useNeedsApproval(amount) - const isTxBundlingEnabled = useIsTxBundlingEnabled() + const isBundlingSupported = useIsBundlingSupported() - return isTxBundlingEnabled && needsApproval + return isBundlingSupported && needsApproval } diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts index ce62a2556f..3d0f49ba9c 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts @@ -16,8 +16,6 @@ import { limitOrdersSettingsAtom } from 'modules/limitOrders/state/limitOrdersSe import { useTradeQuote } from 'modules/tradeQuote' import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet' -import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags' - import { useLimitOrdersDerivedState } from './useLimitOrdersDerivedState' export function useTradeFlowContext(): TradeFlowContext | null { @@ -32,7 +30,6 @@ export function useTradeFlowContext(): TradeFlowContext | null { const quoteState = useTradeQuote() const rateImpact = useRateImpact() const settingsState = useAtomValue(limitOrdersSettingsAtom) - const { partialFillsEnabled } = useFeatureFlags() if ( !chainId || @@ -56,8 +53,7 @@ export function useTradeFlowContext(): TradeFlowContext | null { const feeAmount = CurrencyAmount.fromRawAmount(state.inputCurrency, 0) const quoteId = quoteState.response?.id || undefined - // Depends on the feature flag to allow partial fills or not - const partiallyFillable = partialFillsEnabled && settingsState.partialFillsEnabled + const partiallyFillable = settingsState.partialFillsEnabled return { chainId, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx index 776d046c24..d9fcd3f2e7 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx @@ -1,8 +1,6 @@ import { SetStateAction } from 'jotai' -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { OrderKind } from '@cowprotocol/cow-sdk' -import { OrderClass } from '@cowprotocol/cow-sdk' +import { OrderClass, OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount } from '@uniswap/sdk-core' import { COW, GNO } from 'legacy/constants/tokens' @@ -63,7 +61,6 @@ const Fixtures = { executionPrice={null} limitRateState={initLimitRateState()} partiallyFillableOverride={[true, (_?: SetStateAction) => void 0]} - featurePartialFillsEnabled /> ), } diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx index f7aa0ceb4f..0a086921f6 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx @@ -47,19 +47,11 @@ export interface LimitOrdersDetailsProps { executionPrice: Price | null limitRateState: LimitRateState partiallyFillableOverride: PartiallyFillableOverrideDispatcherType - featurePartialFillsEnabled: boolean } export function LimitOrdersDetails(props: LimitOrdersDetailsProps) { - const { - executionPrice, - tradeContext, - settingsState, - rateInfoParams, - limitRateState, - partiallyFillableOverride, - featurePartialFillsEnabled, - } = props + const { executionPrice, tradeContext, settingsState, rateInfoParams, limitRateState, partiallyFillableOverride } = + props const { account, recipient, recipientAddressOrName, partiallyFillable } = tradeContext.postOrderParams const { feeAmount, activeRate, marketRate } = limitRateState @@ -136,11 +128,7 @@ export function LimitOrdersDetails(props: LimitOrdersDetailsProps) { Active */} - + {recipientAddressOrName && recipient !== account && (
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx index 153fd3e834..a59dd4bcf3 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx @@ -10,7 +10,6 @@ import * as styledEl from './styled' export type OrderTypeProps = { isPartiallyFillable: boolean - featurePartialFillsEnabled: boolean partiallyFillableOverride: PartiallyFillableOverrideDispatcherType className?: string } @@ -41,11 +40,7 @@ export function OrderType(props: OrderTypeProps) { const LABELS = ['Partially fillable', 'Fill or kill'] -function OrderTypePicker({ - isPartiallyFillable, - featurePartialFillsEnabled, - partiallyFillableOverride, -}: OrderTypeProps) { +function OrderTypePicker({ isPartiallyFillable, partiallyFillableOverride }: OrderTypeProps) { const [override, setOverride] = partiallyFillableOverride const showPartiallyFillable = override ?? isPartiallyFillable @@ -53,21 +48,18 @@ function OrderTypePicker({ const [labelText] = showPartiallyFillable ? LABELS : [...LABELS].reverse() const onSelect = (label: string) => setOverride(label === LABELS[0]) - const disabled = !featurePartialFillsEnabled return ( {({ isExpanded }: { isExpanded: boolean }) => ( - + {labelText} - {!disabled && ( - - )} + diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.cosmos.tsx index 99857c61ee..df49f8cc0c 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.cosmos.tsx @@ -8,7 +8,6 @@ const defaultProps: SettingsProps = { deadlineMilliseconds: 200_000, customDeadlineTimestamp: null, }, - featurePartialFillsEnabled: true, onStateChanged(state) { console.log('Settings state changed: ', state) }, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.tsx index 4fcbca9924..6f5dbe5f3c 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/index.tsx @@ -4,11 +4,10 @@ import { LimitOrdersSettingsState } from '../../state/limitOrdersSettingsAtom' export interface SettingsProps { state: LimitOrdersSettingsState - featurePartialFillsEnabled: boolean onStateChanged: (state: Partial) => void } -export function Settings({ state, featurePartialFillsEnabled, onStateChanged }: SettingsProps) { +export function Settings({ state, onStateChanged }: SettingsProps) { const { expertMode, showRecipient, partialFillsEnabled } = state return ( @@ -41,8 +40,7 @@ export function Settings({ state, featurePartialFillsEnabled, onStateChanged }: amount. } - disabled={!featurePartialFillsEnabled} - value={featurePartialFillsEnabled && partialFillsEnabled} + value={partialFillsEnabled} toggle={() => onStateChanged({ partialFillsEnabled: !partialFillsEnabled })} /> diff --git a/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx b/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx index abf730ceb5..290cb15b5d 100644 --- a/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx +++ b/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx @@ -60,6 +60,12 @@ export const MAIN_MENU: MenuTreeItem[] = [ title: 'Limit orders', url: Routes.LIMIT_ORDER, }, + { + id: MainMenuItemId.ADVANCED_ORDERS, + kind: MenuItemKind.PARAMETRIZED_LINK, + title: 'TWAP orders', + url: Routes.ADVANCED_ORDERS, + }, ], }, ], diff --git a/apps/cowswap-frontend/src/modules/mainMenu/hooks.ts b/apps/cowswap-frontend/src/modules/mainMenu/hooks.ts deleted file mode 100644 index 7612906103..0000000000 --- a/apps/cowswap-frontend/src/modules/mainMenu/hooks.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { useMemo } from 'react' - -import { useIsAdvancedOrdersEnabled } from 'common/hooks/useIsAdvancedOrdersEnabled' - -import { MenuTreeItem } from './types' -import { buildMainMenuTreeItems } from './utils' - -export function useMenuItems(): MenuTreeItem[] { - const isAdvancedOrdersEnabled = !!useIsAdvancedOrdersEnabled() - - return useMemo(() => buildMainMenuTreeItems({ isAdvancedOrdersEnabled }), [isAdvancedOrdersEnabled]) -} diff --git a/apps/cowswap-frontend/src/modules/mainMenu/index.ts b/apps/cowswap-frontend/src/modules/mainMenu/index.ts index 52c64f81db..28508e16a2 100644 --- a/apps/cowswap-frontend/src/modules/mainMenu/index.ts +++ b/apps/cowswap-frontend/src/modules/mainMenu/index.ts @@ -1,4 +1,2 @@ export * from './constants/mainMenu' export * from './types' -export * from './utils' -export * from './hooks' diff --git a/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx b/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx index 04bf386858..2215781845 100644 --- a/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx +++ b/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx @@ -8,20 +8,22 @@ import { MenuSection, MenuTitle } from 'legacy/components/MenuDropdown/styled' import { ExternalLink as ExternalLinkComponent } from 'legacy/theme/components' import { - DropDownItem, - ParametrizedLink, CustomItem, + DropDownItem, ExternalLink, InternalLink, MainMenuContext, MenuItemKind, MenuLink, MenuTreeItem, + ParametrizedLink, } from 'modules/mainMenu/types' import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute' import { RoutesValues } from 'common/constants/routes' +import { MAIN_MENU } from '../../constants/mainMenu' + // Assets // TODO: decompose the file @@ -164,12 +166,12 @@ function MenuItemWithDropDown(props: MenuItemWithDropDownProps) { } export interface MenuTreeProps { - items: MenuTreeItem[] + items?: MenuTreeItem[] context: MainMenuContext isMobileMenuOpen: boolean } -export function MenuTree({ items, isMobileMenuOpen, context }: MenuTreeProps) { +export function MenuTree({ items = MAIN_MENU, isMobileMenuOpen, context }: MenuTreeProps) { return ( {items.map((menuItem, index) => { diff --git a/apps/cowswap-frontend/src/modules/mainMenu/utils.ts b/apps/cowswap-frontend/src/modules/mainMenu/utils.ts deleted file mode 100644 index 4cb760db8b..0000000000 --- a/apps/cowswap-frontend/src/modules/mainMenu/utils.ts +++ /dev/null @@ -1,34 +0,0 @@ -import cloneDeep from 'clone-deep' - -import { Routes } from 'common/constants/routes' - -import { MAIN_MENU } from './constants/mainMenu' -import { DropDownItem, MainMenuItemId, MenuItemKind, MenuTreeItem } from './types' - -const ADVANCED_ORDERS_MENU_TITLE = 'TWAP orders' - -export type BuildMainMenuTreeItemsParams = { - isAdvancedOrdersEnabled: boolean -} - -export function buildMainMenuTreeItems({ isAdvancedOrdersEnabled }: BuildMainMenuTreeItemsParams): MenuTreeItem[] { - if (!isAdvancedOrdersEnabled) { - return MAIN_MENU - } - - // Make a deep copy to avoid mutating original - const mainMenuCopy = cloneDeep(MAIN_MENU) - - // Assume trade menu is at the first position - const [tradeMenu] = mainMenuCopy - - // Add to the bottom of the list - ;(tradeMenu as DropDownItem).items[0].links.push({ - id: MainMenuItemId.ADVANCED_ORDERS, - kind: MenuItemKind.PARAMETRIZED_LINK, - title: ADVANCED_ORDERS_MENU_TITLE, - url: Routes.ADVANCED_ORDERS, - }) - - return mainMenuCopy -} diff --git a/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts b/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts index 7f5b8eb78f..ac64574685 100644 --- a/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts +++ b/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts @@ -40,8 +40,7 @@ export interface SwapButtonStateParams { isReadonlyGnosisSafeUser: boolean isExpertMode: boolean isSwapUnsupported: boolean - isTxBundlingEnabled: boolean - isEthFlowBundlingEnabled: boolean + isBundlingSupported: boolean quoteError: QuoteError | undefined | null inputError?: string approvalState: ApprovalState @@ -104,12 +103,8 @@ export function getSwapButtonState(input: SwapButtonStateParams): SwapButtonStat } if (!input.isNativeIn && showApproveFlow) { - if (input.isTxBundlingEnabled) { - // TODO: decide if this should be done re-using the current approval flow state or whether do it custom with bundling - if (input.isExpertMode) { - return SwapButtonState.ExpertApproveAndSwap - } - return SwapButtonState.ApproveAndSwap + if (input.isBundlingSupported) { + return input.isExpertMode ? SwapButtonState.ExpertApproveAndSwap : SwapButtonState.ApproveAndSwap } return SwapButtonState.NeedApprove } @@ -125,7 +120,7 @@ export function getSwapButtonState(input: SwapButtonStateParams): SwapButtonStat if (input.isNativeIn) { if (getEthFlowEnabled(input.isSmartContractWallet)) { return input.isExpertMode ? SwapButtonState.ExpertModeEthFlowSwap : SwapButtonState.RegularEthFlowSwap - } else if (input.isEthFlowBundlingEnabled) { + } else if (input.isBundlingSupported) { return input.isExpertMode ? SwapButtonState.ExpertWrapAndSwap : SwapButtonState.WrapAndSwap } else { return SwapButtonState.SwapWithWrappedToken diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts index a108950381..7a9d6428ef 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts @@ -1,10 +1,10 @@ -import { useIsEthFlowBundlingEnabled } from 'common/hooks/featureFlags/useIsEthFlowBundlingEnabled' +import { useIsBundlingSupported } from 'modules/wallet' import { useIsSwapEth } from './useIsSwapEth' export function useIsSafeEthFlow(): boolean { const isSwapEth = useIsSwapEth() - const isEthFlowBundlingEnabled = useIsEthFlowBundlingEnabled() + const isBundlingSupported = useIsBundlingSupported() - return isEthFlowBundlingEnabled && isSwapEth + return isBundlingSupported && isSwapEth } diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts index 4ac0493a34..dd54c6b8f6 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts @@ -20,11 +20,9 @@ import { useWrapNativeFlow } from 'modules/trade' import { useIsNativeIn } from 'modules/trade/hooks/useIsNativeInOrOut' import { useIsWrappedOut } from 'modules/trade/hooks/useIsWrappedInOrOut' import { useWrappedToken } from 'modules/trade/hooks/useWrappedToken' -import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet' +import { useGnosisSafeInfo, useIsBundlingSupported, useWalletDetails, useWalletInfo } from 'modules/wallet' import { useTradeApproveState } from 'common/containers/TradeApprove/useTradeApproveState' -import { useIsEthFlowBundlingEnabled } from 'common/hooks/featureFlags/useIsEthFlowBundlingEnabled' -import { useIsTxBundlingEnabled } from 'common/hooks/featureFlags/useIsTxBundlingEnabled' import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet' import { useSafeBundleEthFlowContext } from './useSafeBundleEthFlowContext' @@ -87,16 +85,14 @@ export function useSwapButtonContext(input: SwapButtonInput): SwapButtonsContext const isReadonlyGnosisSafeUser = gnosisSafeInfo?.isReadOnly || false const isSwapUnsupported = useIsTradeUnsupported(currencyIn, currencyOut) const isSmartContractWallet = useIsSmartContractWallet() - const isTxBundlingEnabled = useIsTxBundlingEnabled() - const isEthFlowBundlingEnabled = useIsEthFlowBundlingEnabled() + const isBundlingSupported = useIsBundlingSupported() const swapButtonState = getSwapButtonState({ account, isSupportedWallet, isSmartContractWallet, isReadonlyGnosisSafeUser, - isTxBundlingEnabled, - isEthFlowBundlingEnabled, + isBundlingSupported, isExpertMode, isSwapUnsupported, isNativeIn: isNativeInSwap, diff --git a/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx b/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx index c7720cf4f5..87d879fb64 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx @@ -12,7 +12,6 @@ import { CompatibilityIssuesWarning } from 'modules/trade/pure/CompatibilityIssu import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning' import { TradeUrlParams } from 'modules/trade/types/TradeRawState' -import { FeatureGuard } from 'common/containers/FeatureGuard' import { BundleTxApprovalBanner, BundleTxSafeWcBanner, BundleTxWrapBanner } from 'common/pure/InlineBanner/banners' import { ZeroApprovalWarning } from 'common/pure/ZeroApprovalWarning' import { genericPropsChecker } from 'utils/genericPropsChecker' @@ -97,15 +96,13 @@ export const SwapWarningsTop = React.memo(function (props: SwapWarningsTopProps) )} - - - + ) }, genericPropsChecker) diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts index 0074bcfdf4..674a1d5e62 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts @@ -7,10 +7,9 @@ import { isUnsupportedTokenInQuote } from 'modules/limitOrders/utils/isUnsupport import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap' import { useTradeQuote } from 'modules/tradeQuote' -import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet' +import { useGnosisSafeInfo, useIsBundlingSupported, useWalletDetails, useWalletInfo } from 'modules/wallet' import { useTradeApproveState } from 'common/containers/TradeApprove' -import { useIsTxBundlingEnabled } from 'common/hooks/featureFlags/useIsTxBundlingEnabled' import { TradeFormValidationCommonContext } from '../types' @@ -25,7 +24,7 @@ export function useTradeFormValidationContext(): TradeFormValidationCommonContex const isSwapUnsupported = useIsTradeUnsupported(inputCurrency, outputCurrency) || isUnsupportedTokenInQuote(tradeQuote) - const isTxBundlingEnabled = useIsTxBundlingEnabled() + const isBundlingSupported = useIsBundlingSupported() const isWrapUnwrap = useIsWrapOrUnwrap() const { isSupportedWallet } = useWalletDetails() const gnosisSafeInfo = useGnosisSafeInfo() @@ -35,7 +34,7 @@ export function useTradeFormValidationContext(): TradeFormValidationCommonContex const commonContext = { account, isWrapUnwrap, - isTxBundlingEnabled, + isBundlingSupported, isSupportedWallet, isSwapUnsupported, isSafeReadonlyUser, diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts index ecd88eda97..c5eb269c37 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts @@ -9,7 +9,7 @@ export function validateTradeForm(context: TradeFormValidationContext): TradeFor const { derivedTradeState, approvalState, - isTxBundlingEnabled, + isBundlingSupported, isWrapUnwrap, isExpertMode, isSupportedWallet, @@ -77,11 +77,8 @@ export function validateTradeForm(context: TradeFormValidationContext): TradeFor } if (approvalRequired) { - if (isTxBundlingEnabled) { - if (isExpertMode) { - return TradeFormValidation.ExpertApproveAndSwap - } - return TradeFormValidation.ApproveAndSwap + if (isBundlingSupported) { + return isExpertMode ? TradeFormValidation.ExpertApproveAndSwap : TradeFormValidation.ApproveAndSwap } return TradeFormValidation.ApproveRequired } diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts index f90018345b..a889122039 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts @@ -45,7 +45,7 @@ export interface TradeFormValidationCommonContext { tradeQuote: TradeQuoteState recipientEnsAddress: string | null isWrapUnwrap: boolean - isTxBundlingEnabled: boolean + isBundlingSupported: boolean isSupportedWallet: boolean isSwapUnsupported: boolean isSafeReadonlyUser: boolean diff --git a/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx b/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx index 876cbf5187..f41b65eb5b 100644 --- a/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx +++ b/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx @@ -1,24 +1,15 @@ import { useAtomValue } from 'jotai' -import { Navigate } from 'react-router-dom' - import { advancedOrdersAtom, AdvancedOrdersWidget, FillAdvancedOrdersDerivedStateUpdater } from 'modules/advancedOrders' import { OrdersTableWidget } from 'modules/ordersTable' import { TabOrderTypes } from 'modules/ordersTable/pure/OrdersTableContainer' -import { useTradeRouteContext } from 'modules/trade/hooks/useTradeRouteContext' import * as styledEl from 'modules/trade/pure/TradePageLayout' -import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute' import { TradeFormValidation, useGetTradeFormValidation } from 'modules/tradeFormValidation' import { TwapFormWidget, TwapUpdaters, useAllEmulatedOrders } from 'modules/twap' import { useTwapFormState } from 'modules/twap/hooks/useTwapFormState' import { TwapFormState } from 'modules/twap/pure/PrimaryActionButton/getTwapFormState' -import { Routes as RoutesEnum } from 'common/constants/routes' -import { useIsAdvancedOrdersEnabled } from 'common/hooks/useIsAdvancedOrdersEnabled' - export default function AdvancedOrdersPage() { - const isAdvancedOrdersEnabled = useIsAdvancedOrdersEnabled() - const tradeContext = useTradeRouteContext() const { isUnlocked } = useAtomValue(advancedOrdersAtom) const allEmulatedOrders = useAllEmulatedOrders() @@ -26,15 +17,6 @@ export default function AdvancedOrdersPage() { const primaryFormValidation = useGetTradeFormValidation() const twapFormValidation = useTwapFormState() - if (isAdvancedOrdersEnabled === undefined) { - return null - } - - if (!isAdvancedOrdersEnabled) { - // To prevent direct access when the flag is off - return - } - const disablePriceImpact = primaryFormValidation === TradeFormValidation.QuoteErrors || primaryFormValidation === TradeFormValidation.CurrencyNotSupported || From d62b7f4340ebdc83e5f33fbf221568e355bd2271 Mon Sep 17 00:00:00 2001 From: Leandro Date: Thu, 21 Sep 2023 06:31:09 -0700 Subject: [PATCH 06/36] feat(permit): initial flow (#3067) * feat: permit hack * feat: permit hack * feat: permit hack * feat: permit hack * Fix code style issues with Prettier * try to make work with UNI token * Fix order signing * add hooks to quote for correct fee * Fix code style issues with Prettier * fix: put appData to quote request * refactor: add appData optional prop to LegacyFeeQuoteParams * refactor: simplify if condition * chore: made contract addresses not Partial as all chainIds are defined * chore: add @1inch/permit-signed-approvals-utils dependency * feat: first draft of the estimatePermit fn. Not yet tested! * chore: added a draft of useIsTokenPermittable still untested! * chore: update permitTokenChecker return types * feat: add hook usePermitHookParams * feat: update generatePermitHook to accept permitInfo and handle dai like permit * chore: add permitInfo to swapFlowContext * chore: update price quote data with permit info if permit params present * fix: use correct way to encode call data when using ethersjs * chore: debug statements REVERT ME! * fix: remove EIP712Domain before signing typed message * feat: use fake signer when checking whether token is permittable * chore: account is irrelevant for checking whether token is permittable * chore: add todos regarding app data merging * fix: properly await async methods * fix: gasLimit must be a string on appData hooks * chore: update .gitignore * feat: add permit module * chore: replace useIsTokenPermittable with hook from permit module * chore: update cow-sdk and app-data to latest RC versions * chore: move checkIsTokenPermittable into permit module * chore: move generatePermitHook to permit module * chore: move usePermitHookParams to permit module * chore: add appDataHash optional param to LegacyFeeQuoteParams * chore: do not pass permitHookParams around * chore: add util fn buildAppDataHooks * chore: add atom appDataHooksAtom * chore: do not mutate the appData on signAndPostOrder * chore: use appData in the quote params * chore: make buildAppData accept hooks metadata * chore: add addHooksToAppData fn * chore: add helper hooks to deal with appDataHooks * chore: update hooks inside appData updater * chore: export more stuff from appData module * chore: add usePermitHookData * chore: update appData when fee request is updated * chore: trigger permit signature when placing swap merging with existing appData * chore: remove unused method to generate permit * test: fix unittests * chore: refactor buildAppDataHooks * chore: refactor permit types * chore: remove debug statements * chore: replace magic hex with import form 1inch lib * refactor: hide magic string replacement behind helper function * chore: return e.message if available * chore: move constants to const file * chore: upper case local consts names * chore: use a constant PK rather than creating a random one every time * chore: move PermitProviderConnector to wallet module * refactor: rename generateQuotePermitHook to generatePermitHook * chore: export generatePermitHook from permit module * refactor: simplify permit's module hook interface Internalize the usage of usePermitHookParams * chore: chainId cannot be falsy * refactor: simplify useAddPermitInfo hook * refactor: useFakePermitHookData no longer takes in any parameter * chore: move appDataHooks updater inside appData module * fix: fix issue with appData not updating when it shouldn't * refactor: add in memory caching for checkIsTokenPermittable requests * refactor: cache on generatePermitHook * chore: return PermitHookData from generatePermitHook instead of a string * refactor: split permit hooks into individual hook files * chore: remove debug statements * chore: remove unnecessary cast to any * chore: rename DEFAULT_PERMIT_DURATION * chore: fix typo * chore: fix useTradeQuotePolling test * fix: let ethers be part of the main chunk Otherwise the whole page fails to load :( * chore: app is not starting now because of cowprotocol chunk removing it... * chore: get rid of metamask chunk too because doesn't work otherwise :/ * chore: add return type to generateAppDataFromDoc * chore: rename hooks updaters to component updaters * refactor: rename useFake->useAccountAgnostic * refactor: make PERMIT_GAS_LIMIT_MIN a single const rather than an obj with repeated values * chore: use stringifyDeterministic to generate appData * fix: update token logo cache after tokens list loading (#3100) * fix: fix crash tokens page due to tiny price (#3111) * chore: remove duplicated file * chore: work with strings for the price to avoid JS number finicky-ness * chore: do not try to calculate prices when it's < 1 USDC atom * chore: only number without integer part are too small * test: fix unit tests * feat: add new static fromNumber to FractionUtils * feat: create CurrencyAmounts from Fraction instances * chore: use Fraction rather than string or number to store prices * chore: it can be equal to 1 usdc atom * test: fix unit tests * fix(twap): load TWAP part details (#3113) * fix(price-impact): display unknown price impact warning only when there is no data (#3114) * fix(swap): reset state after network changes (#3116) * chore: allow enough balance check to return unknown state (#3106) * chore: allow enough balance check to return unknown state * chore: allow undefined in the getPriceQuality fn * chore: refactor repetitive code * chore: add nit to simplify expresssion Co-authored-by: Leandro * chore: move logic to private function * chore: don't allow to check quotes with same sellToken and buyToken * chore: add private function * fix: add mapping for error in the buttons map --------- Co-authored-by: Leandro * chore: reduce queries from unfillable updater (#3107) * chore: uipdate query time to 30s * chore: do not clear intervals because of a change in the update function * fix: make sure we invoke the latest update function * chore: reduce the times the update function is recreated * Remove ref from dependencies Co-authored-by: Leandro * chore: remove unecesary log --------- Co-authored-by: Leandro * fix: add html space chars before banner token symbols (#3117) * fix(usd-amount): fallback to native_price API if Coingecko doesn't know the currency (#3120) * fix(usd-amount): delete token from queue only if there are no subscribers left (#3121) * fix: surplus modal flickering (#3124) * fix: fix mapping network name from URL query to chainId (#3125) * chore(main): release 1.47.0-RC.0 (#3126) * Permit styles tag 1 (#3083) * feat: add permit tag token selector * feat: add permit tag token selector * feat: optimize * Permit styles [Modal/Stepper/IconSpinner] (#3097) * feat: updates * feat: updates * feat: updates * feat: updates * feat: updates * feat: fix box shadow var * feat: optimize * feat: optimize IconSpinner (#3099) * feat: optimize IconSpinner * feat: optimize * feat: add ENUM * feat: add ENUM (#3110) * feat: updates * feat: updates * feat: updates * feat: updates * feat: updates * feat: fix box shadow var * feat: optimize * feat: optimize IconSpinner (#3099) * feat: optimize IconSpinner * feat: optimize * feat: add ENUM * feat: add ENUM * feat: add ENUM * feat: add ENUM usage * feat: add ENUM usage * feat: add ENUM usage * fix: restore yarn.lock to version matching parent branch * fix: reverted package.json changes as well * chore: restore once again yarn.lock * feat: add ENUM usage * feat: add ENUM usage --------- Co-authored-by: Alfetopito * feat: updates --------- Co-authored-by: Alfetopito * chore: refactor and simplify pixel logic (#3118) * chore: remove pixels (#3119) * fix(eth-flow): additionally check eth-flow order id in smart-contract (#3103) * fix: trim eth-flow contract abi json file * fix(eth-flow): additionally check eth-flow order id in smart-contract * chore: remove unused ABI * chore: rename checkEthFlowOrderExists * fix(usd-price): handle individual token price query failure (#3127) * fix: handle individual token price query failure * chore: processQueue will no longer throw * chore: remove resetAtom as it's no longer used * chore(main): release 1.47.0 (#3129) * refactor: rename InnerAppDataUpdater to AppDataInfoUpdater * feat(permit): check allowance (#3102) * chore: update the quote if appData changes * chore: refactor useEnoughBalanceAndAllowance to return balance/alloance results separately * chore: propage hasEnoughAllowance to swapFlow * refactor: rename addHooksToAppData to updateHooksOnAppData and remove hooks when unset * chore: only add hooks to order when needed, and remove when not needed * chore: show approval status now includes permittable tokens * chore: hasEnoughAllowance can be undefined * Revert "refactor: make PERMIT_GAS_LIMIT_MIN a single const rather than an obj with repeated values" This reverts commit fbddd09e8da65a9a0ab3a8106a3a847efaff3ebc. * chore: reduce gas limit min for Goerli to 36k down from 55k * refactor: move default to constant * fix: rework request caching to prevent caching failed promises * chore: calculate gasLimit again using the account address * chore: hardcode gas limit to 80k * feat(permit): feature flag (#3135) * chore: add feature flags hook useIsPermitEnabled * feat: do not query/return any result when permit is not enabled * feat(permit): better gas limit estimation (#3138) * feat: use estimated gasLimit for quotes if higher than default * chore: add 10% to quote gas limit estimation for additional wiggle room * chore: estimate gas for real accounts also, but without extra 10% * chore: use a new empty private key for estimating the permits --------- Co-authored-by: Alexandr Kazachenko Co-authored-by: Lint Action Co-authored-by: Nicholas Rodrigues Lordello Co-authored-by: Anxo Rodriguez Co-authored-by: fairlight <31534717+fairlighteth@users.noreply.github.com> --- .../src/api/gnosisProtocol/api.ts | 26 ++- .../src/api/gnosisProtocol/legacy/types.ts | 5 +- .../hooks/featureFlags/useIsPermitEnabled.ts | 18 ++ .../src/legacy/constants/index.ts | 4 +- .../legacy/hooks/useRefetchPriceCallback.tsx | 6 - .../updaters/UnfillableOrdersUpdater.ts | 2 +- .../src/legacy/state/price/updater.ts | 13 +- .../src/legacy/utils/trade.ts | 9 +- .../src/modules/appData/hooks.ts | 10 +- .../src/modules/appData/index.ts | 4 +- .../src/modules/appData/state/atoms.ts | 6 + .../src/modules/appData/types.tsx | 12 +- .../appData/updater/AppDataHooksUpdater.ts | 25 ++ ...ppDataUpdater.ts => AppDataInfoUpdater.ts} | 9 +- ...DataInfoUpdater.tsx => AppDataUpdater.tsx} | 12 +- .../src/modules/appData/utils/buildAppData.ts | 53 ++++- .../appData/utils/buildAppDataHooks.ts | 15 ++ .../src/modules/permit/const.ts | 23 ++ .../hooks/useAccountAgnosticPermitHookData.ts | 56 +++++ .../permit/hooks/useIsTokenPermittable.ts | 90 +++++++ .../src/modules/permit/index.ts | 4 + .../src/modules/permit/state/atoms.ts | 33 +++ .../src/modules/permit/types.ts | 62 +++++ .../permit/utils/buildPermitCallData.ts | 26 +++ .../permit/utils/checkIsTokenPermittable.ts | 171 ++++++++++++++ .../permit/utils/generatePermitHook.ts | 141 +++++++++++ .../modules/permit/utils/getPermitDeadline.ts | 5 + .../swap/helpers/getSwapButtonState.ts | 7 +- .../src/modules/swap/hooks/useFlowContext.ts | 10 +- .../swap/hooks/useSwapButtonContext.ts | 3 + .../modules/swap/hooks/useSwapFlowContext.ts | 16 +- .../modules/swap/services/swapFlow/index.ts | 27 ++- .../src/modules/swap/services/types.ts | 7 +- .../modules/tokens/hooks/useEnoughBalance.ts | 23 +- .../src/modules/trade/index.ts | 1 + .../useTradeQuotePolling.test.tsx.snap | 28 +-- .../tradeQuote/hooks/useQuoteParams.ts | 20 +- .../hooks/useTradeQuotePolling.test.tsx | 29 +-- .../wallet/utils/PermitProviderConnector.ts | 48 ++++ apps/cowswap-frontend/vite.config.ts | 3 - libs/abis/src/abis-legacy/erc20.json | 219 +++++++++++++++--- libs/abis/src/generated/legacy/Erc20.ts | 84 +++++++ .../legacy/factories/Erc20__factory.ts | 62 +++++ package.json | 5 +- yarn.lock | 128 ++++++++-- 45 files changed, 1413 insertions(+), 147 deletions(-) create mode 100644 apps/cowswap-frontend/src/common/hooks/featureFlags/useIsPermitEnabled.ts create mode 100644 apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts rename apps/cowswap-frontend/src/modules/appData/updater/{useAppDataUpdater.ts => AppDataInfoUpdater.ts} (88%) rename apps/cowswap-frontend/src/modules/appData/updater/{AppDataInfoUpdater.tsx => AppDataUpdater.tsx} (62%) create mode 100644 apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/const.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/index.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/state/atoms.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/types.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/utils/getPermitDeadline.ts create mode 100644 apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts b/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts index b08515a235..2eece9971d 100644 --- a/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts +++ b/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts @@ -7,14 +7,14 @@ import { OrderKind, OrderQuoteRequest, OrderQuoteResponse, + OrderQuoteSideKindBuy, + OrderQuoteSideKindSell, PartialApiContext, + PriceQuality, SigningScheme, SupportedChainId as ChainId, - Trade, - PriceQuality, TotalSurplus, - OrderQuoteSideKindBuy, - OrderQuoteSideKindSell, + Trade, } from '@cowprotocol/cow-sdk' import { orderBookApi } from 'cowSdk' @@ -103,7 +103,20 @@ const ETH_FLOW_AUX_QUOTE_PARAMS = { } function _mapNewToLegacyParams(params: FeeQuoteParams): OrderQuoteRequest { - const { amount, kind, userAddress, receiver, validTo, sellToken, buyToken, chainId, priceQuality, isEthFlow } = params + const { + amount, + kind, + userAddress, + receiver, + validTo, + sellToken, + buyToken, + chainId, + priceQuality, + isEthFlow, + appData, + appDataHash, + } = params const fallbackAddress = userAddress || ZERO_ADDRESS const baseParams = { @@ -112,7 +125,8 @@ function _mapNewToLegacyParams(params: FeeQuoteParams): OrderQuoteRequest { buyToken: toNativeBuyAddress(buyToken, chainId), from: fallbackAddress, receiver: receiver || fallbackAddress, - appData: getAppData().appDataKeccak256, + appData: appData || getAppData().appDataKeccak256, + appDataHash, validTo, partiallyFillable: false, priceQuality, diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/legacy/types.ts b/apps/cowswap-frontend/src/api/gnosisProtocol/legacy/types.ts index 59f74cd80c..f380b208c4 100644 --- a/apps/cowswap-frontend/src/api/gnosisProtocol/legacy/types.ts +++ b/apps/cowswap-frontend/src/api/gnosisProtocol/legacy/types.ts @@ -1,5 +1,4 @@ -import { SupportedChainId as ChainId, PriceQuality } from '@cowprotocol/cow-sdk' -import { EnrichedOrder } from '@cowprotocol/cow-sdk' +import { AppData, AppDataHash, EnrichedOrder, PriceQuality, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { FeeInformation, PriceInformation } from 'types' @@ -38,6 +37,8 @@ export interface LegacyFeeQuoteParams extends FeeQuoteParams { priceQuality: PriceQuality isBestQuote?: boolean isEthFlow: boolean + appData?: AppData + appDataHash?: AppDataHash } export type LegacyPriceQuoteParams = Omit & { diff --git a/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsPermitEnabled.ts b/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsPermitEnabled.ts new file mode 100644 index 0000000000..56dff4497e --- /dev/null +++ b/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsPermitEnabled.ts @@ -0,0 +1,18 @@ +import { SupportedChainId } from '@cowprotocol/cow-sdk' + +import { useFeatureFlags } from './useFeatureFlags' + +export function useIsPermitEnabled(chainId: SupportedChainId | undefined): boolean { + const { permitEnabledMainnet, permitEnabledGoerli, permitEnabledGnosis } = useFeatureFlags() + + switch (chainId) { + case SupportedChainId.MAINNET: + return !!permitEnabledMainnet + case SupportedChainId.GNOSIS_CHAIN: + return !!permitEnabledGnosis + case SupportedChainId.GOERLI: + return !!permitEnabledGoerli + default: + return false + } +} diff --git a/apps/cowswap-frontend/src/legacy/constants/index.ts b/apps/cowswap-frontend/src/legacy/constants/index.ts index 160523ed91..4eb7a8a498 100644 --- a/apps/cowswap-frontend/src/legacy/constants/index.ts +++ b/apps/cowswap-frontend/src/legacy/constants/index.ts @@ -65,13 +65,13 @@ export const COWSWAP_ETHFLOW_CONTRACT_ADDRESS: Record> = { +export const GP_SETTLEMENT_CONTRACT_ADDRESS: Record = { [ChainId.MAINNET]: GPv2Settlement[ChainId.MAINNET].address, [ChainId.GNOSIS_CHAIN]: GPv2Settlement[ChainId.GNOSIS_CHAIN].address, [ChainId.GOERLI]: GPv2Settlement[ChainId.GOERLI].address, } -export const GP_VAULT_RELAYER: Partial> = { +export const GP_VAULT_RELAYER: Record = { [ChainId.MAINNET]: GPv2VaultRelayer[ChainId.MAINNET].address, [ChainId.GNOSIS_CHAIN]: GPv2VaultRelayer[ChainId.GNOSIS_CHAIN].address, [ChainId.GOERLI]: GPv2VaultRelayer[ChainId.GOERLI].address, diff --git a/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx b/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx index d858a2fe29..26ddeca6c9 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx +++ b/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx @@ -241,12 +241,6 @@ export function useRefetchQuoteCallback() { }, } - // Register get best and fast quote methods on window - registerOnWindow({ - getBestQuote: async () => getBestQuoteResolveOnlyLastCall(bestQuoteParams), - getFastQuote: async () => getFastQuoteResolveOnlyLastCall(fastQuoteParams), - }) - // Get the fast quote if (!isPriceRefresh) { getFastQuoteResolveOnlyLastCall(fastQuoteParams) diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/UnfillableOrdersUpdater.ts b/apps/cowswap-frontend/src/legacy/state/orders/updaters/UnfillableOrdersUpdater.ts index c8e3080f99..d89fd64b21 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/UnfillableOrdersUpdater.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/updaters/UnfillableOrdersUpdater.ts @@ -146,7 +146,7 @@ export function UnfillableOrdersUpdater(): null { console.debug(`[UnfillableOrdersUpdater] Check order`, order) const currencyAmount = CurrencyAmount.fromRawAmount(order.inputToken, order.sellAmount) - const enoughBalance = hasEnoughBalanceAndAllowance({ + const { enoughBalance } = hasEnoughBalanceAndAllowance({ account, amount: currencyAmount, balances: balancesRef.current, diff --git a/apps/cowswap-frontend/src/legacy/state/price/updater.ts b/apps/cowswap-frontend/src/legacy/state/price/updater.ts index dd7b2553f0..7080f8aab9 100644 --- a/apps/cowswap-frontend/src/legacy/state/price/updater.ts +++ b/apps/cowswap-frontend/src/legacy/state/price/updater.ts @@ -15,6 +15,7 @@ import { isWrappingTrade } from 'legacy/state/swap/utils' import { useOrderValidTo } from 'legacy/state/user/hooks' import { isAddress } from 'legacy/utils' +import { useAppData } from 'modules/appData' import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow' import { useEnoughBalanceAndAllowance } from 'modules/tokens' import { useWalletInfo } from 'modules/wallet' @@ -66,8 +67,9 @@ function quoteUsingSameParameters(currentParams: FeeQuoteParams, quoteInfo: Quot kind: currentKind, userAddress: currentUserAddress, receiver: currentReceiver, + appData: currentAppData, } = currentParams - const { amount, buyToken, sellToken, kind, userAddress, receiver } = quoteInfo + const { amount, buyToken, sellToken, kind, userAddress, receiver, appData } = quoteInfo const hasSameReceiver = currentReceiver && receiver ? currentReceiver === receiver : true // cache the base quote params without quoteInfo user address to check @@ -76,6 +78,7 @@ function quoteUsingSameParameters(currentParams: FeeQuoteParams, quoteInfo: Quot buyToken === currentBuyToken && amount === currentAmount && kind === currentKind && + appData === currentAppData && hasSameReceiver // 2 checks: if there's a quoteInfo user address (meaning quote was already calculated once) and one without // in case user is not connected @@ -130,7 +133,7 @@ export default function FeesUpdater(): null { parsedAmount, } = useDerivedSwapInfo() - const enoughBalance = useEnoughBalanceAndAllowance({ account, amount: parsedAmount }) + const { enoughBalance } = useEnoughBalanceAndAllowance({ account, amount: parsedAmount }) const { address: ensRecipientAddress } = useENSAddress(recipient) const receiver = ensRecipientAddress || recipient @@ -150,6 +153,8 @@ export default function FeesUpdater(): null { const isUnsupportedTokenGp = useIsUnsupportedTokenGp() + const appData = useAppData() + const refetchQuote = useRefetchQuoteCallback() const setQuoteError = useSetQuoteError() @@ -208,6 +213,8 @@ export default function FeesUpdater(): null { validTo, isEthFlow, priceQuality: getPriceQuality({ verifyQuote: verifiedQuotesEnabled && enoughBalance }), + appData: appData?.fullAppData, + appDataHash: appData?.appDataKeccak256, } // Don't refetch if offline. @@ -280,6 +287,8 @@ export default function FeesUpdater(): null { sellTokenAddressInvalid, enoughBalance, verifiedQuotesEnabled, + appData?.fullAppData, + appData?.appDataKeccak256, ]) return null diff --git a/apps/cowswap-frontend/src/legacy/utils/trade.ts b/apps/cowswap-frontend/src/legacy/utils/trade.ts index 2339f4a56a..7559a2dccb 100644 --- a/apps/cowswap-frontend/src/legacy/utils/trade.ts +++ b/apps/cowswap-frontend/src/legacy/utils/trade.ts @@ -2,17 +2,17 @@ import { EcdsaSigningScheme, OrderClass, OrderKind, - UnsignedOrder, - SigningScheme, OrderSigningUtils, + SigningScheme, + SupportedChainId as ChainId, + UnsignedOrder, } from '@cowprotocol/cow-sdk' -import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { Signer } from '@ethersproject/abstract-signer' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { orderBookApi } from 'cowSdk' -import { RADIX_DECIMAL, NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants' +import { NATIVE_CURRENCY_BUY_ADDRESS, RADIX_DECIMAL } from 'legacy/constants' import { ChangeOrderStatusParams, Order, OrderStatus } from 'legacy/state/orders/actions' import { AddUnserialisedPendingOrderParams } from 'legacy/state/orders/hooks' import { isAddress, shortenAddress } from 'legacy/utils/index' @@ -234,6 +234,7 @@ export async function signAndPostOrder(params: PostOrderParams): Promise get(appDataUploadQueueAtom).filter(buildInverseDocFilterFn(chainId, orderId))) } ) + +/** + * In memory atom for storing the current appData hooks info + */ +export const appDataHooksAtom = atom(undefined) diff --git a/apps/cowswap-frontend/src/modules/appData/types.tsx b/apps/cowswap-frontend/src/modules/appData/types.tsx index 52be631151..521c348b62 100644 --- a/apps/cowswap-frontend/src/modules/appData/types.tsx +++ b/apps/cowswap-frontend/src/modules/appData/types.tsx @@ -1,4 +1,4 @@ -import { LatestAppDataDocVersion, createOrderClassMetadata } from '@cowprotocol/app-data' +import { latest, LatestAppDataDocVersion } from '@cowprotocol/app-data' import { CowEnv, SupportedChainId } from '@cowprotocol/cow-sdk' export type AppDataInfo = { @@ -21,7 +21,7 @@ export type AppDataKeyParams = { export type AppDataRecord = AppDataInfo & AppDataUploadStatus & AppDataKeyParams -export type AppDataOrderClass = Parameters[0]['orderClass'] +export type AppDataOrderClass = latest.OrderClass['orderClass'] export type AppDataPendingToUpload = Array @@ -30,3 +30,11 @@ export type UploadAppDataParams = AppDataKeyParams & { } export type UpdateAppDataOnUploadQueueParams = AppDataKeyParams & Partial export type RemoveAppDataFromUploadQueueParams = AppDataKeyParams + +export type AppDataHooks = latest.OrderInteractionHooks + +export type PreHooks = latest.PreHooks + +export type PostHooks = latest.PostHooks + +export type AppDataRootSchema = latest.AppDataRootSchema diff --git a/apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts b/apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts new file mode 100644 index 0000000000..d0a7060837 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/appData/updater/AppDataHooksUpdater.ts @@ -0,0 +1,25 @@ +import { useEffect, useRef } from 'react' + +import { useAccountAgnosticPermitHookData } from 'modules/permit' + +import { useUpdateAppDataHooks } from '../hooks' +import { buildAppDataHooks } from '../utils/buildAppDataHooks' + +export function AppDataHooksUpdater(): null { + const updateAppDataHooks = useUpdateAppDataHooks() + const permitHookData = useAccountAgnosticPermitHookData() + + // To avoid dumb re-renders + const ref = useRef(permitHookData) + ref.current = permitHookData + const stableRef = JSON.stringify(permitHookData) + + useEffect(() => { + if (stableRef) { + const hooks = buildAppDataHooks(ref.current ? [ref.current] : undefined) + updateAppDataHooks(hooks) + } + }, [stableRef, updateAppDataHooks]) + + return null +} diff --git a/apps/cowswap-frontend/src/modules/appData/updater/useAppDataUpdater.ts b/apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.ts similarity index 88% rename from apps/cowswap-frontend/src/modules/appData/updater/useAppDataUpdater.ts rename to apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.ts index 255269f497..e9cb72f06f 100644 --- a/apps/cowswap-frontend/src/modules/appData/updater/useAppDataUpdater.ts +++ b/apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.ts @@ -7,7 +7,7 @@ import { UtmParams } from 'modules/utm' import { useAppCode } from '../hooks' import { appDataInfoAtom } from '../state/atoms' -import { AppDataOrderClass } from '../types' +import { AppDataHooks, AppDataOrderClass } from '../types' import { buildAppData, BuildAppDataParams } from '../utils/buildAppData' import { getAppData } from '../utils/fullAppData' @@ -16,13 +16,14 @@ export type UseAppDataParams = { slippageBips: string orderClass: AppDataOrderClass utm: UtmParams | undefined + hooks?: AppDataHooks } /** * Fetches and updates appDataInfo whenever a dependency changes * The hook can be called only from an updater */ -export function useAppDataUpdater({ chainId, slippageBips, orderClass, utm }: UseAppDataParams): void { +export function AppDataInfoUpdater({ chainId, slippageBips, orderClass, utm, hooks }: UseAppDataParams): void { // AppDataInfo, from Jotai const setAppDataInfo = useSetAtom(appDataInfoAtom) @@ -36,7 +37,7 @@ export function useAppDataUpdater({ chainId, slippageBips, orderClass, utm }: Us return } - const params: BuildAppDataParams = { chainId, slippageBips, appCode, orderClass, utm } + const params: BuildAppDataParams = { chainId, slippageBips, appCode, orderClass, utm, hooks } const updateAppData = async (): Promise => { try { @@ -51,7 +52,7 @@ export function useAppDataUpdater({ chainId, slippageBips, orderClass, utm }: Us } updateAppData() - }, [appCode, chainId, setAppDataInfo, slippageBips, orderClass, utm]) + }, [appCode, chainId, setAppDataInfo, slippageBips, orderClass, utm, hooks]) } function getEnvByClass(orderClass: string): CowEnv | undefined { if (orderClass === 'twap') { diff --git a/apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.tsx b/apps/cowswap-frontend/src/modules/appData/updater/AppDataUpdater.tsx similarity index 62% rename from apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.tsx rename to apps/cowswap-frontend/src/modules/appData/updater/AppDataUpdater.tsx index 26b2bdf2c7..79a38d70b4 100644 --- a/apps/cowswap-frontend/src/modules/appData/updater/AppDataInfoUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/appData/updater/AppDataUpdater.tsx @@ -7,8 +7,10 @@ import { percentToBips } from 'legacy/utils/misc' import { useUtm } from 'modules/utm' import { useWalletInfo } from 'modules/wallet' -import { UseAppDataParams, useAppDataUpdater } from './useAppDataUpdater' +import { AppDataHooksUpdater } from './AppDataHooksUpdater' +import { AppDataInfoUpdater, UseAppDataParams } from './AppDataInfoUpdater' +import { useAppDataHooks } from '../hooks' import { AppDataOrderClass } from '../types' interface AppDataUpdaterProps { @@ -21,14 +23,18 @@ export const AppDataUpdater = React.memo(({ slippage, orderClass }: AppDataUpdat const slippageBips = percentToBips(slippage) const utm = useUtm() + const hooks = useAppDataHooks() if (!chainId) return null - return + return ( + + ) }) const AppDataUpdaterMemo = React.memo((params: UseAppDataParams) => { - useAppDataUpdater(params) + AppDataHooksUpdater() + AppDataInfoUpdater(params) return null }) diff --git a/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts b/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts index 1bccca5c4c..ef6bf94536 100644 --- a/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts +++ b/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts @@ -1,3 +1,4 @@ +import { stringifyDeterministic } from '@cowprotocol/app-data' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { metadataApiSDK } from 'cowSdk' @@ -7,7 +8,7 @@ import { environmentName } from 'legacy/utils/environments' import { UtmParams } from 'modules/utm' -import { AppDataOrderClass } from '../types' +import { AppDataHooks, AppDataInfo, AppDataOrderClass, AppDataRootSchema } from '../types' export type BuildAppDataParams = { appCode: string @@ -16,6 +17,15 @@ export type BuildAppDataParams = { orderClass: AppDataOrderClass referrerAccount?: string utm: UtmParams | undefined + hooks?: AppDataHooks +} + +async function generateAppDataFromDoc( + doc: AppDataRootSchema +): Promise> { + const fullAppData = await stringifyDeterministic(doc) + const appDataKeccak256 = toKeccak256(fullAppData) + return { fullAppData, appDataKeccak256 } } export async function buildAppData({ @@ -23,22 +33,23 @@ export async function buildAppData({ slippageBips, referrerAccount, appCode, - orderClass, - utm: utmParams, -}: BuildAppDataParams) { + orderClass: orderClassName, + utm, + hooks, +}: BuildAppDataParams): Promise { const referrerParams = referrerAccount && chainId === SupportedChainId.MAINNET ? { address: referrerAccount } : undefined const quoteParams = { slippageBips } - const orderClassParams = { orderClass } + const orderClass = { orderClass: orderClassName } const doc = await metadataApiSDK.generateAppDataDoc({ - appDataParams: { appCode, environment: environmentName }, - metadataParams: { referrerParams, quoteParams, orderClassParams, utmParams }, + appCode, + environment: environmentName, + metadata: { referrer: referrerParams, quote: quoteParams, orderClass, utm, hooks }, }) - const fullAppData = JSON.stringify(doc) - const appDataKeccak256 = toKeccak256(fullAppData) + const { fullAppData, appDataKeccak256 } = await generateAppDataFromDoc(doc) return { doc, fullAppData, appDataKeccak256 } } @@ -46,3 +57,27 @@ export async function buildAppData({ export function toKeccak256(fullAppData: string) { return keccak256(toUtf8Bytes(fullAppData)) } + +export async function updateHooksOnAppData(appData: AppDataInfo, hooks: AppDataHooks | undefined): Promise { + const { doc } = appData + + const newDoc = { + ...doc, + metadata: { + ...doc.metadata, + hooks, + }, + } + + if (!hooks) { + delete newDoc.metadata.hooks + } + + const { fullAppData, appDataKeccak256 } = await generateAppDataFromDoc(newDoc) + + return { + doc: newDoc, + fullAppData, + appDataKeccak256, + } +} diff --git a/apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts b/apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts new file mode 100644 index 0000000000..cc671136b8 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts @@ -0,0 +1,15 @@ +import { AppDataHooks, PostHooks, PreHooks } from '../types' + +export function buildAppDataHooks( + preInteractionHooks?: PreHooks, + postInteractionHooks?: PostHooks +): AppDataHooks | undefined { + if (!preInteractionHooks && !postInteractionHooks) { + return undefined + } + + return { + ...{ pre: preInteractionHooks || undefined }, + ...{ post: postInteractionHooks || undefined }, + } +} diff --git a/apps/cowswap-frontend/src/modules/permit/const.ts b/apps/cowswap-frontend/src/modules/permit/const.ts new file mode 100644 index 0000000000..9f534b3bc4 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/const.ts @@ -0,0 +1,23 @@ +import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { MaxUint256 } from '@ethersproject/constants' +import { Wallet } from '@ethersproject/wallet' + +import ms from 'ms.macro' + +// PK used only for signing permit requests for quoting and identifying token 'permittability' +// Do not use or try to send funds to it. Or do. It'll be your funds 🤷 +const PERMIT_PK = '0xc58a2a421ca71ca57ae698f1c32feeb0b0ccb434da0b8089d88d80fb918f3f9d' // address: 0xFf65D1DfCF256cf4A8D5F2fb8e70F936606B7474 + +export const PERMIT_SIGNER = new Wallet(PERMIT_PK) + +export const PERMIT_GAS_LIMIT_MIN: Record = { + 1: 55_000, + 100: 55_000, + 5: 36_000, +} + +export const DEFAULT_PERMIT_GAS_LIMIT = '80000' + +export const DEFAULT_PERMIT_VALUE = MaxUint256.toString() + +export const DEFAULT_PERMIT_DURATION = ms`5 years` diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts new file mode 100644 index 0000000000..15b298c94a --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts @@ -0,0 +1,56 @@ +import { useEffect, useState } from 'react' + +import { Token } from '@uniswap/sdk-core' +import { useWeb3React } from '@web3-react/core' + +import { useDerivedTradeState } from 'modules/trade' +import { useWalletInfo } from 'modules/wallet' + +import { useSafeMemo } from 'common/hooks/useSafeMemo' + +import { useIsTokenPermittable } from './useIsTokenPermittable' + +import { PermitHookData, PermitHookParams } from '../types' +import { generatePermitHook } from '../utils/generatePermitHook' + +/** + * Returns PermitHookData using an account agnostic signer if inputCurrency is permittable + * + * Internally checks whether the token is permittable + * + * If not permittable or not able to tell, returns undefined + */ +export function useAccountAgnosticPermitHookData(): PermitHookData | undefined { + const params = usePermitHookParams() + + const [data, setData] = useState(undefined) + + useEffect(() => { + if (!params) return + + generatePermitHook(params).then(setData) + }, [params]) + + return data +} + +function usePermitHookParams(): PermitHookParams | undefined { + const { chainId } = useWalletInfo() + const { provider } = useWeb3React() + + const { state } = useDerivedTradeState() + const { inputCurrency } = state || {} + + const permitInfo = useIsTokenPermittable(inputCurrency) + + return useSafeMemo(() => { + if (!inputCurrency || !provider || !permitInfo) return undefined + + return { + chainId, + provider, + inputToken: inputCurrency as Token, + permitInfo, + } + }, [inputCurrency, provider, permitInfo, chainId]) +} diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts new file mode 100644 index 0000000000..b97e5e38b6 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts @@ -0,0 +1,90 @@ +import { useAtomValue, useSetAtom } from 'jotai' +import { useEffect, useMemo } from 'react' + +import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { Currency } from '@uniswap/sdk-core' +import { useWeb3React } from '@web3-react/core' + +import { Nullish } from 'types' + +import { useWalletInfo } from 'modules/wallet' + +import { useIsPermitEnabled } from 'common/hooks/featureFlags/useIsPermitEnabled' + +import { addPermitInfoForTokenAtom, permittableTokensAtom } from '../state/atoms' +import { IsTokenPermittableResult } from '../types' +import { checkIsTokenPermittable } from '../utils/checkIsTokenPermittable' + +/** + * Checks whether the token is permittable, and caches the result on localStorage + * + * When it is, returned type is `{type: 'dai'|'permit', gasLimit: number} + * When it is not, returned type is `false` + * When it is unknown, returned type is `undefined` + * + * @param token + */ +export function useIsTokenPermittable(token: Nullish): IsTokenPermittableResult { + const { chainId } = useWalletInfo() + const { provider } = useWeb3React() + + const lowerCaseAddress = token?.wrapped?.address?.toLowerCase() + const isNative = token?.isNative + const tokenName = token?.name || lowerCaseAddress || '' + + const isPermitEnabled = useIsPermitEnabled(chainId) + + const addPermitInfo = useAddPermitInfo() + const permitInfo = usePermitInfo(chainId, isPermitEnabled ? lowerCaseAddress : undefined) + + useEffect(() => { + if (!chainId || !isPermitEnabled || !lowerCaseAddress || !provider || permitInfo !== undefined || isNative) { + return + } + + checkIsTokenPermittable({ tokenAddress: lowerCaseAddress, tokenName, chainId, provider }).then((result) => { + if (!result) { + // When falsy, we know it doesn't support permit. Cache it. + addPermitInfo({ chainId, tokenAddress: lowerCaseAddress, permitInfo: false }) + } else if ('error' in result) { + // When error, we don't know. Log and don't cache. + console.debug( + `useIsTokenPermittable: failed to check whether token ${lowerCaseAddress} is permittable: ${result.error}` + ) + } else { + // Otherwise, we know it is permittable. Cache it. + addPermitInfo({ chainId, tokenAddress: lowerCaseAddress, permitInfo: result }) + } + }) + }, [addPermitInfo, chainId, isNative, lowerCaseAddress, permitInfo, provider, tokenName]) + + if (isNative) { + return false + } + // TODO: add an updater for this + return permitInfo +} + +/** + * Returns a callback for adding PermitInfo for a given token + */ +function useAddPermitInfo() { + return useSetAtom(addPermitInfoForTokenAtom) +} + +/** + * Returns whether a token is permittable. + * + * When it is, returned type is `{type: 'dai'|'permit', gasLimit: number}` + * When it is not, returned type is `false` + * When it is unknown, returned type is `undefined` + */ +function usePermitInfo(chainId: SupportedChainId, tokenAddress: string | undefined): IsTokenPermittableResult { + const permittableTokens = useAtomValue(permittableTokensAtom) + + return useMemo(() => { + if (!tokenAddress) return undefined + + return permittableTokens[chainId][tokenAddress.toLowerCase()] + }, [chainId, permittableTokens, tokenAddress]) +} diff --git a/apps/cowswap-frontend/src/modules/permit/index.ts b/apps/cowswap-frontend/src/modules/permit/index.ts new file mode 100644 index 0000000000..f060dce5cd --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/index.ts @@ -0,0 +1,4 @@ +export { useAccountAgnosticPermitHookData } from './hooks/useAccountAgnosticPermitHookData' +export { generatePermitHook } from './utils/generatePermitHook' +export { useIsTokenPermittable } from './hooks/useIsTokenPermittable' +export * from './types' diff --git a/apps/cowswap-frontend/src/modules/permit/state/atoms.ts b/apps/cowswap-frontend/src/modules/permit/state/atoms.ts new file mode 100644 index 0000000000..daf8a9de07 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/state/atoms.ts @@ -0,0 +1,33 @@ +import { atom } from 'jotai' +import { atomWithStorage } from 'jotai/utils' + +import { SupportedChainId } from '@cowprotocol/cow-sdk' + +import { AddPermitTokenParams, PermittableTokens } from '../types' + +/** + * Atom that stores the permittable tokens info for each chain on localStorage. + * It's meant to be shared across different tabs, thus no special storage handling. + * + * Contains either the permit info with `type` and `gasLimit` when supported or + * `false` when not supported + */ +export const permittableTokensAtom = atomWithStorage('permittableTokens:v0', { + [SupportedChainId.MAINNET]: {}, + [SupportedChainId.GOERLI]: {}, + [SupportedChainId.GNOSIS_CHAIN]: {}, +}) + +/** + * Helper derived atom to add a permit info for a token for a given chain + */ +export const addPermitInfoForTokenAtom = atom( + null, + (get, set, { chainId, tokenAddress, permitInfo }: AddPermitTokenParams) => { + const permittableTokens = { ...get(permittableTokensAtom) } + + permittableTokens[chainId][tokenAddress.toLowerCase()] = permitInfo + + set(permittableTokensAtom, permittableTokens) + } +) diff --git a/apps/cowswap-frontend/src/modules/permit/types.ts b/apps/cowswap-frontend/src/modules/permit/types.ts new file mode 100644 index 0000000000..baa427015f --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/types.ts @@ -0,0 +1,62 @@ +import { latest } from '@cowprotocol/app-data' +import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { Web3Provider } from '@ethersproject/providers' +import { Token } from '@uniswap/sdk-core' + +import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' + +export type PermitType = 'dai-like' | 'eip-2612' + +export type SupportedPermitInfo = { + type: PermitType + gasLimit: number +} +type UnsupportedPermitInfo = false +export type PermitInfo = SupportedPermitInfo | UnsupportedPermitInfo + +export type PermittableTokens = Record> + +export type IsTokenPermittableResult = PermitInfo | undefined + +export type AddPermitTokenParams = { + chainId: SupportedChainId + tokenAddress: string + permitInfo: PermitInfo +} + +export type PermitHookParams = { + inputToken: Token + chainId: SupportedChainId + permitInfo: SupportedPermitInfo + provider: Web3Provider + account?: string +} + +export type PermitHookData = latest.CoWHook + +type FailedToIdentify = { error: string } + +export type EstimatePermitResult = + // When it's a permittable token: + | SupportedPermitInfo + // When something failed: + | FailedToIdentify + // When it's not permittable: + | UnsupportedPermitInfo + +type BasePermitCallDataParams = { + eip2162Utils: Eip2612PermitUtils +} +export type BuildEip2162PermitCallDataParams = BasePermitCallDataParams & { + callDataParams: Parameters +} +export type BuildDaiLikePermitCallDataParams = BasePermitCallDataParams & { + callDataParams: Parameters +} + +export type CheckIsTokenPermittableParams = { + tokenAddress: string + tokenName: string + chainId: SupportedChainId + provider: Web3Provider +} diff --git a/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts b/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts new file mode 100644 index 0000000000..67d5ddcca0 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/utils/buildPermitCallData.ts @@ -0,0 +1,26 @@ +import { DAI_PERMIT_SELECTOR, EIP_2612_PERMIT_SELECTOR } from '@1inch/permit-signed-approvals-utils' + +import { BuildDaiLikePermitCallDataParams, BuildEip2162PermitCallDataParams } from '../types' + +export async function buildEip2162PermitCallData({ + eip2162Utils, + callDataParams, +}: BuildEip2162PermitCallDataParams): Promise { + const callData = await eip2162Utils.buildPermitCallData(...callDataParams) + + // For some reason, the method above removes the permit selector prefix + // https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.utils.ts#L92 + // Adding it back + return callData.replace('0x', EIP_2612_PERMIT_SELECTOR) +} + +export async function buildDaiLikePermitCallData({ + eip2162Utils, + callDataParams, +}: BuildDaiLikePermitCallDataParams): Promise { + const callData = await eip2162Utils.buildDaiLikePermitCallData(...callDataParams) + + // Same as above, but for dai like + // https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.utils.ts#L140 + return callData.replace('0x', DAI_PERMIT_SELECTOR) +} diff --git a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts new file mode 100644 index 0000000000..d5ab345122 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts @@ -0,0 +1,171 @@ +import { SupportedChainId } from '@cowprotocol/cow-sdk' +import type { Web3Provider } from '@ethersproject/providers' + +import { DAI_LIKE_PERMIT_TYPEHASH, Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' + +import { GP_VAULT_RELAYER, NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants' + +import { PermitProviderConnector } from 'modules/wallet/utils/PermitProviderConnector' + +import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData' +import { getPermitDeadline } from './getPermitDeadline' + +import { DEFAULT_PERMIT_VALUE, PERMIT_GAS_LIMIT_MIN, PERMIT_SIGNER } from '../const' +import { CheckIsTokenPermittableParams, EstimatePermitResult } from '../types' + +const EIP_2162_PERMIT_PARAMS = { + value: DEFAULT_PERMIT_VALUE, + nonce: 0, + deadline: getPermitDeadline(), +} + +const DAI_LIKE_PERMIT_PARAMS = { + allowed: true, + nonce: 0, + expiry: getPermitDeadline(), +} + +const REQUESTS_CACHE: Record> = {} + +export async function checkIsTokenPermittable(params: CheckIsTokenPermittableParams): Promise { + const { tokenAddress, chainId } = params + if (NATIVE_CURRENCY_BUY_ADDRESS.toLowerCase() === tokenAddress.toLowerCase()) { + // We shouldn't call this for the native token, but just in case + return false + } + + const key = `${chainId}-${tokenAddress.toLowerCase()}` + + const cached = REQUESTS_CACHE[key] + + if (cached) { + return cached + } + + const request = actuallyCheckTokenIsPermittable(params) + + REQUESTS_CACHE[key] = request + + return request +} + +async function actuallyCheckTokenIsPermittable(params: CheckIsTokenPermittableParams): Promise { + const { tokenAddress, tokenName, chainId, provider } = params + + const spender = GP_VAULT_RELAYER[chainId] + + const eip2612PermitUtils = getPermitUtilsInstance(chainId, provider) + + const owner = PERMIT_SIGNER.address + + try { + const nonce = await eip2612PermitUtils.getTokenNonce(tokenAddress, owner) + + const data = await buildEip2162PermitCallData({ + eip2162Utils: eip2612PermitUtils, + callDataParams: [ + { + ...EIP_2162_PERMIT_PARAMS, + owner, + spender, + nonce, + }, + +chainId, + tokenName, + tokenAddress, + ], + }) + + const estimatedGas = await provider.estimateGas({ + data, + from: owner, + to: tokenAddress, + }) + + const gasLimit = estimatedGas.toNumber() + + // Sometimes tokens implement the permit interface but don't actually implement it + // This check filters out possible cases where that happened by excluding + // gas limit which are bellow a minimum threshold + return gasLimit > PERMIT_GAS_LIMIT_MIN[chainId] + ? { + type: 'eip-2612', + gasLimit, + } + : false + } catch (e) { + try { + return await estimateDaiLikeToken(tokenAddress, tokenName, chainId, owner, spender, provider, eip2612PermitUtils) + } catch (e) { + return { error: e.message || e.toString() } + } + } +} + +const PERMIT_UTILS_CACHE: Record = {} + +function getPermitUtilsInstance(chainId: SupportedChainId, provider: Web3Provider): Eip2612PermitUtils { + const cached = PERMIT_UTILS_CACHE[chainId] + + if (cached) { + return cached + } + + const web3ProviderConnector = new PermitProviderConnector(provider, PERMIT_SIGNER) + const eip2612PermitUtils = new Eip2612PermitUtils(web3ProviderConnector) + + PERMIT_UTILS_CACHE[chainId] = eip2612PermitUtils + + return eip2612PermitUtils +} + +// TODO: refactor and make DAI like tokens work +function estimateDaiLikeToken( + tokenAddress: string, + tokenName: string, + chainId: SupportedChainId, + walletAddress: string, + spender: string, + provider: Web3Provider, + eip2612PermitUtils: Eip2612PermitUtils +): Promise { + return eip2612PermitUtils.getPermitTypeHash(tokenAddress).then((permitTypeHash) => { + return permitTypeHash === DAI_LIKE_PERMIT_TYPEHASH + ? eip2612PermitUtils + .getTokenNonce(tokenAddress, walletAddress) + .then((nonce) => + buildDaiLikePermitCallData({ + eip2162Utils: eip2612PermitUtils, + callDataParams: [ + { + ...DAI_LIKE_PERMIT_PARAMS, + holder: walletAddress, + spender, + nonce, + }, + chainId as number, + tokenName, + tokenAddress, + ], + }) + ) + .then((data) => + provider.estimateGas({ + data, + from: walletAddress, + to: tokenAddress, + }) + ) + .then((res) => { + const gasLimit = res.toNumber() + + return gasLimit > PERMIT_GAS_LIMIT_MIN[chainId] + ? { + gasLimit, + type: 'dai-like', + } + : false + }) + : false + }) +} diff --git a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts new file mode 100644 index 0000000000..0032cb19bc --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts @@ -0,0 +1,141 @@ +import { Web3Provider } from '@ethersproject/providers' + +import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' + +import { GP_VAULT_RELAYER } from 'legacy/constants' + +import { PermitProviderConnector } from 'modules/wallet/utils/PermitProviderConnector' + +import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData' +import { getPermitDeadline } from './getPermitDeadline' + +import { DEFAULT_PERMIT_GAS_LIMIT, DEFAULT_PERMIT_VALUE, PERMIT_SIGNER } from '../const' +import { PermitHookData, PermitHookParams } from '../types' + +const CACHE_PREFIX = 'permitCache:v0-' +const REQUESTS_CACHE: { [permitKey: string]: Promise } = {} + +function getCacheKey(params: PermitHookParams): string { + const { inputToken, chainId, account } = params + + return `${CACHE_PREFIX}${inputToken.address.toLowerCase()}-${chainId}${account ? `-${account}` : ''}` +} + +export async function generatePermitHook(params: PermitHookParams): Promise { + const permitKey = getCacheKey(params) + + const cachedResult = localStorage.getItem(permitKey) + if (cachedResult) return JSON.parse(cachedResult) + + const cachedRequest = REQUESTS_CACHE[permitKey] + + if (cachedRequest) { + try { + return await cachedRequest + } catch (e) { + console.debug(`[generatePermitHookWith] cached request failed`, e) + delete REQUESTS_CACHE[permitKey] + } + } + + const request = generatePermitHookRaw(params).then((permitHookData) => { + const permitHook = JSON.stringify(permitHookData) + + localStorage.setItem(permitKey, permitHook) + + return permitHookData + }) + + REQUESTS_CACHE[permitKey] = request + + return request +} + +async function generatePermitHookRaw(params: PermitHookParams): Promise { + const { inputToken, chainId, permitInfo, provider, account } = params + const tokenAddress = inputToken.address + const tokenName = inputToken.name || tokenAddress + + // TODO: verify whether cached result is still valid and renew it if needed + + const web3ProviderConnector = new PermitProviderConnector(provider, account ? undefined : PERMIT_SIGNER) + const eip2612PermitUtils = new Eip2612PermitUtils(web3ProviderConnector) + + const owner = account || PERMIT_SIGNER.address + + // TODO: check whether cached permit nonce matches current nonce and update it in case it doesnt + + const nonce = await eip2612PermitUtils.getTokenNonce(tokenAddress, owner) + + const spender = GP_VAULT_RELAYER[chainId] + const deadline = getPermitDeadline() + const value = DEFAULT_PERMIT_VALUE + + const callDataPromise = + permitInfo.type === 'eip-2612' + ? buildEip2162PermitCallData({ + eip2162Utils: eip2612PermitUtils, + callDataParams: [ + { + owner, + spender, + value, + nonce, + deadline, + }, + chainId as number, + tokenName, + tokenAddress, + ], + }) + : buildDaiLikePermitCallData({ + eip2162Utils: eip2612PermitUtils, + callDataParams: [ + { + holder: owner, + spender, + allowed: true, + value, + nonce, + expiry: deadline, + }, + chainId as number, + tokenName, + tokenAddress, + ], + }) + + const callData = await callDataPromise + + const gasLimit = await calculateGasLimit(callData, owner, tokenAddress, provider, !!account) + + return { + target: tokenAddress, + callData, + gasLimit, + } +} + +async function calculateGasLimit( + data: string, + from: string, + to: string, + provider: Web3Provider, + isUserAccount: boolean +): Promise { + try { + // Query the actual gas estimate + const actual = await provider.estimateGas({ data, from, to }) + + // Add 10% to actual value to account for minor differences with real account + // Do not add it if this is the real user's account + const gasLimit = !isUserAccount ? actual.add(actual.div(10)) : actual + + // Pick the biggest between estimated and default + return gasLimit.gt(DEFAULT_PERMIT_GAS_LIMIT) ? gasLimit.toString() : DEFAULT_PERMIT_GAS_LIMIT + } catch (e) { + console.debug(`[calculatePermitGasLimit] Failed to estimateGas, using default`, e) + + return DEFAULT_PERMIT_GAS_LIMIT + } +} diff --git a/apps/cowswap-frontend/src/modules/permit/utils/getPermitDeadline.ts b/apps/cowswap-frontend/src/modules/permit/utils/getPermitDeadline.ts new file mode 100644 index 0000000000..4c4090aca1 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/utils/getPermitDeadline.ts @@ -0,0 +1,5 @@ +import { DEFAULT_PERMIT_DURATION } from '../const' + +export function getPermitDeadline() { + return Math.ceil(Date.now() / 1000) + DEFAULT_PERMIT_DURATION +} diff --git a/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts b/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts index ac64574685..fe2112b2f2 100644 --- a/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts +++ b/apps/cowswap-frontend/src/modules/swap/helpers/getSwapButtonState.ts @@ -53,6 +53,7 @@ export interface SwapButtonStateParams { isSmartContractWallet: boolean isBestQuoteLoading: boolean wrappedToken: Token + isPermitSupported: boolean } const quoteErrorToSwapButtonState: { [key in QuoteError]: SwapButtonState | null } = { @@ -66,12 +67,14 @@ const quoteErrorToSwapButtonState: { [key in QuoteError]: SwapButtonState | null } export function getSwapButtonState(input: SwapButtonStateParams): SwapButtonState { - const { quoteError, approvalState } = input + const { quoteError, approvalState, isPermitSupported } = input // show approve flow when: no error on inputs, not approved or pending, or approved in current session // never show if price impact is above threshold in non expert mode const showApproveFlow = - !input.inputError && (approvalState === ApprovalState.NOT_APPROVED || approvalState === ApprovalState.PENDING) + !isPermitSupported && + !input.inputError && + (approvalState === ApprovalState.NOT_APPROVED || approvalState === ApprovalState.PENDING) const isValid = !input.inputError && input.feeWarningAccepted && input.impactWarningAccepted const swapBlankState = !input.inputError && !input.trade diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts index 8e6b4f1af9..ac199e0902 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts @@ -1,5 +1,5 @@ import { OrderClass, OrderKind } from '@cowprotocol/cow-sdk' -import { Weth } from '@cowswap/abis' +import { Erc20, Weth } from '@cowswap/abis' import { Web3Provider } from '@ethersproject/providers' import { SafeInfoResponse } from '@safe-global/api-kit' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' @@ -9,7 +9,7 @@ import { useDispatch } from 'react-redux' import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' import { GpEther as ETHER } from 'legacy/constants/tokens' -import { useWETHContract } from 'legacy/hooks/useContract' +import { useTokenContract, useWETHContract } from 'legacy/hooks/useContract' import useENSAddress from 'legacy/hooks/useENSAddress' import { AppDispatch } from 'legacy/state' import { useCloseModals } from 'legacy/state/application/hooks' @@ -29,6 +29,7 @@ import { BaseFlowContext } from 'modules/swap/services/types' import { SwapFlowAnalyticsContext } from 'modules/trade/utils/analytics' import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet' +import { getAddress } from 'utils/getAddress' import { calculateValidTo } from 'utils/time' import { useIsSafeEthFlow } from './useIsSafeEthFlow' @@ -63,6 +64,7 @@ export enum FlowType { interface BaseFlowContextSetup { chainId: number | undefined account: string | undefined + sellTokenContract: Erc20 | null provider: Web3Provider | undefined trade: TradeGp | undefined appData: AppDataInfo | null @@ -109,6 +111,7 @@ export function useBaseFlowContextSetup(): BaseFlowContextSetup { trade, allowedSlippage ) + const sellTokenContract = useTokenContract(getAddress(inputAmountWithSlippage?.currency) || undefined, true) const isSafeBundle = useIsSafeApprovalBundle(inputAmountWithSlippage) const flowType = _getFlowType(isSafeBundle, isEoaEthFlow, isSafeEthFlow) @@ -116,6 +119,7 @@ export function useBaseFlowContextSetup(): BaseFlowContextSetup { return { chainId, account, + sellTokenContract, provider, trade, appData, @@ -179,6 +183,7 @@ export function getFlowContext({ baseProps, sellToken, kind }: BaseGetFlowContex uploadAppData, dispatch, flowType, + sellTokenContract, } = baseProps if ( @@ -263,5 +268,6 @@ export function getFlowContext({ baseProps, sellToken, kind }: BaseGetFlowContex swapConfirmManager, orderParams, appDataInfo: appData, + sellTokenContract, } } diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts index dd54c6b8f6..68688e3968 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts @@ -8,6 +8,7 @@ import { Field } from 'legacy/state/swap/actions' import { useDerivedSwapInfo, useSwapActionHandlers } from 'legacy/state/swap/hooks' import { useExpertModeManager } from 'legacy/state/user/hooks' +import { useIsTokenPermittable } from 'modules/permit' import { getSwapButtonState } from 'modules/swap/helpers/getSwapButtonState' import { useEthFlowContext } from 'modules/swap/hooks/useEthFlowContext' import { useHandleSwap } from 'modules/swap/hooks/useHandleSwap' @@ -86,6 +87,7 @@ export function useSwapButtonContext(input: SwapButtonInput): SwapButtonsContext const isSwapUnsupported = useIsTradeUnsupported(currencyIn, currencyOut) const isSmartContractWallet = useIsSmartContractWallet() const isBundlingSupported = useIsBundlingSupported() + const isPermitSupported = !!useIsTokenPermittable(currencyIn) const swapButtonState = getSwapButtonState({ account, @@ -106,6 +108,7 @@ export function useSwapButtonContext(input: SwapButtonInput): SwapButtonsContext swapCallbackError, trade, isBestQuoteLoading, + isPermitSupported, }) return { diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts index f8adc0ea86..44bf0aad89 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts @@ -1,14 +1,26 @@ -import { OrderKind } from '@cowprotocol/cow-sdk' +import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { TradeType } from '@uniswap/sdk-core' +import { GP_VAULT_RELAYER } from 'legacy/constants' import { useGP2SettlementContract } from 'legacy/hooks/useContract' +import { useIsTokenPermittable } from 'modules/permit' import { FlowType, getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext' import { SwapFlowContext } from 'modules/swap/services/types' +import { useEnoughBalanceAndAllowance } from 'modules/tokens' export function useSwapFlowContext(): SwapFlowContext | null { const contract = useGP2SettlementContract() const baseProps = useBaseFlowContextSetup() + const sellCurrency = baseProps.trade?.inputAmount?.currency + const permitInfo = useIsTokenPermittable(sellCurrency) + + const checkAllowanceAddress = GP_VAULT_RELAYER[baseProps.chainId || SupportedChainId.MAINNET] + const { enoughAllowance: hasEnoughAllowance } = useEnoughBalanceAndAllowance({ + account: baseProps.account, + amount: baseProps.inputAmountWithSlippage, + checkAllowanceAddress, + }) if (!baseProps.trade) return null @@ -23,5 +35,7 @@ export function useSwapFlowContext(): SwapFlowContext | null { return { ...baseContext, contract, + permitInfo, + hasEnoughAllowance, } } diff --git a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts index a23c0e492f..67ba87bba4 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts @@ -1,16 +1,19 @@ -import { Percent } from '@uniswap/sdk-core' +import { Web3Provider } from '@ethersproject/providers' +import { Percent, Token } from '@uniswap/sdk-core' import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { partialOrderUpdate } from 'legacy/state/orders/utils' import { signAndPostOrder } from 'legacy/utils/trade' +import { buildAppDataHooks, updateHooksOnAppData } from 'modules/appData' +import { generatePermitHook } from 'modules/permit' import { addPendingOrderStep } from 'modules/trade/utils/addPendingOrderStep' +import { tradeFlowAnalytics } from 'modules/trade/utils/analytics' import { logTradeFlow } from 'modules/trade/utils/logger' import { getSwapErrorMessage } from 'modules/trade/utils/swapErrorHelper' import { presignOrderStep } from './steps/presignOrderStep' -import { tradeFlowAnalytics } from '../../../trade/utils/analytics' import { SwapFlowContext } from '../types' export async function swapFlow( @@ -23,6 +26,26 @@ export async function swapFlow( return } + if (input.permitInfo && !input.hasEnoughAllowance) { + // If token is permittable and there's not enough allowance, get th permit hook + + // TODO: maybe we need a modal to inform the user what they need to sign? + const permitData = await generatePermitHook({ + inputToken: input.context.trade.inputAmount.currency as Token, + provider: input.orderParams.signer.provider as Web3Provider, + account: input.orderParams.account, + chainId: input.orderParams.chainId, + permitInfo: input.permitInfo, + }) + + const hooks = buildAppDataHooks([permitData]) + + input.orderParams.appData = await updateHooksOnAppData(input.orderParams.appData, hooks) + } else { + // Otherwise, remove hooks (if any) from appData to avoid stale data + input.orderParams.appData = await updateHooksOnAppData(input.orderParams.appData, undefined) + } + logTradeFlow('SWAP FLOW', 'STEP 2: send transaction') tradeFlowAnalytics.trade(input.swapFlowAnalyticsContext) input.swapConfirmManager.sendTransaction(input.context.trade) diff --git a/apps/cowswap-frontend/src/modules/swap/services/types.ts b/apps/cowswap-frontend/src/modules/swap/services/types.ts index 5dd98add18..4beacef971 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/types.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/types.ts @@ -1,5 +1,4 @@ -import { GPv2Settlement, CoWSwapEthFlow } from '@cowswap/abis' -import { Erc20, Weth } from '@cowswap/abis' +import { CoWSwapEthFlow, Erc20, GPv2Settlement, Weth } from '@cowswap/abis' import { Web3Provider } from '@ethersproject/providers' import SafeAppsSDK from '@safe-global/safe-apps-sdk' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' @@ -11,6 +10,7 @@ import TradeGp from 'legacy/state/swap/TradeGp' import { PostOrderParams } from 'legacy/utils/trade' import { AppDataInfo, UploadAppDataParams } from 'modules/appData' +import { IsTokenPermittableResult } from 'modules/permit' import { SwapConfirmManager } from 'modules/swap/hooks/useSwapConfirmManager' import { SwapFlowAnalyticsContext } from 'modules/trade/utils/analytics' @@ -34,6 +34,7 @@ export interface BaseFlowContext { addOrderCallback: AddOrderCallback uploadAppData: (params: UploadAppDataParams) => void } + sellTokenContract: Erc20 | null dispatch: AppDispatch swapFlowAnalyticsContext: SwapFlowAnalyticsContext swapConfirmManager: SwapConfirmManager @@ -43,6 +44,8 @@ export interface BaseFlowContext { export type SwapFlowContext = BaseFlowContext & { contract: GPv2Settlement + permitInfo: IsTokenPermittableResult + hasEnoughAllowance: boolean | undefined } export type EthFlowContext = BaseFlowContext & { diff --git a/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts b/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts index cdadded320..5e466ff5bd 100644 --- a/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts +++ b/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts @@ -26,12 +26,19 @@ export interface UseEnoughBalanceParams { checkAllowanceAddress?: string } +export type UseEnoughBalanceAndAllowanceResult = { + enoughBalance: boolean | undefined + enoughAllowance: boolean | undefined +} + +const DEFAULT_BALANCE_AND_ALLOWANCE = { enoughBalance: undefined, enoughAllowance: undefined } + /** * Check if the account has enough balance and optionally allowance - * @param params Parameters to check balance and optionally the allowance - * @returns true if the account has enough balance (and allowance if it applies) + * @param params UseEnoughBalanceParams to check balance and optionally the allowance + * @returns UseEnoughBalanceAndAllowanceResult */ -export function useEnoughBalanceAndAllowance(params: UseEnoughBalanceParams): boolean | undefined { +export function useEnoughBalanceAndAllowance(params: UseEnoughBalanceParams): UseEnoughBalanceAndAllowanceResult { const { account, amount, checkAllowanceAddress } = params const isNativeCurrency = amount?.currency.isNative const token = amount?.currency.wrapped @@ -75,11 +82,11 @@ export interface EnoughBalanceParams extends Omit ({ - ...jest.requireActual('api/gnosisProtocol/api'), - getQuote: jest.fn(), -})) - -jest.mock('modules/tokens', () => ({ - ...jest.requireActual('modules/tokens'), - useEnoughBalanceAndAllowance: jest.fn(), -})) - -const getQuoteMock = jest.mocked(getQuote) -const useEnoughBalanceAndAllowanceMock = jest.mocked(useEnoughBalanceAndAllowance) +const getQuoteMock = jest.spyOn(orderBookApi, 'getQuote') +const useEnoughBalanceAndAllowanceMock = jest.spyOn(tokensModule, 'useEnoughBalanceAndAllowance') const inputCurrencyAmount = CurrencyAmount.fromRawAmount(WETH_GOERLI, 10_000_000) const outputCurrencyAmount = CurrencyAmount.fromRawAmount(COW[5], 2_000_000) @@ -44,6 +34,7 @@ const walletInfoMock: WalletInfo = { account: '0x333333f332a06ecb5d20d35da44ba07986d6e203', active: true, } + const limitOrdersDerivedStateMock: LimitOrdersDerivedState = { ...DEFAULT_TRADE_DERIVED_STATE, inputCurrency: inputCurrencyAmount.currency, @@ -71,7 +62,7 @@ describe('useTradeQuotePolling()', () => { beforeEach(() => { jest.clearAllMocks() - getQuoteMock.mockReturnValue(new Promise(() => void 0)) + getQuoteMock.mockImplementation(() => new Promise(() => void 0)) useEnoughBalanceAndAllowanceMock.mockReturnValue(true) }) @@ -86,14 +77,14 @@ describe('useTradeQuotePolling()', () => { // Assert const callParams = getQuoteMock.mock.calls[0][0] - expect(callParams.userAddress).toBe(walletInfoMock.account) // useAddress field value + expect(callParams.from).toBe(walletInfoMock.account) // useAddress field value expect(getQuoteMock).toHaveBeenCalledTimes(1) expect(callParams).toMatchSnapshot() }) }) describe('When wallet is NOT connected', () => { - it('Then the "useAddress" field in the quote request should be 0x000...0000', () => { + it('Then the "useAddress" field in the quote request should be 0x000...0000', () => { // Arrange const mocks = [...jotaiMock, [walletInfoAtom, { ...walletInfoMock, account: undefined }]] @@ -103,7 +94,7 @@ describe('useTradeQuotePolling()', () => { // Assert const callParams = getQuoteMock.mock.calls[0][0] - expect(callParams.userAddress).toBe(undefined) // useAddress field value + expect(callParams.from).toBe(ZERO_ADDRESS) // useAddress field value expect(getQuoteMock).toHaveBeenCalledTimes(1) expect(callParams).toMatchSnapshot() }) diff --git a/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts b/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts new file mode 100644 index 0000000000..58cc084f2d --- /dev/null +++ b/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts @@ -0,0 +1,48 @@ +import { defaultAbiCoder, ParamType } from '@ethersproject/abi' +import { TypedDataField } from '@ethersproject/abstract-signer' +import type { Web3Provider } from '@ethersproject/providers' +import { Wallet } from '@ethersproject/wallet' + +import { AbiItem, EIP712TypedData, ProviderConnector } from '@1inch/permit-signed-approvals-utils' +import { AbiInput } from 'web3-utils' + +import { getContract } from 'legacy/utils' + +export class PermitProviderConnector implements ProviderConnector { + constructor(private provider: Web3Provider, private walletSigner?: Wallet | undefined) {} + + contractEncodeABI(abi: AbiItem[], address: string | null, methodName: string, methodParams: unknown[]): string { + const contract = getContract(address || '', abi, this.provider) + + return contract.interface.encodeFunctionData(methodName, methodParams) + } + + signTypedData(_walletAddress: string, typedData: EIP712TypedData, _typedDataHash: string): Promise { + // Removes `EIP712Domain` as it's already part of EIP712 (see https://ethereum.stackexchange.com/a/151930/55204) + // and EthersJS complains when a type is not needed (see https://github.com/ethers-io/ethers.js/discussions/4000) + const types = Object.keys(typedData.types).reduce>((acc, type) => { + if (type !== 'EIP712Domain') { + acc[type] = typedData.types[type] + } + return acc + }, {}) + + const signer = this.walletSigner || this.provider.getSigner() + + return signer._signTypedData(typedData.domain, types, typedData.message) + } + + ethCall(contractAddress: string, callData: string): Promise { + return this.provider.call({ + to: contractAddress, + data: callData, + }) + } + + decodeABIParameter(type: string, hex: string): T { + return defaultAbiCoder.decode([type], hex)[0] + } + decodeABIParameters(types: AbiInput[], hex: string): T { + return defaultAbiCoder.decode(types as unknown as (ParamType | string)[], hex) as T + } +} diff --git a/apps/cowswap-frontend/vite.config.ts b/apps/cowswap-frontend/vite.config.ts index 2c06ac89b6..51c69e5673 100644 --- a/apps/cowswap-frontend/vite.config.ts +++ b/apps/cowswap-frontend/vite.config.ts @@ -132,9 +132,6 @@ export default defineConfig(({ mode }) => { manualChunks(id) { if (id.includes('@1inch')) return '@1inch' if (id.includes('@amplitude')) return '@amplitude' - if (id.includes('@cowprotocol')) return '@cowprotocol' - if (id.includes('@ethersproject')) return '@ethersproject' - if (id.includes('@metamask') || id.includes('elliptic')) return '@metamask' if (id.includes('@safe-global') || id.includes('viem')) return '@safe-global' if (id.includes('@sentry')) return '@sentry' if (id.includes('@uniswap')) return '@uniswap' diff --git a/libs/abis/src/abis-legacy/erc20.json b/libs/abis/src/abis-legacy/erc20.json index dd7bf99d6e..58c0e583be 100644 --- a/libs/abis/src/abis-legacy/erc20.json +++ b/libs/abis/src/abis-legacy/erc20.json @@ -3,7 +3,12 @@ "constant": true, "inputs": [], "name": "name", - "outputs": [{ "name": "", "type": "string" }], + "outputs": [ + { + "name": "", + "type": "string" + } + ], "payable": false, "stateMutability": "view", "type": "function" @@ -11,11 +16,22 @@ { "constant": false, "inputs": [ - { "name": "_spender", "type": "address" }, - { "name": "_value", "type": "uint256" } + { + "name": "_spender", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } ], "name": "approve", - "outputs": [{ "name": "", "type": "bool" }], + "outputs": [ + { + "name": "", + "type": "bool" + } + ], "payable": false, "stateMutability": "nonpayable", "type": "function" @@ -24,7 +40,12 @@ "constant": true, "inputs": [], "name": "totalSupply", - "outputs": [{ "name": "", "type": "uint256" }], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], "payable": false, "stateMutability": "view", "type": "function" @@ -32,12 +53,26 @@ { "constant": false, "inputs": [ - { "name": "_from", "type": "address" }, - { "name": "_to", "type": "address" }, - { "name": "_value", "type": "uint256" } + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } ], "name": "transferFrom", - "outputs": [{ "name": "", "type": "bool" }], + "outputs": [ + { + "name": "", + "type": "bool" + } + ], "payable": false, "stateMutability": "nonpayable", "type": "function" @@ -46,16 +81,31 @@ "constant": true, "inputs": [], "name": "decimals", - "outputs": [{ "name": "", "type": "uint8" }], + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, - "inputs": [{ "name": "_owner", "type": "address" }], + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], "name": "balanceOf", - "outputs": [{ "name": "balance", "type": "uint256" }], + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], "payable": false, "stateMutability": "view", "type": "function" @@ -64,7 +114,12 @@ "constant": true, "inputs": [], "name": "symbol", - "outputs": [{ "name": "", "type": "string" }], + "outputs": [ + { + "name": "", + "type": "string" + } + ], "payable": false, "stateMutability": "view", "type": "function" @@ -72,11 +127,22 @@ { "constant": false, "inputs": [ - { "name": "_to", "type": "address" }, - { "name": "_value", "type": "uint256" } + { + "name": "_to", + "type": "address" + }, + { + "name": "_value", + "type": "uint256" + } ], "name": "transfer", - "outputs": [{ "name": "", "type": "bool" }], + "outputs": [ + { + "name": "", + "type": "bool" + } + ], "payable": false, "stateMutability": "nonpayable", "type": "function" @@ -84,22 +150,49 @@ { "constant": true, "inputs": [ - { "name": "_owner", "type": "address" }, - { "name": "_spender", "type": "address" } + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } ], "name": "allowance", - "outputs": [{ "name": "", "type": "uint256" }], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], "payable": false, "stateMutability": "view", "type": "function" }, - { "payable": true, "stateMutability": "payable", "type": "fallback" }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, { "anonymous": false, "inputs": [ - { "indexed": true, "name": "owner", "type": "address" }, - { "indexed": true, "name": "spender", "type": "address" }, - { "indexed": false, "name": "value", "type": "uint256" } + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } ], "name": "Approval", "type": "event" @@ -107,11 +200,85 @@ { "anonymous": false, "inputs": [ - { "indexed": true, "name": "from", "type": "address" }, - { "indexed": true, "name": "to", "type": "address" }, - { "indexed": false, "name": "value", "type": "uint256" } + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } ], "name": "Transfer", "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ] diff --git a/libs/abis/src/generated/legacy/Erc20.ts b/libs/abis/src/generated/legacy/Erc20.ts index 54c74b62a9..2de889a712 100644 --- a/libs/abis/src/generated/legacy/Erc20.ts +++ b/libs/abis/src/generated/legacy/Erc20.ts @@ -28,6 +28,8 @@ export interface Erc20Interface extends utils.Interface { 'symbol()': FunctionFragment 'transfer(address,uint256)': FunctionFragment 'allowance(address,address)': FunctionFragment + 'nonces(address)': FunctionFragment + 'permit(address,address,uint256,uint256,uint8,bytes32,bytes32)': FunctionFragment } getFunction( @@ -41,6 +43,8 @@ export interface Erc20Interface extends utils.Interface { | 'symbol' | 'transfer' | 'allowance' + | 'nonces' + | 'permit' ): FunctionFragment encodeFunctionData(functionFragment: 'name', values?: undefined): string @@ -61,6 +65,19 @@ export interface Erc20Interface extends utils.Interface { values: [PromiseOrValue, PromiseOrValue] ): string encodeFunctionData(functionFragment: 'allowance', values: [PromiseOrValue, PromiseOrValue]): string + encodeFunctionData(functionFragment: 'nonces', values: [PromiseOrValue]): string + encodeFunctionData( + functionFragment: 'permit', + values: [ + PromiseOrValue, + PromiseOrValue, + PromiseOrValue, + PromiseOrValue, + PromiseOrValue, + PromiseOrValue, + PromiseOrValue + ] + ): string decodeFunctionResult(functionFragment: 'name', data: BytesLike): Result decodeFunctionResult(functionFragment: 'approve', data: BytesLike): Result @@ -71,6 +88,8 @@ export interface Erc20Interface extends utils.Interface { decodeFunctionResult(functionFragment: 'symbol', data: BytesLike): Result decodeFunctionResult(functionFragment: 'transfer', data: BytesLike): Result decodeFunctionResult(functionFragment: 'allowance', data: BytesLike): Result + decodeFunctionResult(functionFragment: 'nonces', data: BytesLike): Result + decodeFunctionResult(functionFragment: 'permit', data: BytesLike): Result events: { 'Approval(address,address,uint256)': EventFragment @@ -156,6 +175,19 @@ export interface Erc20 extends BaseContract { _spender: PromiseOrValue, overrides?: CallOverrides ): Promise<[BigNumber]> + + nonces(owner: PromiseOrValue, overrides?: CallOverrides): Promise<[BigNumber]> + + permit( + owner: PromiseOrValue, + spender: PromiseOrValue, + value: PromiseOrValue, + deadline: PromiseOrValue, + v: PromiseOrValue, + r: PromiseOrValue, + s: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise } name(overrides?: CallOverrides): Promise @@ -193,6 +225,19 @@ export interface Erc20 extends BaseContract { overrides?: CallOverrides ): Promise + nonces(owner: PromiseOrValue, overrides?: CallOverrides): Promise + + permit( + owner: PromiseOrValue, + spender: PromiseOrValue, + value: PromiseOrValue, + deadline: PromiseOrValue, + v: PromiseOrValue, + r: PromiseOrValue, + s: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise + callStatic: { name(overrides?: CallOverrides): Promise @@ -228,6 +273,19 @@ export interface Erc20 extends BaseContract { _spender: PromiseOrValue, overrides?: CallOverrides ): Promise + + nonces(owner: PromiseOrValue, overrides?: CallOverrides): Promise + + permit( + owner: PromiseOrValue, + spender: PromiseOrValue, + value: PromiseOrValue, + deadline: PromiseOrValue, + v: PromiseOrValue, + r: PromiseOrValue, + s: PromiseOrValue, + overrides?: CallOverrides + ): Promise } filters: { @@ -289,6 +347,19 @@ export interface Erc20 extends BaseContract { _spender: PromiseOrValue, overrides?: CallOverrides ): Promise + + nonces(owner: PromiseOrValue, overrides?: CallOverrides): Promise + + permit( + owner: PromiseOrValue, + spender: PromiseOrValue, + value: PromiseOrValue, + deadline: PromiseOrValue, + v: PromiseOrValue, + r: PromiseOrValue, + s: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise } populateTransaction: { @@ -326,5 +397,18 @@ export interface Erc20 extends BaseContract { _spender: PromiseOrValue, overrides?: CallOverrides ): Promise + + nonces(owner: PromiseOrValue, overrides?: CallOverrides): Promise + + permit( + owner: PromiseOrValue, + spender: PromiseOrValue, + value: PromiseOrValue, + deadline: PromiseOrValue, + v: PromiseOrValue, + r: PromiseOrValue, + s: PromiseOrValue, + overrides?: Overrides & { from?: PromiseOrValue } + ): Promise } } diff --git a/libs/abis/src/generated/legacy/factories/Erc20__factory.ts b/libs/abis/src/generated/legacy/factories/Erc20__factory.ts index d0ccd7b39f..b344021c45 100644 --- a/libs/abis/src/generated/legacy/factories/Erc20__factory.ts +++ b/libs/abis/src/generated/legacy/factories/Erc20__factory.ts @@ -227,6 +227,68 @@ const _abi = [ name: 'Transfer', type: 'event', }, + { + constant: true, + inputs: [ + { + name: 'owner', + type: 'address', + }, + ], + name: 'nonces', + outputs: [ + { + name: '', + type: 'uint256', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'deadline', + type: 'uint256', + }, + { + internalType: 'uint8', + name: 'v', + type: 'uint8', + }, + { + internalType: 'bytes32', + name: 'r', + type: 'bytes32', + }, + { + internalType: 'bytes32', + name: 's', + type: 'bytes32', + }, + ], + name: 'permit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, ] as const export class Erc20__factory { diff --git a/package.json b/package.json index 74f3426a65..0f6dab69a7 100644 --- a/package.json +++ b/package.json @@ -43,13 +43,14 @@ ] }, "dependencies": { + "@1inch/permit-signed-approvals-utils": "^1.4.8", "@amplitude/analytics-browser": "^1.1.4", "@babel/runtime": "^7.17.0", "@coinbase/wallet-sdk": "^3.3.0", - "@cowprotocol/app-data": "v0.2.7", + "@cowprotocol/app-data": "^1.1.0-RC.0", "@cowprotocol/contracts": "^1.3.1", "@cowprotocol/cow-runner-game": "^0.2.9", - "@cowprotocol/cow-sdk": "^2.3.0", + "@cowprotocol/cow-sdk": "^3.0.0-rc.0", "@cowprotocol/ethflowcontract": "cowprotocol/ethflowcontract.git#v1.0.0-artifacts", "@davatar/react": "1.8.1", "@ethersproject/bignumber": "^5.7.0", diff --git a/yarn.lock b/yarn.lock index 92ba99114d..690b3eb08a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,15 @@ # yarn lockfile v1 +"@1inch/permit-signed-approvals-utils@^1.4.8": + version "1.4.8" + resolved "https://registry.yarnpkg.com/@1inch/permit-signed-approvals-utils/-/permit-signed-approvals-utils-1.4.8.tgz#d5d20e9e8a763f2649945aef8b843034a9a92c52" + integrity sha512-1U9U/tdvZpp9ZXaNmiiehu6S2EIYV3A4c1pj48oPcObRaWxX0QSDCrEHh95eJ0ND9y7QgvdlOy8DSAWUmxZOhA== + dependencies: + "@metamask/eth-sig-util" "^4.0.1" + web3 "^1.5.1" + web3-utils "^1.5.1" + "@aashutoshrathi/word-wrap@^1.2.3": version "1.2.6" resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" @@ -1439,14 +1448,15 @@ dependencies: chalk "^4.1.0" -"@cowprotocol/app-data@v0.2.7": - version "0.2.7" - resolved "https://registry.yarnpkg.com/@cowprotocol/app-data/-/app-data-0.2.7.tgz#8cabd22f9491119111176ab544c323f793169818" - integrity sha512-kN+eiG4r49Q0yUp/TyhRZsAHCvt2RNR9EhI/1XubQYiTa5Il0CiSVLUjDbV1r2BYyZ6JBMMtHS/n8dCT2or/BQ== +"@cowprotocol/app-data@^1.1.0-RC.0": + version "1.1.0-RC.0" + resolved "https://registry.yarnpkg.com/@cowprotocol/app-data/-/app-data-1.1.0-RC.0.tgz#ac4e5d7a036c4033df431e07f7670e47be7662fd" + integrity sha512-tQrFTTXu2beVrPnHlB1YsRfYpmK9wvYpqJXsdHlXisuTm38EGPMSIAxV9NxYFbqlbslmYvBX7uSFPO70kMrN9g== dependencies: ajv "^8.11.0" cross-fetch "^3.1.5" ipfs-only-hash "^4.0.0" + json-stringify-deterministic "^1.0.8" multiformats "^9.6.4" "@cowprotocol/contracts@^1.3.1", "@cowprotocol/contracts@^1.4.0": @@ -1459,13 +1469,14 @@ resolved "https://registry.yarnpkg.com/@cowprotocol/cow-runner-game/-/cow-runner-game-0.2.9.tgz#3f94b3f370bd114f77db8b1d238cba3ef4e9d644" integrity sha512-rX7HnoV+HYEEkBaqVUsAkGGo0oBrExi+d6Io+8nQZYwZk+IYLmS9jdcIObsLviM2h4YX8+iin6NuKl35AaiHmg== -"@cowprotocol/cow-sdk@^2.3.0": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@cowprotocol/cow-sdk/-/cow-sdk-2.3.1.tgz#ea7347869eada629b706cc24567ddcaa48bcc1ed" - integrity sha512-Rn3zCo3VCPqi3Wzqov0mDHXVVxBVhkLpnxnxcEZW7Kpv9WGcudl1vpz9e3Gs3YMzUQ5G6IA+kHxm5l81boIPhQ== +"@cowprotocol/cow-sdk@^3.0.0-rc.0": + version "3.0.0-rc.0" + resolved "https://registry.yarnpkg.com/@cowprotocol/cow-sdk/-/cow-sdk-3.0.0-rc.0.tgz#2583d3726a0f559b2a2faf86ed86261820b93311" + integrity sha512-hdAkLKdda7kPXHZxhDKvRo01MbFMHM+WV8okPJL0xgpVsjzQTCitKkitUf3e9kSdyUebdaGe3iWVZviCiI72ew== dependencies: "@cowprotocol/contracts" "^1.4.0" "@ethersproject/abstract-signer" "^5.7.0" + "@openzeppelin/merkle-tree" "^1.0.5" cross-fetch "^3.1.5" exponential-backoff "^3.1.1" graphql-request "^4.3.0" @@ -3234,6 +3245,17 @@ resolved "https://registry.yarnpkg.com/@metamask/detect-provider/-/detect-provider-1.2.0.tgz#3667a7531f2a682e3c3a43eaf3a1958bdb42a696" integrity sha512-ocA76vt+8D0thgXZ7LxFPyqw3H7988qblgzddTDA6B8a/yU0uKV42QR/DhA+Jh11rJjxW0jKvwb5htA6krNZDQ== +"@metamask/eth-sig-util@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" + integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^6.2.1" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + "@metamask/eth-sig-util@^5.0.2": version "5.1.0" resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-5.1.0.tgz#a47f62800ee1917fef976ba67544a0ccd7d1bd6b" @@ -3420,6 +3442,11 @@ dependencies: "@noble/hashes" "1.3.1" +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== + "@noble/hashes@1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" @@ -3430,6 +3457,11 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -3904,6 +3936,14 @@ yargs "^17.6.2" yargs-parser "21.1.1" +"@openzeppelin/merkle-tree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@openzeppelin/merkle-tree/-/merkle-tree-1.0.5.tgz#4836d377777a7e39f31674f06ec3d6909def7913" + integrity sha512-JkwG2ysdHeIphrScNxYagPy6jZeNONgDRyqU6lbFgE8HKCZFSkcP8r6AjZs+3HZk4uRNV0kNBBzuWhKQ3YV7Kw== + dependencies: + "@ethersproject/abi" "^5.7.0" + ethereum-cryptography "^1.1.2" + "@parcel/watcher@2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.4.tgz#f300fef4cc38008ff4b8c29d92588eced3ce014b" @@ -4372,6 +4412,15 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== +"@scure/bip32@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" + integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== + dependencies: + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" + "@scure/base" "~1.1.0" + "@scure/bip32@1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87" @@ -4390,6 +4439,14 @@ "@noble/hashes" "~1.3.1" "@scure/base" "~1.1.0" +"@scure/bip39@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== + dependencies: + "@noble/hashes" "~1.2.0" + "@scure/base" "~1.1.0" + "@scure/bip39@1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b" @@ -5567,6 +5624,13 @@ dependencies: "@babel/types" "^7.20.7" +"@types/bn.js@^4.11.3": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + "@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" @@ -8521,7 +8585,7 @@ bn.js@4.11.8: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.12.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.12.0: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== @@ -11097,7 +11161,7 @@ electron-to-chromium@^1.4.477: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.477.tgz#05669aa6f161ee9076a6805457e9bd9fe6d0dfd1" integrity sha512-shUVy6Eawp33dFBFIoYbIwLHrX0IZ857AlH9ug2o4rvbWmpaCUdBpQ5Zw39HRrfzAFm4APJE9V+E2A/WB0YqJw== -elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.3, elliptic@^6.5.4: +elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -11965,6 +12029,16 @@ ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" +ethereum-cryptography@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" + integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== + dependencies: + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/bip32" "1.1.5" + "@scure/bip39" "1.1.1" + ethereum-cryptography@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" @@ -11975,6 +12049,27 @@ ethereum-cryptography@^2.0.0: "@scure/bip32" "1.3.1" "@scure/bip39" "1.2.1" +ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" @@ -12030,7 +12125,7 @@ ethjs-unit@0.1.6: bn.js "4.11.6" number-to-bn "1.7.0" -ethjs-util@^0.1.6: +ethjs-util@0.1.6, ethjs-util@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== @@ -15947,6 +16042,11 @@ json-stable-stringify@^1.0.2: dependencies: jsonify "^0.0.1" +json-stringify-deterministic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/json-stringify-deterministic/-/json-stringify-deterministic-1.0.10.tgz#d56660b6e9c12f47dee4340ec2ce26745fa6ee64" + integrity sha512-hBLYMyCnoYh0rQ2ZyEegbLaFAS5KqOZ6HZ5fgq6lGWhtNRKw2JUp/hkfjQS1bjYZlHW9AjvXBWCJe9OwcugRNw== + json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -20407,7 +20507,7 @@ ripple-lib@^1.10.1: ripple-lib-transactionparser "0.8.2" ws "^7.2.0" -rlp@^2.2.4: +rlp@^2.2.3, rlp@^2.2.4: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== @@ -23296,7 +23396,7 @@ web3-shh@1.10.0: web3-core-subscriptions "1.10.0" web3-net "1.10.0" -web3-utils@1.10.0, web3-utils@^1.8.1: +web3-utils@1.10.0, web3-utils@^1.5.1, web3-utils@^1.8.1: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578" integrity sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg== @@ -23309,7 +23409,7 @@ web3-utils@1.10.0, web3-utils@^1.8.1: randombytes "^2.1.0" utf8 "3.0.0" -web3@^1.8.1: +web3@^1.5.1, web3@^1.8.1: version "1.10.0" resolved "https://registry.yarnpkg.com/web3/-/web3-1.10.0.tgz#2fde0009f59aa756c93e07ea2a7f3ab971091274" integrity sha512-YfKY9wSkGcM8seO+daR89oVTcbu18NsVfvOngzqMYGUU0pPSQmE57qQDvQzUeoIOHAnXEBNzrhjQJmm8ER0rng== From 3b396b8788ea315e7c18d16b825d9f7d758b20e4 Mon Sep 17 00:00:00 2001 From: Alfetopito Date: Thu, 21 Sep 2023 15:05:29 +0100 Subject: [PATCH 07/36] fix: add missing dep to useEffect in useIsTokenPermittable --- .../src/modules/permit/hooks/useIsTokenPermittable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts index b97e5e38b6..ccf2505ac0 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts @@ -56,7 +56,7 @@ export function useIsTokenPermittable(token: Nullish): IsTokenPermitta addPermitInfo({ chainId, tokenAddress: lowerCaseAddress, permitInfo: result }) } }) - }, [addPermitInfo, chainId, isNative, lowerCaseAddress, permitInfo, provider, tokenName]) + }, [addPermitInfo, chainId, isNative, isPermitEnabled, lowerCaseAddress, permitInfo, provider, tokenName]) if (isNative) { return false From 1cdfa24c6448e3ebf2c6e3c986cb5d7bfd269aa4 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Thu, 21 Sep 2023 17:55:45 +0300 Subject: [PATCH 08/36] feat: split app into libs and NX cloud integration (#3108) --- .github/workflows/ci.yml | 1 - apps/cowswap-frontend/.eslintrc.json | 2 +- apps/cowswap-frontend/jest.config.ts | 2 +- apps/cowswap-frontend/jest.preset.js | 11 - apps/cowswap-frontend/project.json | 2 +- apps/cowswap-frontend/src/api/1inch/index.ts | 4 +- .../src/{legacy/utils => api}/blocknative.ts | 4 +- .../src/api/gasPrices/index.ts | 4 +- .../src/api/gnosisProtocol/api.ts | 8 +- .../src/api/gnosisProtocol/hooks.ts | 5 +- .../src/api/gnosisProtocol/priceApi.ts | 4 +- .../src/api/matcha-0x/index.ts | 4 +- apps/cowswap-frontend/src/api/proxy/hooks.ts | 8 +- .../src/common/constants/featureFlags.ts | 1 - .../src/common/constants/routes.ts | 3 +- .../containers/ImportTokenModal/index.tsx | 9 +- .../MultipleOrdersCancellationModal/index.tsx | 10 +- .../TradeApprove/TradeApproveModal.tsx | 5 +- .../TradeApprove/useTradeApproveCallback.ts | 5 +- .../WalletUnsupportedNetworkBanner/index.tsx | 6 +- .../ZeroApprovalModal/ZeroApprovalModal.tsx | 2 +- .../hooks/useAnalyticsReporter.ts | 27 +- .../src/common/hooks/useApproveCallback.ts | 9 +- .../src/common/hooks/useApproveState.ts | 10 +- .../hooks/useAreThereTokensWithSameSymbol.ts | 2 +- .../src/common/hooks/useCancelOrder/index.ts | 5 +- .../useCancelOrder/onChainCancellation.ts | 4 +- .../useGetOnChainCancellation.ts | 3 +- .../useCancelOrder/useOffChainCancelOrder.ts | 3 +- .../useSendOnChainCancellation.test.ts | 22 +- .../useSendOnChainCancellation.ts | 3 +- .../hooks/useConfirmPriceImpactWithoutFee.ts | 3 +- .../common/hooks/useExternalTokenSearch.ts | 3 +- .../hooks/useGetMarketDimension.ts | 0 .../common/hooks/useGetSurplusFiatValue.ts | 2 +- .../common/hooks/useIsSmartContractWallet.ts | 54 ---- .../common/hooks/useLegacySetChainIdToUrl.ts | 3 +- .../useCancelMultipleOrders.ts | 3 +- .../src/common/hooks/useNeedsApproval.ts | 4 +- .../src/common/hooks/useNeedsZeroApproval.ts | 2 +- .../src/common/hooks/useOnSelectNetwork.ts | 5 +- .../src/common/hooks/usePrice.ts | 3 +- .../src/common/hooks/useRateInfoParams.ts | 4 +- .../hooks/useSafeApiKit.ts | 6 +- .../useShouldZeroApprove/shouldZeroApprove.ts | 2 +- .../useShouldZeroApprove.ts | 3 +- .../common/hooks/useTokenBySymbolOrAddress.ts | 2 +- .../common/hooks/useTradeSpenderAddress.ts | 5 +- .../src/common/hooks/useWalletStatusIcon.ts | 2 +- .../src/common/hooks/useZeroApprove.ts | 6 +- .../pure/AnimatedConfirmation/index.tsx | 4 +- .../pure/ApproveButton/index.cosmos.tsx | 2 +- .../src/common/pure/ApproveButton/index.tsx | 8 +- .../RequestCancellationModal.tsx | 3 +- .../common/pure/CancellationModal/index.tsx | 5 +- .../ConfirmationPendingContent.cosmos.tsx | 2 +- .../ConfirmationPendingContent/styled.tsx | 6 +- .../pure/ConfirmedButton/ConfirmedButton.tsx | 4 +- .../common/pure/CowSwapSafeAppLink/index.tsx | 2 +- .../pure/CurrencyAmountPreview/index.tsx | 2 +- .../pure/CurrencyArrowSeparator/index.tsx | 2 +- .../CurrencyInputPanel/CurrencyInputPanel.tsx | 10 +- .../defaultCurrencyInputProps.ts | 4 +- .../pure/CurrencyInputPanel/index.cosmos.tsx | 4 +- .../common/pure/CurrencyInputPanel/styled.tsx | 4 +- .../common/pure/CurrencyInputPanel/types.ts | 2 +- .../CurrencyLogo/hooks/useCurrencyLogoURIs.ts | 10 +- .../CurrencySelectButton/index.cosmos.tsx | 3 +- .../pure/CurrencySelectButton/index.tsx | 2 +- .../pure/CurrencySelectButton/styled.tsx | 4 +- .../src/common/pure/ExecutedSummary/styled.ts | 6 +- .../hooks/useExecutionPriceFiat.ts | 3 +- .../src/common/pure/ExecutionPrice/index.tsx | 6 +- .../src/common/pure/FiatValue/index.tsx | 2 +- .../src/common/pure/HelpCircle/index.tsx | 3 +- .../src/common/pure/InlineBanner/banners.tsx | 3 +- .../src/common/pure/InlineBanner/index.tsx | 10 +- .../src/common/pure/Modal/index.tsx | 43 +-- .../src/common/pure/NetworksList/index.tsx | 9 +- .../pure/OrderSubmittedContent/index.tsx | 4 +- .../pure/PriceImpactIndicator/index.tsx | 7 +- .../src/common/pure/RateInfo/index.cosmos.tsx | 7 +- .../src/common/pure/RateInfo/index.tsx | 6 +- .../src/common/pure/SafeWalletLink/index.tsx | 5 +- .../src/common/pure/SelectDropdown/index.tsx | 31 -- .../common/pure/TradeLoadingButton/index.tsx | 3 +- .../pure/TransactionErrorContent/index.tsx | 3 +- .../SurplusModal.tsx | 14 +- .../TransactionSubmittedContent/index.tsx | 4 +- .../common/services/getQuoteCurrency/index.ts | 9 +- .../state/totalSurplusState/updaters.ts | 3 +- .../updaters/ApplicationUpdater.ts} | 12 +- .../updaters}/CancelReplaceTxUpdater.tsx | 6 +- .../updaters/FeesUpdater.ts} | 29 +- .../updaters}/FinalizeTxUpdater.tsx | 20 +- .../updaters/GasUpdater.tsx} | 32 +- .../updaters/HwAccountIndexUpdater.tsx | 5 +- .../updaters/ListsUpdater.ts} | 11 +- .../updaters/LogsUpdater.ts} | 15 +- .../updaters/SentryUpdater.ts} | 31 +- .../updaters/UserUpdater.tsx} | 5 +- .../orders}/CancelledOrdersUpdater.ts | 7 +- .../updaters/orders}/ExpiredOrdersUpdater.ts | 5 +- .../updaters/orders}/GpOrdersUpdater.ts | 7 +- .../updaters/orders}/PendingOrdersUpdater.ts | 19 +- .../updaters/orders}/SpotPricesUpdater.ts | 10 +- .../orders}/UnfillableOrdersUpdater.ts | 16 +- .../updaters/orders}/index.ts | 0 .../updaters/orders}/utils.ts | 4 +- .../common/utils/isOrderCancellable.test.ts | 5 +- .../src/common/utils/markets.ts | 11 - .../cowswap-frontend/src/cosmos.decorator.tsx | 19 +- apps/cowswap-frontend/src/cow-react/index.tsx | 16 +- .../src/{utils => cow-react}/sentry.ts | 4 +- apps/cowswap-frontend/src/cowSdk.ts | 3 +- apps/cowswap-frontend/src/i18n.tsx | 3 +- .../src/legacy/components/AMMsLogo/index.tsx | 27 +- .../components/AddressInputPanel/index.tsx | 13 +- .../legacy/components/AppziButton/index.tsx | 6 +- .../legacy/components/Badge/RangeBadge.tsx | 4 +- .../__fixtures__/ButtonRadioChecked.tsx | 9 - .../src/legacy/components/Confetti/index.tsx | 4 +- .../src/legacy/components/Copy/CopyMod.tsx | 3 +- .../legacy/components/CowBalance/index.tsx | 3 +- .../components/CowBalanceButton/index.tsx | 5 +- .../components/CowProtocolLogo/index.tsx | 4 +- .../CowSubsidyModal/SubsidyTable.tsx | 4 +- .../components/CowSubsidyModal/index.tsx | 14 +- .../ErrorBoundary/ChunkLoadError.tsx | 12 +- .../ErrorBoundary/ErrorWithStackTrace.tsx | 15 +- .../legacy/components/ErrorBoundary/index.tsx | 4 +- .../legacy/components/ExplorerLink/index.tsx | 11 +- .../components/FlashingLoading/index.tsx | 4 +- .../Header/ChainConnectivityWarning.tsx | 5 +- .../Header/NetworkSelector/index.tsx | 7 +- .../src/legacy/components/Header/Polling.tsx | 19 +- .../components/Header/URLWarning/index.tsx | 9 +- .../src/legacy/components/Header/index.tsx | 15 +- .../src/legacy/components/Header/styled.tsx | 3 +- .../components/HoverInlineText/index.tsx | 4 +- .../src/legacy/components/InfoIcon/index.tsx | 4 +- .../src/legacy/components/Link/index.tsx | 4 +- .../legacy/components/Loader/Logo/index.tsx | 4 +- .../src/legacy/components/Markdown/index.tsx | 4 +- .../legacy/components/MenuDropdown/index.tsx | 5 +- .../components/NetworkAlert/NetworkAlert.tsx | 12 +- .../legacy/components/NetworkAlert/styles.ts | 4 +- .../components/NumericalInput/index.tsx | 4 +- .../components/OrderProgressBar/index.tsx | 16 +- .../components/OrderProgressBar/styled.ts | 6 +- .../Popups/FailedNetworkSwitchPopup.tsx | 4 +- .../legacy/components/Popups/PopupItem.tsx | 2 +- .../components/Popups/TransactionPopup.tsx | 8 +- .../legacy/components/Popups/WarningPopup.tsx | 3 +- .../src/legacy/components/Popups/index.tsx | 5 +- .../QuestionHelper/QuestionHelperMod.tsx | 5 +- .../components/QuestionHelper/index.tsx | 6 +- .../CommonBases/CommonBasesMod.tsx | 5 +- .../SearchModal/CommonBases/index.ts | 2 +- .../CurrencyList/CurrencyListMod.tsx | 21 +- .../SearchModal/CurrencyList/index.tsx | 38 +-- .../SearchModal/CurrencyList/styled.ts | 19 +- .../CurrencySearch/CurrencySearchMod.tsx | 24 +- .../SearchModal/CurrencySearch/index.tsx | 3 +- .../SearchModal/CurrencySearch/sorting.ts | 2 +- .../SearchModal/CurrencySearchModal.tsx | 5 +- .../SearchModal/ImportList/ImportListMod.tsx | 11 +- .../SearchModal/ImportList/index.tsx | 5 +- .../SearchModal/ImportRow/ImportRowMod.tsx | 6 +- .../SearchModal/ImportRow/index.tsx | 4 +- .../ImportToken/ImportTokenMod.tsx | 6 +- .../SearchModal/ImportToken/index.tsx | 5 +- .../SearchModal/Manage/ManageMod.tsx | 3 +- .../components/SearchModal/Manage/index.tsx | 2 +- .../ManageLists/ManageListsMod.tsx | 25 +- .../SearchModal/ManageLists/index.tsx | 9 +- .../ManageTokens/ManageTokensMod.tsx | 15 +- .../SearchModal/ManageTokens/index.tsx | 5 +- .../TokenImportCard/TokenImportCardMod.tsx | 10 +- .../legacy/components/SearchModal/styleds.tsx | 5 +- .../components/Settings/SettingsMod.tsx | 15 +- .../src/legacy/components/Settings/index.tsx | 3 +- .../src/legacy/components/Stepper/index.tsx | 10 +- .../legacy/components/SwapWarnings/index.tsx | 4 +- .../legacy/components/Tokens/BalanceCell.tsx | 11 +- .../Tokens/FavouriteTokenButton.tsx | 4 +- .../components/Tokens/FiatBalanceCell.tsx | 6 +- .../legacy/components/Tokens/TokensTable.tsx | 5 +- .../components/Tokens/TokensTableRow.tsx | 17 +- .../src/legacy/components/Tokens/styled.ts | 6 +- .../DisplayLink.tsx | 3 +- .../LegacyConfirmationPendingContent.tsx | 25 +- .../index.cosmos.tsx | 9 +- .../TransactionConfirmationModal/index.tsx | 8 +- .../TransactionConfirmationModal/styled.ts | 6 +- .../TransactionExecutedContent/index.tsx | 2 +- .../TransactionExecutedContent/styled.ts | 5 +- .../TransactionSettingsMod.tsx | 24 +- .../components/TransactionSettings/index.tsx | 4 +- .../src/legacy/components/Version/index.tsx | 16 +- .../Web3Provider}/hooks/useEagerlyConnect.ts | 20 +- .../hooks/useOrderedConnections.ts | 10 +- .../legacy/components/Web3Provider/index.tsx | 7 +- .../components/analytics/pixel/constants.ts | 3 - .../src/legacy/components/earn/styled.ts | 8 +- .../swap/ConfirmSwapModal/hooks.tsx | 3 +- .../swap/ConfirmSwapModal/index.tsx | 10 +- .../components/swap/FeeInformationTooltip.tsx | 5 +- .../swap/SwapHeader/SwapHeaderMod.tsx | 2 +- .../components/swap/SwapModalFooter/index.tsx | 5 +- .../SwapModalHeader/SwapModalHeaderMod.tsx | 10 +- .../components/swap/SwapModalHeader/index.tsx | 3 +- .../UnsupportedCurrencyFooterMod.tsx | 12 +- .../swap/UnsupportedCurrencyFooter/index.tsx | 4 +- .../swap/confirmPriceImpactWithoutFee.ts | 3 +- .../src/legacy/components/swap/styleds.tsx | 3 +- .../src/legacy/constants/chains.ts | 8 - .../src/legacy/constants/proposals/index.ts | 5 - .../proposals/polygon_proposal_title.ts | 1 - .../uniswap_grants_proposal_description.ts | 106 ------- .../src/legacy/hooks/Tokens.ts | 41 ++- .../src/legacy/hooks/useAccountRiskCheck.ts | 45 --- .../src/legacy/hooks/useActiveLocale.ts | 11 +- .../legacy/hooks/useActivityDerivedState.ts | 9 +- .../hooks/useAllCurrencyCombinations.ts | 73 ----- .../hooks/useApeModeQueryParamReader.ts | 24 -- .../legacy/hooks/useApproveCallback/index.ts | 12 +- .../useApproveCallbackMod.ts | 11 +- .../legacy/hooks/useArgentWalletContract.ts | 16 - .../src/legacy/hooks/useColor/index.ts | 1 - .../src/legacy/hooks/useCombinedBalance.ts | 57 ++++ .../legacy/hooks/useCowBalanceAndSubsidy.ts | 4 +- .../legacy/hooks/useCurrentBlockTimestamp.ts | 3 +- .../src/legacy/hooks/useENSAddress.ts | 38 --- .../src/legacy/hooks/useENSAvatar.ts | 165 ---------- .../src/legacy/hooks/useENSContentHash.ts | 32 -- .../src/legacy/hooks/useENSName.ts | 49 --- .../legacy/hooks/useErrorMessageAndModal.tsx | 29 -- .../hooks/useFavouriteOrCommonTokens.tsx | 6 +- .../src/legacy/hooks/useFetchListCallback.ts | 7 +- .../src/legacy/hooks/useGasPrice.ts | 6 +- .../src/legacy/hooks/useGetSafeInfo.ts | 9 +- .../src/legacy/hooks/useHttpLocations.ts | 7 +- .../src/legacy/hooks/useIsActiveWallet.ts | 3 +- .../src/legacy/hooks/useIsAmbireWallet.ts | 8 - .../src/legacy/hooks/useIsArgentWallet.ts | 15 - .../src/legacy/hooks/useIsSwapUnsupported.ts | 2 +- .../src/legacy/hooks/useLocationLinkProps.ts | 41 --- .../src/legacy/hooks/useNetworkName.ts | 13 - .../usePriceImpact/useFiatValuePriceImpact.ts | 5 +- .../src/legacy/hooks/useRecentActivity.ts | 8 +- .../legacy/hooks/useRefetchPriceCallback.tsx | 17 +- .../src/legacy/hooks/useTheme.ts | 7 - .../src/legacy/hooks/useTokenAllowance.ts | 3 +- .../hooks/useTokenInfoFromActiveList.ts | 26 -- .../src/legacy/hooks/useTokenLazy.ts | 9 +- .../src/legacy/hooks/useTotalSupply.ts | 3 +- .../hooks/useTransactionConfirmationModal.tsx | 4 +- .../src/legacy/hooks/useWrapCallback.ts | 15 +- .../src/legacy/state/application/hooks.ts | 16 +- .../legacy/state/application/initialState.ts | 4 +- .../legacy/state/application/localWarning.ts | 4 +- .../src/legacy/state/application/reducer.ts | 6 +- .../src/legacy/state/claim/actions.ts | 29 +- .../src/legacy/state/claim/hooks/const.ts | 7 + .../src/legacy/state/claim/hooks/index.ts | 97 ++---- .../src/legacy/state/claim/hooks/types.ts | 30 ++ .../src/legacy/state/claim/hooks/utils.ts | 21 +- .../Claim => legacy/state/claim}/types.ts | 4 +- .../src/legacy/state/claim/updater.tsx | 12 +- .../src/legacy/state/connection/hooks.ts | 38 --- .../src/legacy/state/connection/reducer.ts | 6 +- .../src/legacy/state/cowToken/hooks.ts | 70 +---- .../src/legacy/state/cowToken/middleware.ts | 6 +- .../hooks/TransactionHooksMod.tsx | 5 +- .../state/enhancedTransactions/hooks/index.ts | 6 +- .../state/enhancedTransactions/reducer.ts | 2 +- .../enhancedTransactions/updater/index.tsx | 13 - .../src/legacy/state/gas/actions.ts | 4 +- .../src/legacy/state/gas/atoms.ts | 2 +- .../state/gas/gas-price-strategy-updater.tsx | 10 +- .../src/legacy/state/gas/hooks.ts | 26 +- .../src/legacy/state/global/actions.ts | 2 +- .../src/legacy/state/hooks/index.ts | 2 +- .../src/legacy/state/index.ts | 58 ++-- .../src/legacy/state/lists/hooks.ts | 40 +-- .../src/legacy/state/lists/reducer.test.ts | 9 +- .../src/legacy/state/lists/reducer.ts | 16 +- .../legacy/state/lists/wrappedTokenInfo.ts | 3 +- .../src/legacy/state/logs/hooks.ts | 6 +- .../src/legacy/state/multicall.tsx | 13 + .../src/legacy/state/orders/actions.ts | 4 +- .../orders/buildCancellationPopupSummary.tsx | 12 +- .../state/orders}/flatOrdersStateNetwork.ts | 2 +- .../src/legacy/state/orders/helpers.tsx | 2 +- .../src/legacy/state/orders/hooks.ts | 13 +- .../orders/middleware/appziMiddleware.test.ts | 5 +- .../orders/middleware/appziMiddleware.ts | 9 +- .../middleware/batchCancelOrdersPopup.ts | 3 +- .../middleware/batchExpireOrdersPopup.ts | 3 +- .../middleware/batchFulfillOrderPopup.tsx | 4 +- .../middleware/batchPresignOrdersPopup.ts | 3 +- .../legacy/state/orders/middleware/index.ts | 1 - .../orders/middleware/pendingOrderPopup.ts | 3 +- .../orders/middleware/popupMiddleware.ts | 4 +- .../orders/middleware/soundMiddleware.test.ts | 6 +- .../orders/middleware/soundMiddleware.ts | 3 +- .../orders/middleware/updateOrderPopup.ts | 5 +- .../src/legacy/state/orders/mocks.ts | 10 +- .../src/legacy/state/orders/priceUtils.ts | 4 +- .../src/legacy/state/orders/reducer.ts | 3 +- .../src/legacy/state/orders/utils.test.ts | 3 +- .../src/legacy/state/orders/utils.ts | 19 +- .../src/legacy/state/price/actions.ts | 3 +- .../src/legacy/state/price/hooks.ts | 17 +- .../src/legacy/state/price/middleware.ts | 7 +- .../src/legacy/state/price/reducer.ts | 9 +- .../legacy => legacy/state/price}/types.ts | 13 +- .../src/legacy/state/profile/hooks.tsx | 4 +- .../src/legacy/state/swap/TradeGp.ts | 14 +- .../src/legacy/state/swap/actions.ts | 5 +- .../src/legacy/state/swap/extension.ts | 4 +- .../src/legacy/state/swap/reducer.ts | 15 +- .../src/legacy/state/swap/trade.test.ts | 4 +- .../src/legacy/state/swap/utils.ts | 8 +- .../types.ts | 5 + .../src/legacy/state/user/hooks.tsx | 24 +- .../src/legacy/state/user/reducer.ts | 10 +- .../src/legacy/theme/baseTheme.tsx | 47 +-- .../src/legacy/theme/components.tsx | 116 +------ .../src/legacy/theme/styled.d.ts | 2 +- .../legacy/utils/constructSameAddressMap.ts | 13 - .../src/legacy/utils/listVersionLabel.ts | 5 - .../src/legacy/utils/price.ts | 8 +- .../src/legacy/utils/priceLegacy.ts | 20 +- .../src/legacy/utils/prices.ts | 11 +- .../src/legacy/utils/trade.ts | 6 +- .../src/lib/hooks/multicall.ts | 9 +- .../src/lib/hooks/useApproval.ts | 7 +- .../src/lib/hooks/useCurrency.ts | 11 +- .../src/lib/hooks/useNativeCurrency.ts | 6 +- .../lib/hooks/useTokenList/fetchTokenList.ts | 5 +- .../src/lib/hooks/useTokenList/filtering.ts | 3 +- apps/cowswap-frontend/src/lib/i18n.tsx | 4 +- .../src/lib/state/multicall.tsx | 22 -- .../lib/utils/contenthashToUri.test.skip.ts | 21 -- apps/cowswap-frontend/src/mocks/orderMock.ts | 2 +- .../src/mocks/tradeStateMock.ts | 4 +- .../containers/AccountDetails/SurplusCard.tsx | 7 +- .../containers/AccountDetails/index.tsx | 44 +-- .../containers/AccountDetails/styled.ts | 11 +- .../account/containers/CopyHelper/index.tsx | 3 +- .../account/containers/OrdersPanel/index.tsx | 6 +- .../containers/SimpleAccountDetails/index.tsx | 4 +- .../Transaction/ActivityDetails.tsx | 5 +- .../containers/Transaction/StatusDetails.tsx | 15 +- .../account/containers/Transaction/index.tsx | 5 +- .../account/containers/Transaction/styled.ts | 8 +- .../hooks/useDisconnectWallet.ts | 0 .../pure/ConnectedAccountBlocked/index.tsx | 6 +- .../containers/AdvancedOrdersWidget/index.tsx | 2 +- .../hooks/useAdvancedOrdersActions.ts | 4 +- .../hooks/useComposableCowContract.ts | 8 +- .../state/advancedOrdersAtom.ts | 3 +- .../state/advancedOrdersSettingsAtom.ts | 2 +- .../src/modules/appData/hooks.ts | 8 +- .../appData/updater/AppDataUpdater.tsx | 5 +- .../src/modules/appData/utils/buildAppData.ts | 3 +- .../src/modules/appData/utils/fullAppData.ts | 2 +- .../application/containers/App/RoutesApp.tsx | 9 +- .../application/containers/App/Updaters.tsx | 42 +-- .../application/containers/App/index.tsx | 8 +- .../containers/PageTitle/index.tsx | 4 +- .../containers/FortuneWidget/index.tsx | 13 +- .../fortune/hooks/useOpenRandomFortune.ts | 4 +- .../modules/fortune/state/fortunesListAtom.ts | 2 +- .../updaters/InjectedWidgetUpdater.ts | 4 +- .../LimitOrdersConfirmModal/index.tsx | 3 +- .../containers/LimitOrdersWarnings/index.tsx | 4 +- .../hooks/useLimitOrdersWidgetActions.ts | 7 +- .../containers/LimitOrdersWidget/index.tsx | 2 +- .../limitOrdersPropsChecker.ts | 4 +- .../containers/RateInput/index.tsx | 10 +- .../containers/RateInput/styled.ts | 3 +- .../limitOrders/hooks/useGetInitialPrice.ts | 7 +- .../hooks/useHandleOrderPlacement.test.ts | 9 +- .../hooks/useIsSafeApprovalBundle.ts | 3 +- .../hooks/useLimitOrdersFormState.ts | 2 +- .../hooks/useSafeBundleFlowContext.ts | 4 +- .../hooks/useSetupLimitOrderAmountsFromUrl.ts | 7 +- .../limitOrders/hooks/useTradeFlowContext.ts | 4 +- .../hooks/useUpdateCurrencyAmount.ts | 4 +- .../pure/DeadlineSelector/index.tsx | 4 +- .../pure/ExecutionPriceTooltip/index.tsx | 3 +- .../limitOrders/pure/InfoBanner/index.tsx | 4 +- .../pure/LimitOrdersDetails/index.cosmos.tsx | 7 +- .../pure/LimitOrdersDetails/index.tsx | 8 +- .../limitOrders/pure/OrderType/index.tsx | 3 +- .../pure/RateImpactIndicator/index.cosmos.tsx | 2 +- .../pure/RateImpactIndicator/index.tsx | 5 +- .../pure/RateImpactWarning/index.cosmos.tsx | 3 +- .../pure/RateImpactWarning/index.tsx | 2 +- .../src/modules/limitOrders/services/types.ts | 2 +- .../state/limitOrdersRawStateAtom.ts | 3 +- .../state/limitOrdersSettingsAtom.ts | 3 +- .../limitOrders/state/limitRateAtom.ts | 3 +- .../updaters/InitialPriceUpdater/index.tsx | 4 +- .../updaters/QuoteObserverUpdater/index.tsx | 3 +- .../utils/calculateLimitOrdersDeadline.ts | 4 +- .../modules/limitOrders/utils/parsePrice.ts | 3 +- .../modules/mainMenu/constants/mainMenu.tsx | 39 +-- .../modules/mainMenu/pure/MenuTree/index.tsx | 7 +- .../operations/bundle/buildApproveTx.ts | 2 +- .../operations/bundle/buildPresignTx.ts | 2 +- .../modules/operations/bundle/buildWrapTx.ts | 2 +- .../orders/hooks/useSWROrdersRequest.ts | 5 +- .../modules/orders/hooks/useSWRProdOrders.ts | 8 +- .../orders/hooks/useTokensForOrdersList.ts | 2 +- .../MultipleCancellationMenu/index.tsx | 4 +- .../containers/OrdersReceiptModal/index.tsx | 5 +- .../containers/OrdersTableWidget/index.tsx | 8 +- .../OrderRow/EstimatedExecutionPrice.tsx | 9 +- .../OrdersTableContainer/OrderRow/index.tsx | 15 +- .../pure/OrdersTableContainer/OrdersTable.tsx | 2 +- .../OrdersTableContainer/index.cosmos.tsx | 1 + .../pure/OrdersTableContainer/index.tsx | 19 +- .../pure/OrdersTableContainer/orders.mock.ts | 4 +- .../utils/getOrderParams.ts | 2 +- .../pure/ReceiptModal/CurrencyField.tsx | 2 +- .../pure/ReceiptModal/DateField.tsx | 4 +- .../pure/ReceiptModal/FeeField.tsx | 2 +- .../pure/ReceiptModal/FilledField.tsx | 3 +- .../ordersTable/pure/ReceiptModal/IdField.tsx | 5 +- .../pure/ReceiptModal/PriceField.tsx | 4 +- .../pure/ReceiptModal/SurplusField.tsx | 2 +- .../pure/ReceiptModal/fields/SafeTxFields.tsx | 3 +- .../ordersTable/pure/ReceiptModal/index.tsx | 6 +- .../ordersTable/pure/ReceiptModal/styled.ts | 4 +- .../hooks/useAccountAgnosticPermitHookData.ts | 2 +- .../permit/hooks/useIsTokenPermittable.ts | 3 +- .../permit/utils/checkIsTokenPermittable.ts | 3 +- .../permit/utils/generatePermitHook.ts | 3 +- .../EthFlow/hooks/useEthFlowActions.ts | 9 +- .../hooks/useRemainingNativeTxsAndCosts.ts | 5 +- .../EthFlow/hooks/useSetupEthFlow.ts | 3 +- .../modules/swap/containers/EthFlow/index.tsx | 2 +- .../swap/containers/EthFlowStepper/index.tsx | 5 +- .../swap/containers/FeesDiscount/index.tsx | 5 +- .../swap/containers/Row/RowFee/index.tsx | 6 +- .../Row/RowReceivedAfterSlippage/index.tsx | 2 +- .../swap/containers/Row/RowSlippage/index.tsx | 2 +- .../swap/containers/SetRecipient/index.tsx | 3 +- .../containers/SurplusModalSetup/index.tsx | 4 +- .../swap/containers/SwapModals/index.tsx | 4 +- .../swap/containers/SwapWidget/index.tsx | 23 +- .../containers/SwapWidget/propsChecker.ts | 5 +- .../swap/containers/SwapWidget/types.ts | 3 +- .../containers/TradeBasicDetails/index.tsx | 2 +- .../swap/containers/TradeSummary/index.tsx | 2 +- .../swap/helpers/tradeReceiveAmount.test.ts | 2 +- .../swap/helpers/tradeReceiveAmount.tsx | 3 +- .../hooks/useBaseSafeBundleFlowContext.ts | 5 +- .../swap/hooks/useCheckEthFlowOrderExists.ts | 4 +- .../modules/swap/hooks/useEthFlowContext.ts | 4 +- .../src/modules/swap/hooks/useFlowContext.ts | 17 +- .../modules/swap/hooks/useHandleSwap.test.tsx | 8 +- .../src/modules/swap/hooks/useHandleSwap.ts | 4 +- .../src/modules/swap/hooks/useIsEoaEthFlow.ts | 4 +- .../modules/swap/hooks/useIsSafeEthFlow.ts | 2 +- .../hooks/useSafeBundleApprovalFlowContext.ts | 2 +- .../swap/hooks/useSafeBundleEthFlowContext.ts | 2 +- .../swap/hooks/useSetupSwapAmountsFromUrl.ts | 7 +- .../swap/hooks/useSwapButtonContext.ts | 13 +- .../swap/hooks/useSwapCurrenciesAmounts.ts | 7 +- .../modules/swap/hooks/useSwapFlowContext.ts | 5 +- .../src/modules/swap/hooks/useSwapRawState.ts | 3 +- .../src/modules/swap/hooks/useSwapSlippage.ts | 2 +- .../swap/hooks/useSwapState.test.ts} | 6 +- .../swap/hooks/useSwapState.tsx} | 21 +- .../swap/hooks/useTradePricesUpdate.ts | 19 +- .../EthFlow/EthFlowBanner/index.cosmos.tsx | 3 +- .../swap/pure/EthFlow/EthFlowBanner/index.tsx | 7 +- .../pure/EthFlow/EthFlowBanner/styleds.ts | 4 +- .../EthFlowModalContent/ActionButton.tsx | 5 +- .../EthFlow/EthFlowStepper/steps/Step1.tsx | 8 +- .../EthFlow/EthFlowStepper/steps/Step2.tsx | 8 +- .../EthFlow/EthFlowStepper/steps/Step3.tsx | 10 +- .../WrappingPreview/WrapCard.cosmos.tsx | 3 +- .../pure/EthFlow/WrappingPreview/WrapCard.tsx | 5 +- .../swap/pure/ReceiveAmountInfo/index.tsx | 3 +- .../pure/Row/RowDeadline/index.cosmos.tsx | 2 +- .../swap/pure/Row/RowDeadline/index.tsx | 8 +- .../pure/Row/RowFeeContent/index.cosmos.tsx | 2 +- .../swap/pure/Row/RowFeeContent/index.tsx | 4 +- .../index.cosmos.tsx | 2 +- .../RowReceivedAfterSlippageContent/index.tsx | 9 +- .../pure/Row/RowSlippageContent/index.tsx | 8 +- .../src/modules/swap/pure/Row/styled.ts | 6 +- .../modules/swap/pure/SwapButton/index.tsx | 3 +- .../swap/pure/SwapButtons/index.cosmos.tsx | 4 +- .../modules/swap/pure/SwapButtons/index.tsx | 11 +- .../modules/swap/pure/SwapButtons/styled.tsx | 6 +- .../swap/pure/TradeRates/index.cosmos.tsx | 2 +- .../modules/swap/pure/TradeRates/index.tsx | 2 +- .../swap/pure/TradeSummary/index.cosmos.tsx | 2 +- .../src/modules/swap/pure/styled.tsx | 4 +- .../src/modules/swap/pure/warnings.tsx | 2 +- .../modules/swap/services/ethFlow/mocks.ts | 3 +- .../ethFlow/steps/calculateUniqueOrderId.ts | 7 +- .../ethFlow/steps/signEthFlowOrderStep.ts | 4 +- .../services/ethFlow/transactionsMocks.ts | 22 +- .../safeBundleFlow/safeBundleEthFlow.ts | 2 +- .../swapFlow/steps/presignOrderStep.ts | 5 +- .../src/modules/swap/services/types.ts | 3 +- .../updaters/EthFlowDeadlineUpdater.tsx | 6 +- .../updaters/EthFlowSlippageUpdater.tsx | 5 +- .../modules/swap/state/useSwapDerivedState.ts | 5 +- .../tokens/hooks/useCurrencyBalance.ts | 9 +- .../modules/tokens/hooks/useEnoughBalance.ts | 3 +- .../tokens/hooks/useOnchainBalances.ts | 5 +- .../tokensList/utils/getTokensByAddress.ts | 6 +- .../TradeConfirmPendingContent.tsx | 4 +- .../TradeConfirmModal/index.cosmos.tsx | 3 +- .../containers/TradeConfirmModal/index.tsx | 2 +- .../TradeWidget/TradeWidgetModals.tsx | 2 +- .../trade/containers/TradeWidget/index.tsx | 5 +- .../containers/WrapNativeModal/index.tsx | 5 +- .../useResetStateWithSymbolDuplication.ts | 4 +- .../setupTradeState/useSetupTradeState.ts | 6 +- .../trade/hooks/useBuildTradeDerivedState.ts | 5 +- .../hooks/useDisableNativeTokenSelling.ts | 7 +- .../modules/trade/hooks/useIsNativeInOrOut.ts | 5 +- .../modules/trade/hooks/useIsWrapOrUnwrap.ts | 6 +- .../trade/hooks/useIsWrappedInOrOut.ts | 9 +- .../hooks/useNavigateOnCurrencySelection.ts | 4 +- .../trade/hooks/useOnCurrencySelection.ts | 4 +- .../trade/hooks/useSwitchTokensPlaces.ts | 8 +- .../trade/hooks/useUpdateCurrencyAmount.ts | 6 +- .../modules/trade/hooks/useWrapNativeFlow.ts | 5 +- .../pure/CompatibilityIssuesWarning/index.tsx | 3 +- .../trade/pure/ConfirmDetailsItem/index.tsx | 3 +- .../pure/ReviewOrderModalAmountRow/index.tsx | 4 +- .../trade/pure/TradeConfirmation/index.tsx | 4 +- .../trade/pure/TradeNumberInput/index.tsx | 4 +- .../trade/pure/TradeWidgetField/index.tsx | 3 +- .../trade/pure/UnlockWidgetScreen/index.tsx | 8 +- .../src/modules/trade/types/TradeRawState.ts | 3 +- .../updaters/RecipientAddressUpdater.tsx | 2 +- .../src/modules/trade/utils/analytics.ts | 4 +- .../modules/trade/utils/swapErrorHelper.ts | 2 +- .../hooks/useGetTradeFormValidation.ts | 2 +- .../hooks/useTradeFormButtonContext.ts | 3 +- .../hooks/useTradeFormValidationContext.ts | 5 +- .../pure/TradeFormButtons/tradeButtonsMap.tsx | 3 +- .../services/validateTradeForm.ts | 6 +- .../hooks/useProcessUnsupportedTokenError.ts | 6 +- .../tradeQuote/hooks/useQuoteParams.ts | 8 +- .../hooks/useTradeQuotePolling.test.tsx | 11 +- .../tradeQuote/hooks/useTradeQuotePolling.ts | 4 +- .../src/modules/twap/const.ts | 3 +- .../twap/containers/ActionButtons/index.tsx | 2 +- .../TwapConfirmModal/TwapConfirmDetails.tsx | 6 +- .../containers/TwapFormWarnings/index.tsx | 4 +- .../warnings/FallbackHandlerWarning.tsx | 4 +- .../warnings/SmallPartVolumeWarning.tsx | 2 +- .../warnings/SwapPriceDifferenceWarning.tsx | 3 +- .../warnings/UnsupportedWalletWarning.tsx | 2 +- .../twap/containers/TwapFormWidget/index.tsx | 9 +- .../containers/TwapFormWidget/tooltips.tsx | 4 +- .../twap/hooks/useAllEmulatedOrders.ts | 3 +- .../modules/twap/hooks/useCancelTwapOrder.ts | 5 +- .../modules/twap/hooks/useCreateTwapOrder.ts | 11 +- .../twap/hooks/useEmulatedPartOrders.ts | 3 +- .../twap/hooks/useEmulatedTwapOrders.ts | 5 +- .../hooks/useExtensibleFallbackContext.ts | 8 +- .../hooks/useFallbackHandlerVerification.ts | 2 +- .../twap/hooks/useFetchTwapOrdersFromSafe.ts | 4 +- .../twap/hooks/useSetupTwapAmountsFromUrls.ts | 6 +- .../modules/twap/hooks/useTwapFormState.ts | 2 +- .../twap/hooks/useTwapOrderCreationContext.ts | 7 +- .../twap/hooks/useTwapOrdersAuthMulticall.ts | 2 +- .../twap/hooks/useTwapOrdersExecutions.ts | 4 +- .../hooks/useTwapOrdersTradeableMulticall.ts | 2 +- .../twap/hooks/useTwapWarningsContext.ts | 3 +- .../modules/twap/pure/AmountParts/index.tsx | 2 +- .../modules/twap/pure/AmountParts/styled.tsx | 5 +- .../pure/CustomDeadlineSelector/index.tsx | 4 +- .../pure/CustomDeadlineSelector/styled.tsx | 4 +- .../twap/pure/DeadlineSelector/index.tsx | 4 +- .../getTwapFormState.test.ts | 5 +- .../PrimaryActionButton/getTwapFormState.tsx | 3 +- .../twap/pure/PrimaryActionButton/index.tsx | 3 +- .../twap/services/cancelTwapOrderTxs.ts | 2 +- .../twap/services/createTwapOrderTxs.test.ts | 5 +- .../twap/services/fetchTwapOrdersFromSafe.ts | 5 +- .../services/getSignatureVerifierContract.ts | 2 +- .../state}/composableOrdersPopupMiddleware.ts | 20 +- .../state/fallbackHandlerVerificationAtom.ts | 2 +- .../twap/state/swapAmountDifferenceAtom.ts | 3 +- .../src/modules/twap/state/twapOrderAtom.ts | 2 +- .../modules/twap/state/twapOrdersListAtom.ts | 12 +- .../twap/state/twapOrdersSettingsAtom.ts | 2 +- .../modules/twap/state/twapPartOrdersAtom.ts | 9 +- .../CreatedInOrderBookOrdersUpdater.tsx | 2 +- .../FallbackHandlerVerificationUpdater.tsx | 4 +- .../twap/updaters/FullAmountQuoteUpdater.tsx | 3 +- .../twap/updaters/PartOrdersUpdater.tsx | 6 +- .../twap/updaters/QuoteObserverUpdater.tsx | 4 +- .../twap/updaters/TwapOrdersUpdater.tsx | 5 +- .../src/modules/twap/updaters/index.tsx | 3 +- .../twap/utils/mapPartOrderToStoreOrder.ts | 3 +- .../twap/utils/mapTwapOrderToStoreOrder.ts | 3 +- .../modules/twap/utils/twapOrderToStruct.ts | 2 +- .../twap/utils/updateTwapOrdersList.ts | 2 +- .../usdAmount/apis/getCoingeckoUsdPrice.ts | 2 +- .../usdAmount/apis/getCowProtocolUsdPrice.ts | 6 +- .../usdAmount/hooks/useTradeUsdAmounts.ts | 3 +- .../usdAmount/hooks/useUsdAmount.test.tsx | 3 +- .../modules/usdAmount/hooks/useUsdAmount.ts | 2 +- .../usdAmount/state/usdRawPricesAtom.ts | 3 +- .../usdAmount/state/usdTokenPricesAtom.ts | 6 +- .../updaters/UsdPricesUpdater.test.tsx | 3 +- .../usdAmount/updaters/UsdPricesUpdater.ts | 11 +- .../modules/wallet/api/assets/formatic.png | Bin 2047 -> 0 bytes .../wallet/api/pure/ZengoBanner/index.tsx | 41 --- .../wallet/api/pure/ZengoBanner/styled.ts | 72 ----- .../containers/AccountSelectorModal/index.tsx | 17 +- .../containers/AccountSelectorModal/state.ts | 0 .../AccountSelectorModal/styled.tsx | 4 +- .../containers/AddToMetamask/index.tsx | 28 +- .../containers/ConnectWalletOptions.tsx | 98 ++++++ .../FollowPendingTxPopupUI.tsx | 3 +- .../FollowPendingTxPopup/index.tsx | 19 +- .../containers/WalletModal/index.tsx | 21 +- .../containers/Web3Status/index.tsx | 21 +- .../src/modules/wallet/index.ts | 20 -- .../{api => }/pure/AddToMetamask/index.tsx | 16 +- .../{api => }/pure/PendingView/index.tsx | 4 +- .../{api => }/pure/StatusIcon/index.tsx | 14 +- .../{api => }/pure/WalletModal/index.tsx | 8 +- .../{api => }/pure/WalletModal/styled.tsx | 6 +- .../{api => }/pure/Web3StatusInner/index.tsx | 15 +- .../{api => }/pure/Web3StatusInner/styled.ts | 6 +- .../wallet/state/followPendingTxPopupAtom.ts} | 2 +- .../wallet/utils/PermitProviderConnector.ts | 3 +- .../wallet/web3-react/connection/formatic.tsx | 50 --- .../wallet/web3-react/connection/index.tsx | 174 ----------- .../src/pages/About/index.tsx | 12 +- .../src/pages/Account/Balances.tsx | 29 +- .../src/pages/Account/Governance.tsx | 2 +- .../pages/Account/LockedGnoVesting/hooks.ts | 27 +- .../pages/Account/LockedGnoVesting/index.tsx | 35 ++- .../src/pages/Account/Menu.tsx | 3 +- .../pages/Account/Tokens/TokensOverview.tsx | 13 +- .../src/pages/Account/styled.tsx | 289 ++++-------------- .../src/pages/Claim/CanUserClaimMessage.tsx | 14 +- .../src/pages/Claim/ClaimAddress.tsx | 9 +- .../src/pages/Claim/ClaimBanner.tsx | 8 +- .../src/pages/Claim/ClaimNav.tsx | 10 +- .../src/pages/Claim/ClaimSummary.tsx | 9 +- .../src/pages/Claim/ClaimingStatus.tsx | 22 +- .../pages/Claim/ClaimsOnOtherChainsBanner.tsx | 3 +- .../src/pages/Claim/ClaimsTable.tsx | 21 +- .../src/pages/Claim/FooterNavButtons.tsx | 8 +- .../Claim/InvestmentFlow/InvestOption.tsx | 35 +-- .../Claim/InvestmentFlow/InvestSummaryRow.tsx | 11 +- .../src/pages/Claim/InvestmentFlow/index.tsx | 16 +- .../cowswap-frontend/src/pages/Claim/const.ts | 2 +- .../src/pages/Claim/index.tsx | 22 +- .../src/pages/Claim/styled.ts | 17 +- .../src/pages/Faq/AffiliateFaq.tsx | 3 +- apps/cowswap-frontend/src/pages/Faq/Menu.tsx | 3 +- apps/cowswap-frontend/src/pages/Faq/index.tsx | 11 +- .../cowswap-frontend/src/pages/Faq/styled.tsx | 6 +- .../src/pages/KitchenSink/index.tsx | 40 --- .../src/pages/LimitOrders/index.tsx | 2 +- .../cowswap-frontend/src/pages/Swap/index.tsx | 6 +- .../error/AnySwapAffectedUsers/index.tsx | 8 +- .../useIsAnySwapAffectedUser.ts | 10 +- .../src/pages/error/NotFound/index.tsx | 6 +- .../src/pages/games/CowRunner/index.tsx | 3 +- .../src/pages/games/MevSlicer/index.tsx | 8 +- apps/cowswap-frontend/src/react-app-env.d.ts | 2 - apps/cowswap-frontend/src/test-utils.tsx | 6 +- apps/cowswap-frontend/src/types/index.ts | 2 +- .../orderUtils/calculateAmountForRate.ts | 22 +- .../calculateExecutionPrice.test.ts | 6 +- .../orderUtils/calculateExecutionPrice.ts | 3 +- ...alculatePercentageInRelationToReference.ts | 3 +- .../calculatePriceDifference.test.ts | 12 +- .../orderUtils/calculatePriceDifference.ts | 20 +- .../utils/orderUtils/getOrderFilledAmount.ts | 3 +- .../src/utils/orderUtils/getOrderSurplus.ts | 3 +- .../utils/orderUtils/getTokenFromMapping.ts | 6 +- apps/cowswap-frontend/tsconfig.json | 20 +- apps/cowswap-frontend/vite.config.ts | 16 +- jest.preset.js | 10 +- libs/analytics/.babelrc | 20 ++ libs/analytics/.eslintrc.json | 21 ++ libs/analytics/README.md | 1 + libs/analytics/jest.config.ts | 11 + libs/analytics/package.json | 12 + libs/analytics/project.json | 46 +++ .../analytics/src}/events/cowFortune.ts | 0 .../analytics/src}/events/listEvents.ts | 0 .../analytics/src}/events/otherEvents.ts | 2 +- .../analytics/src}/events/settingsEvents.ts | 2 +- .../analytics/src}/events/swapEvents.ts | 9 +- .../analytics/src}/events/themeEvents.ts | 0 .../src}/events/transactionEvents.ts | 0 .../analytics/src}/events/twapEvents.ts | 0 .../analytics/src}/events/walletEvents.ts | 0 .../analytics/src}/googleAnalytics.ts | 0 .../analytics => libs/analytics/src}/index.ts | 10 +- libs/analytics/src/pixel/constants.ts | 3 + .../analytics/src}/pixel/facebook.ts | 0 .../analytics/src}/pixel/index.ts | 0 .../analytics/src}/pixel/linkedin.ts | 0 .../analytics/src}/pixel/microsoft.ts | 0 .../analytics/src}/pixel/paved.ts | 0 .../analytics/src}/pixel/reddit.ts | 0 .../analytics/src}/pixel/sendAllPixels.ts | 0 .../analytics/src}/pixel/twitter.ts | 0 .../analytics/src}/pixel/types.ts | 0 .../analytics/src}/pixel/utils.ts | 0 .../analytics/src}/provider/index.ts | 4 +- .../analytics => libs/analytics/src}/types.ts | 0 libs/analytics/tsconfig.json | 21 ++ libs/analytics/tsconfig.lib.json | 19 ++ libs/analytics/tsconfig.spec.json | 20 ++ libs/analytics/vite.config.ts | 49 +++ libs/assets/.babelrc | 20 ++ libs/assets/.eslintrc.json | 18 ++ libs/assets/README.md | 1 + libs/assets/jest.config.ts | 11 + libs/assets/package.json | 12 + libs/assets/project.json | 46 +++ .../assets/src}/cow-swap/CowError.png | Bin .../assets/src}/cow-swap/alert-circle.svg | 0 .../assets/src}/cow-swap/alert.svg | 0 .../assets/src}/cow-swap/ammslogo/0x.png | Bin .../assets/src}/cow-swap/ammslogo/1inch.png | Bin .../assets/src}/cow-swap/ammslogo/baoswap.png | Bin .../assets/src}/cow-swap/ammslogo/curve.png | Bin .../assets/src}/cow-swap/ammslogo/elk.png | Bin .../src}/cow-swap/ammslogo/honeyswap.png | Bin .../src}/cow-swap/ammslogo/levinswap.png | Bin .../assets/src}/cow-swap/ammslogo/matcha.png | Bin .../src}/cow-swap/ammslogo/paraswap.png | Bin .../assets/src}/cow-swap/ammslogo/sushi.png | Bin .../assets/src}/cow-swap/ammslogo/swapr.png | Bin .../src}/cow-swap/ammslogo/symmetric.png | Bin .../assets/src}/cow-swap/ammslogo/uniswap.png | Bin .../src}/cow-swap/anniversary-icons.png | Bin .../assets/src}/cow-swap/arrow.svg | 0 .../assets/src}/cow-swap/arrowDownRight.svg | 0 .../assets/src}/cow-swap/attention.svg | 0 .../assets/src}/cow-swap/carret-down.svg | 0 .../assets/src}/cow-swap/check-singular.svg | 0 .../assets/src}/cow-swap/check.svg | 0 .../assets/src}/cow-swap/checkmark.svg | 0 .../assets/src}/cow-swap/code.svg | 0 .../assets/src}/cow-swap/cookie-policy.svg | 0 .../assets/src}/cow-swap/cow-404.png | Bin .../assets/src}/cow-swap/cow-load.gif | Bin .../assets/src}/cow-swap/cow-load.webp | Bin .../src}/cow-swap/cow-no-connection.png | Bin .../assets/src}/cow-swap/cow.svg | 0 .../assets/src}/cow-swap/cow_v2.svg | 0 .../assets/src}/cow-swap/cowprotocol.svg | 0 .../assets/src}/cow-swap/cowswap-diagram.png | Bin .../assets/src}/cow-swap/cowswap-logo.svg | 0 .../assets/src}/cow-swap/cursor1.gif | Bin .../assets/src}/cow-swap/cursor2.gif | Bin .../assets/src}/cow-swap/cursor3.gif | Bin .../assets/src}/cow-swap/cursor4.gif | Bin .../assets/src}/cow-swap/discord.svg | 0 .../assets/src}/cow-swap/doc.svg | 0 .../assets/src}/cow-swap/etherscan-icon.svg | 0 .../assets/src}/cow-swap/exclamation.svg | 0 .../assets/src}/cow-swap/experiment.svg | 0 .../assets/src}/cow-swap/feedback.svg | 0 .../assets/src}/cow-swap/finish.svg | 0 .../assets/src}/cow-swap/fortune-cookie.png | Bin .../assets/src}/cow-swap/game.gif | Bin .../assets/src}/cow-swap/gasless.png | Bin .../assets/src}/cow-swap/gno.png | Bin .../assets/src}/cow-swap/halloween-bats.svg | 0 .../assets/src}/cow-swap/halloween-spider.svg | 0 .../assets/src}/cow-swap/important.svg | 0 .../assets/src}/cow-swap/info.svg | 0 .../assets/src}/cow-swap/loading.svg | 0 .../src}/cow-swap/meditating-cow-v2.svg | 0 .../assets/src}/cow-swap/menu.svg | 0 .../assets/src}/cow-swap/mev.png | Bin .../assets/src}/cow-swap/moon.svg | 0 .../cow-swap/network-gnosis-chain-logo.svg | 0 .../src}/cow-swap/network-goerli-logo.svg | 0 .../src}/cow-swap/network-mainnet-logo.svg | 0 .../src}/cow-swap/network-rinkeby-logo.svg | 0 .../assets/src}/cow-swap/ninja-cow.png | Bin .../assets/src}/cow-swap/order-cancelled.svg | 0 .../assets/src}/cow-swap/order-check.svg | 0 .../assets/src}/cow-swap/order-cross.svg | 0 .../assets/src}/cow-swap/order-expired.svg | 0 .../assets/src}/cow-swap/order-open.svg | 0 .../cow-swap/order-presignature-pending.svg | 0 .../assets/src}/cow-swap/orderExecution.svg | 0 .../assets/src}/cow-swap/pie.svg | 0 .../assets/src}/cow-swap/plus.svg | 0 .../assets/src}/cow-swap/privacy-policy.svg | 0 .../assets/src}/cow-swap/protection.svg | 0 .../assets/src}/cow-swap/question.ts | 0 .../assets/src}/cow-swap/refund.svg | 0 .../assets/src}/cow-swap/round-arrow.svg | 0 .../assets/src/cow-swap}/safe-logo.svg | 0 .../assets/src}/cow-swap/savings.svg | 0 .../assets/src}/cow-swap/send.svg | 0 .../assets/src}/cow-swap/sun.svg | 0 .../assets/src}/cow-swap/surplus-cow.svg | 0 .../src}/cow-swap/terms-and-conditions.svg | 0 .../src}/cow-swap/transaction-arrows.svg | 0 .../src}/cow-swap/transaction-confirmed.svg | 0 .../assets/src}/cow-swap/twitter.svg | 0 .../assets/src}/cow-swap/usdc.png | Bin .../assets/src}/cow-swap/vCOW.png | Bin .../assets/src}/cow-swap/wallet-plus.svg | 0 .../assets/src}/cow-swap/wxdai.png | Bin .../assets => libs/assets/src}/cow-swap/x.svg | 0 .../assets/src}/cow-swap/xdai.png | Bin .../assets/src}/images/amms-graph-gc.svg | 0 .../assets/src}/images/amms-graph.svg | 0 .../assets/src}/images/arrow-down-blue.svg | 0 .../assets/src}/images/arrow-down-grey.svg | 0 .../assets/src}/images/big_unicorn.png | Bin .../assets/src}/images/blue-loader.svg | 0 .../assets/src}/images/circle-grey.svg | 0 .../assets/src}/images/circle.svg | 0 .../assets/src}/images/cow-graph.svg | 0 .../src}/images/cow-meditating-smoooth.svg | 0 .../assets/src}/images/cow-meditating.svg | 0 .../assets/src}/images/dropdown-blue.svg | 0 .../assets/src}/images/dropdown.svg | 0 .../assets/src}/images/dropup-blue.svg | 0 .../assets/src}/images/ethereum-logo.png | Bin .../assets/src}/images/gas-icon.svg | 0 .../assets/src}/images/link.svg | 0 .../assets/src}/images/magnifying-glass.svg | 0 .../assets/src}/images/menu.svg | 0 .../assets/src}/images/noise.png | Bin .../assets/src}/images/plus-blue.svg | 0 .../assets/src}/images/plus-grey.svg | 0 .../assets/src}/images/portisIcon.png | Bin .../assets/src}/images/question-mark.svg | 0 .../assets/src}/images/question.svg | 0 .../assets/src}/images/router-icon-grey.svg | 0 .../assets/src}/images/sandtexture.webp | Bin .../assets/src}/images/santa-hat.png | Bin .../assets/src}/images/spinner.svg | 0 .../assets/src}/images/squiggle.png | Bin .../assets/src}/images/survey-orb.svg | 0 .../assets/src}/images/token-list-logo.png | Bin .../src}/images/token-list/lists-dark.png | Bin .../src}/images/token-list/lists-light.png | Bin .../assets/src}/images/token-logo.png | Bin .../assets/src}/images/tokenlistsgrouped.png | Bin .../assets/src}/images/trustWallet.png | Bin .../assets/src}/images/ukraine.png | Bin .../assets/src}/images/widget-screenshot.png | Bin .../assets => libs/assets/src}/images/x.svg | 0 .../assets/src}/images/xl_uni.png | Bin libs/assets/src/index.ts | 0 .../assets/src}/styles/styled.ts | 4 +- .../assets => libs/assets/src}/svg/QR.svg | 0 .../assets/src}/svg/arbitrum_logo.svg | 0 .../assets/src}/svg/celo_logo.svg | 0 .../assets/src}/svg/dot_line.svg | 0 .../assets/src}/svg/lightcircle.svg | 0 .../assets => libs/assets/src}/svg/logo.svg | 1 + .../assets/src}/svg/logo_pink.svg | 0 .../assets/src}/svg/matic-token-icon.svg | 0 .../assets/src}/svg/optimism_logo.svg | 0 .../assets/src}/svg/optimistic_ethereum.svg | 0 .../assets/src}/svg/polygon-matic-logo.svg | 0 .../assets/src}/svg/question.svg | 0 .../assets/src}/svg/static_route.svg | 0 .../assets => libs/assets/src}/svg/switch.svg | 0 .../assets/src}/svg/tokenlist.svg | 0 .../assets/src}/svg/wordmark.svg | 0 .../assets/src}/svg/wordmark_pink.svg | 0 .../assets/src}/svg/wordmark_white.svg | 0 libs/assets/tsconfig.json | 21 ++ libs/assets/tsconfig.lib.json | 19 ++ libs/assets/tsconfig.spec.json | 20 ++ libs/assets/vite.config.ts | 49 +++ libs/common-const/.babelrc | 20 ++ libs/common-const/.eslintrc.json | 18 ++ libs/common-const/README.md | 1 + libs/common-const/jest.config.ts | 11 + libs/common-const/package.json | 12 + libs/common-const/project.json | 46 +++ .../common-const/src}/addresses.ts | 14 +- .../common-const/src}/chainInfo.ts | 6 +- .../common-const/src/common.ts | 8 +- .../src}/gnosis_chain/constants.ts | 0 .../common-const/src}/gnosis_chain/hack.ts | 13 +- .../common-const/src}/goerli/constants.ts | 0 libs/common-const/src/index.ts | 14 + .../common-const/src}/intl.ts | 0 .../common-const/src}/ipfs.ts | 0 .../common-const/src}/lists.ts | 2 +- .../common-const/src}/locales.ts | 0 .../common-const/src}/misc.ts | 0 .../common-const/src}/networks.ts | 0 .../common-const/src}/routing.ts | 7 +- .../src}/tokenLists/broken.tokenlist.json | 0 .../tokenLists/unsupported.tokenlist.json | 0 .../common-const/src}/tokens.ts | 17 +- libs/common-const/tsconfig.json | 21 ++ libs/common-const/tsconfig.lib.json | 19 ++ libs/common-const/tsconfig.spec.json | 20 ++ libs/common-const/vite.config.ts | 49 +++ libs/common-hooks/.babelrc | 20 ++ libs/common-hooks/.eslintrc.json | 21 ++ libs/common-hooks/README.md | 1 + libs/common-hooks/jest.config.ts | 11 + libs/common-hooks/package.json | 12 + libs/common-hooks/project.json | 46 +++ libs/common-hooks/src/index.ts | 24 ++ .../common-hooks/src}/useBlockNumber.tsx | 5 +- .../common-hooks/src/useColor/index.ts | 3 +- .../common-hooks/src}/useContract.ts | 31 +- .../common-hooks/src}/useCopyClipboard.ts | 2 +- .../common-hooks/src}/useDebounce.ts | 2 +- .../src}/useDebouncedChangeHandler.tsx | 2 +- .../common-hooks/src}/useFetchFile.ts | 2 +- .../common-hooks/src}/useFilterTokens.ts | 4 +- .../common-hooks/src}/useGetReceipt.ts | 15 +- .../common-hooks/src}/useInterval.ts | 2 +- .../common-hooks/src}/useIsMounted.ts | 2 +- .../common-hooks/src}/useIsOnline.ts | 4 +- .../common-hooks/src}/useIsWindowVisible.ts | 2 +- .../common-hooks/src}/useLast.ts | 2 +- .../src}/useLoadingWithTimeout.ts | 2 +- .../common-hooks/src}/useMachineTime.ts | 7 +- libs/common-hooks/src/useNetworkName.ts | 13 + .../common-hooks/src}/useOnClickOutside.tsx | 0 .../common-hooks/src}/useParsedQueryString.ts | 2 +- .../common-hooks/src}/usePrevious.ts | 2 +- libs/common-hooks/src/useTheme.ts | 7 + .../common-hooks/src}/useTimeAgo.ts | 2 +- .../common-hooks/src}/useToggle.ts | 2 +- .../common-hooks/src}/useWindowSize.ts | 0 libs/common-hooks/tsconfig.json | 21 ++ libs/common-hooks/tsconfig.lib.json | 19 ++ libs/common-hooks/tsconfig.spec.json | 20 ++ libs/common-hooks/vite.config.ts | 49 +++ libs/common-utils/.babelrc | 20 ++ libs/common-utils/.env | 96 ++++++ libs/common-utils/.eslintrc.json | 21 ++ libs/common-utils/README.md | 42 +++ libs/common-utils/jest.config.ts | 11 + libs/common-utils/package.json | 12 + libs/common-utils/project.json | 46 +++ .../common-utils/src}/amountFormat/README.md | 0 .../src}/amountFormat/index.test.ts | 3 +- .../common-utils/src}/amountFormat/index.ts | 18 +- .../common-utils/src}/amountFormat/utils.ts | 4 +- .../common-utils/src}/anonymizeLink.test.ts | 0 .../common-utils/src}/anonymizeLink.ts | 0 .../utils => libs/common-utils/src}/appzi.ts | 5 +- .../common-utils/src}/areFractionsEqual.ts | 0 .../utils => libs/common-utils/src}/async.ts | 0 .../utils => libs/common-utils/src}/blocks.ts | 0 .../src}/buildPriceFromCurrencyAmounts.ts | 5 +- .../src}/calculateGasMargin.test.ts | 0 .../common-utils/src}/calculateGasMargin.ts | 0 .../src}/calculatePriceImpact.test.ts | 0 .../src}/calculateSlippageAmount.test.ts | 0 .../src}/calculateSlippageAmount.ts | 4 +- .../common-utils/src}/contenthashToUri.ts | 2 +- .../src}/currencyAmountToTokenAmount.ts | 6 +- .../common-utils/src}/currencyId.ts | 0 .../common-utils/src}/deepEqual.ts | 0 .../src}/deterministicHash.test.ts | 0 .../common-utils/src}/deterministicHash.ts | 0 .../common-utils/src}/displayTime.tsx | 0 .../src}/doesTokenMatchSymbolOrAddress.ts | 0 .../utils => libs/common-utils/src}/env.ts | 0 .../common-utils/src}/environments.test.ts | 0 .../common-utils/src}/environments.ts | 0 .../common-utils/src}/explorer.ts | 6 +- .../common-utils/src}/featureFlags.ts | 3 +- .../utils => libs/common-utils/src}/format.ts | 0 .../common-utils/src}/formatCurrencyAmount.ts | 4 +- .../src}/formatLocaleNumber.test.ts | 4 +- .../common-utils/src}/formatLocaleNumber.ts | 2 +- .../common-utils/src}/fractionUtils.test.ts | 0 .../common-utils/src}/fractionUtils.ts | 31 +- .../src}/genericPropsChecker.test.ts | 0 .../common-utils/src}/genericPropsChecker.ts | 0 .../common-utils/src}/getAddress.ts | 4 +- .../src}/getCurrentChainIdFromUrl.test.ts | 0 .../src}/getCurrentChainIdFromUrl.ts | 0 .../src}/getDoesMessageIncludeToken.ts | 0 .../common-utils/src}/getExplorerLink.test.ts | 0 .../common-utils/src}/getExplorerLink.ts | 0 .../common-utils/src}/getIntOrFloat.ts | 0 .../common-utils/src}/getIsNativeToken.ts | 2 +- .../common-utils/src}/getIsWrapOrUnwrap.ts | 5 +- .../src}/getQuoteUnsupportedToken.ts | 0 .../common-utils/src}/getRandomInt.ts | 0 .../common-utils/src}/getUserAgent.ts | 0 libs/common-utils/src/index.ts | 54 ++++ .../common-utils/src}/isEnoughAmount.ts | 0 .../common-utils/src}/isFractionFalsy.ts | 0 .../common-utils/src}/isInjectedWidget.ts | 0 .../common-utils/src}/isNotNullish.ts | 2 +- .../utils => libs/common-utils/src}/isZero.ts | 2 +- .../src}/jotai/atomWithPartialUpdate.ts | 3 +- .../src/legacyAddressUtils.test.ts | 5 +- .../common-utils/src/legacyAddressUtils.ts | 19 +- .../common-utils/src}/listSort.ts | 4 +- .../common-utils/src}/localStorage.ts | 0 .../common-utils/src}/logging/index.ts | 5 +- .../common-utils/src}/maxAmountSpend.ts | 0 .../utils => libs/common-utils/src}/misc.ts | 5 +- .../utils => libs/common-utils/src}/node.ts | 0 .../common-utils/src}/parseENSAddress.test.ts | 2 +- .../common-utils/src}/parseENSAddress.ts | 4 +- .../common-utils/src}/rawToTokenAmount.ts | 0 .../common-utils/src}/request.ts | 0 .../src}/resolveENSContentHash.ts | 2 +- .../common-utils/src}/retry.test.ts | 0 .../utils => libs/common-utils/src}/retry.ts | 2 + .../common-utils/src}/safeNamehash.ts | 0 .../utils => libs/common-utils/src}/sound.ts | 0 .../src}/swapErrorToUserReadableMessage.tsx | 0 .../utils => libs/common-utils/src}/time.ts | 0 .../common-utils/src}/toggleBodyClass.ts | 0 .../utils => libs/common-utils/src}/tokens.ts | 7 +- .../common-utils/src}/tooltips.ts | 3 +- .../src}/trimTrailingZeros.test.ts | 0 .../common-utils/src}/trimTrailingZeros.ts | 0 .../src}/tryParseCurrencyAmount.ts | 8 +- .../src}/tryParseFractionalAmount.ts | 3 +- libs/common-utils/src/types.ts | 25 ++ .../common-utils/src}/uriToHttp.test.ts | 2 +- .../common-utils/src}/uriToHttp.ts | 5 +- .../common-utils/src}/userAgent.ts | 0 libs/common-utils/tsconfig.json | 21 ++ libs/common-utils/tsconfig.lib.json | 19 ++ libs/common-utils/tsconfig.spec.json | 20 ++ libs/common-utils/vite.config.ts | 56 ++++ libs/core/.babelrc | 20 ++ libs/core/.eslintrc.json | 18 ++ libs/core/README.md | 1 + libs/core/jest.config.ts | 11 + libs/core/package.json | 12 + libs/core/project.json | 46 +++ .../core/src}/gasPirce/index.ts | 0 .../core/src}/gasPirce/state/gasPriceAtom.ts | 0 .../api => libs/core/src}/gnosisSafe/index.ts | 4 - libs/core/src/index.ts | 3 + .../core}/src/jotaiStore.ts | 0 libs/core/tsconfig.json | 21 ++ libs/core/tsconfig.lib.json | 19 ++ libs/core/tsconfig.spec.json | 20 ++ libs/core/vite.config.ts | 49 +++ libs/ens/.babelrc | 20 ++ libs/ens/.eslintrc.json | 18 ++ libs/ens/README.md | 1 + libs/ens/jest.config.ts | 11 + libs/ens/package.json | 12 + libs/ens/project.json | 46 +++ .../legacy => libs/ens/src}/hooks/useENS.ts | 8 +- libs/ens/src/hooks/useENSAddress.ts | 21 ++ libs/ens/src/hooks/useENSAvatar.ts | 198 ++++++++++++ libs/ens/src/hooks/useENSContentHash.ts | 21 ++ libs/ens/src/hooks/useENSName.ts | 36 +++ libs/ens/src/hooks/useENSRegistrarContract.ts | 21 ++ libs/ens/src/hooks/useENSResolver.ts | 12 + libs/ens/src/hooks/useENSResolverContract.ts | 16 + libs/ens/src/hooks/useENSResolverMethod.ts | 29 ++ libs/ens/src/index.ts | 5 + libs/ens/tsconfig.json | 21 ++ libs/ens/tsconfig.lib.json | 19 ++ libs/ens/tsconfig.spec.json | 20 ++ libs/ens/vite.config.ts | 49 +++ libs/snackbars/README.md | 4 +- libs/snackbars/package.json | 2 +- libs/snackbars/project.json | 2 +- libs/snackbars/vite.config.ts | 2 +- libs/ui/.eslintrc.json | 3 + libs/ui/project.json | 2 +- libs/ui/src/consts.ts | 1 + .../src/legacy/theme => libs/ui/src}/enum.ts | 0 libs/ui/src/index.ts | 13 +- libs/ui/src/lib/ui.spec.tsx | 10 - libs/ui/src/lib/ui.tsx | 16 - .../ui/src/pure}/Button/ButtonMod.tsx | 73 +---- .../src/pure}/Button/__fixtures__/Button.tsx | 0 .../Button/__fixtures__/ButtonConfirmed.tsx | 0 .../Button/__fixtures__/ButtonDropdown.tsx | 0 .../__fixtures__/ButtonDropdownLight.tsx | 0 .../pure}/Button/__fixtures__/ButtonError.tsx | 0 .../Button/__fixtures__/cosmos.decorator.tsx | 2 +- .../ui/src/pure}/Button/index.tsx | 20 +- libs/ui/src/pure/ExternalLink/index.tsx | 112 +++++++ .../ui/src}/pure/FiatAmount/index.tsx | 15 +- .../ui/src/pure}/Loader/index.tsx | 12 +- .../ui/src/pure}/Loader/styled.tsx | 2 +- .../ui/src/pure}/Popover/PopoverMod.tsx | 26 +- .../ui/src/pure}/Popover/index.tsx | 2 +- .../ui/src/pure}/Row/index.tsx | 6 +- libs/ui/src/pure/SelectDropdown/index.tsx | 29 ++ .../ui/src}/pure/TokenAmount/index.tsx | 18 +- .../ui/src}/pure/TokenSymbol/index.tsx | 5 +- .../ui/src/pure}/Tooltip/index.tsx | 6 +- libs/ui/src/types.ts | 14 + libs/ui/vite.config.ts | 4 +- libs/wallet/.babelrc | 20 ++ libs/wallet/.eslintrc.json | 21 ++ libs/wallet/README.md | 1 + libs/wallet/jest.config.ts | 11 + libs/wallet/package.json | 12 + libs/wallet/project.json | 46 +++ .../wallet/src}/api/assets/alpha.svg | 0 .../wallet/src}/api/assets/ambire.svg | 0 .../src}/api/assets/arrow-right-white.png | Bin .../wallet/src}/api/assets/arrow-right.svg | 0 .../wallet/src}/api/assets/coinbase.svg | 0 .../wallet/src}/api/assets/keystone.svg | 0 .../wallet/src}/api/assets/ledger.svg | 0 .../wallet/src}/api/assets/metamask.png | Bin libs/wallet/src/api/assets/safe-logo.svg | 10 + .../wallet/src}/api/assets/tally.svg | 0 .../wallet/src}/api/assets/trezor.svg | 0 .../wallet/src}/api/assets/trust.svg | 0 .../src}/api/assets/wallet-connect-v2.png | Bin .../src}/api/assets/walletConnectIcon.svg | 0 .../wallet/src}/api/assets/zengo.svg | 0 .../src}/api/container/Identicon/index.tsx | 9 +- .../wallet => libs/wallet/src}/api/hooks.ts | 5 +- .../api/pure/ConnectWalletOption/index.tsx | 7 +- .../wallet/src}/api/pure/Identicon/index.tsx | 4 +- .../wallet => libs/wallet/src}/api/state.ts | 5 +- .../wallet => libs/wallet/src}/api/types.ts | 1 - .../wallet/src/api/utils}/accountsLoaders.ts | 6 +- .../wallet/src}/api/utils/connection.ts | 5 +- .../wallet/src}/api/utils/getHwAccount.ts | 2 +- .../wallet/src}/api/utils/getWalletType.ts | 0 .../src}/api/utils/getWalletTypeLabel.ts | 0 libs/wallet/src/assets.ts | 5 + .../wallet => libs/wallet/src}/constants.ts | 0 libs/wallet/src/index.ts | 59 ++++ libs/wallet/src/types.d.ts | 3 + .../src}/web3-react/connection/alpha.tsx | 11 +- .../src}/web3-react/connection/ambire.tsx | 10 +- .../web3-react/connection/asyncConnector.ts | 0 .../src}/web3-react/connection/coinbase.tsx | 35 +-- .../src}/web3-react/connection/injected.tsx | 39 +-- .../web3-react/connection/injectedWidget.tsx | 0 .../src}/web3-react/connection/keystone.tsx | 21 +- .../src}/web3-react/connection/ledger.tsx | 21 +- .../src}/web3-react/connection/network.tsx | 9 +- .../src/web3-react/connection/onError.ts | 3 + .../src}/web3-react/connection/safe.tsx | 3 +- .../src}/web3-react/connection/tally.tsx | 20 +- .../src}/web3-react/connection/trezor.tsx | 10 +- .../src}/web3-react/connection/trust.tsx | 23 +- .../web3-react/connection/walletConnect.tsx | 30 +- .../web3-react/connection/walletConnectV2.tsx | 27 +- .../Injected/IFrameEthereumProvider.ts | 0 .../web3-react/connectors/Injected/index.tsx | 5 +- .../web3-react/connectors/LedgerConnector.tsx | 0 .../TrezorConnector/TrezorProvider.ts | 0 .../TrezorConnector/getAccountsList.ts | 2 +- .../connectors/TrezorConnector/index.ts | 6 +- .../TrezorConnector/sendTransactionHandler.ts | 5 +- .../TrezorConnector/signTypedDataHandler.ts | 0 .../WalletConnectV2Connector/index.tsx | 0 .../WalletConnectLabeledOption/index.tsx | 16 +- .../web3-react/hooks/useIsActiveConnection.ts | 16 + .../hooks/useIsSmartContractWallet.ts | 87 ++++++ .../web3-react/hooks/useIsWalletConnect.ts | 2 +- .../src}/web3-react/hooks/useSafeAppsSdk.ts | 0 .../hooks/useSafeAppsSdkInfo.test.tsx | 0 .../web3-react/hooks/useSafeAppsSdkInfo.ts | 2 +- .../web3-react/hooks/useWalletMetadata.ts | 8 +- .../pure/AccountIndexSelect/index.cosmos.tsx | 7 +- .../pure/AccountIndexSelect/index.tsx | 19 +- .../pure/AccountIndexSelect/styled.tsx | 5 +- .../wallet/src}/web3-react/types.ts | 10 +- .../wallet/src}/web3-react/updater.ts | 22 +- .../web3-react/utils/getIsHardWareWallet.ts | 9 + .../utils/getWeb3ReactConnection.ts | 47 +++ .../src/web3-react/utils/isChainAllowed.ts | 30 ++ .../src/web3-react/utils}/switchChain.ts | 9 +- libs/wallet/tsconfig.json | 21 ++ libs/wallet/tsconfig.lib.json | 19 ++ libs/wallet/tsconfig.spec.json | 20 ++ libs/wallet/vite.config.ts | 49 +++ libs/widget-lib/README.md | 2 +- libs/widget-lib/docs/README.md | 6 +- libs/widget-react/README.md | 2 +- libs/widget-react/src/lib/CowSwapWidget.tsx | 2 +- libs/widget-react/vite.config.ts | 2 +- nx.json | 10 +- package.json | 68 +---- .../testing => testing}/imgMock.js | 0 .../testing => testing}/svgrMock.js | 0 tools/getReactProcessEnv.ts | 13 + tsconfig.base.json | 20 +- yarn.lock | 20 +- 1215 files changed, 5828 insertions(+), 4939 deletions(-) delete mode 100644 apps/cowswap-frontend/jest.preset.js rename apps/cowswap-frontend/src/{legacy/utils => api}/blocknative.ts (96%) rename apps/cowswap-frontend/src/{legacy/components/analytics => common}/hooks/useAnalyticsReporter.ts (86%) rename apps/cowswap-frontend/src/{legacy/components/analytics => common}/hooks/useGetMarketDimension.ts (100%) delete mode 100644 apps/cowswap-frontend/src/common/hooks/useIsSmartContractWallet.ts rename apps/cowswap-frontend/src/{api/gnosisSafe => common}/hooks/useSafeApiKit.ts (83%) delete mode 100644 apps/cowswap-frontend/src/common/pure/SelectDropdown/index.tsx rename apps/cowswap-frontend/src/{legacy/state/application/updater.ts => common/updaters/ApplicationUpdater.ts} (79%) rename apps/cowswap-frontend/src/{legacy/state/enhancedTransactions/updater => common/updaters}/CancelReplaceTxUpdater.tsx (94%) rename apps/cowswap-frontend/src/{legacy/state/price/updater.ts => common/updaters/FeesUpdater.ts} (91%) rename apps/cowswap-frontend/src/{legacy/state/enhancedTransactions/updater => common/updaters}/FinalizeTxUpdater.tsx (95%) rename apps/cowswap-frontend/src/{legacy/state/gas/updater.tsx => common/updaters/GasUpdater.tsx} (55%) rename apps/cowswap-frontend/src/{modules/wallet/api => common}/updaters/HwAccountIndexUpdater.tsx (89%) rename apps/cowswap-frontend/src/{legacy/state/lists/updater.ts => common/updaters/ListsUpdater.ts} (93%) rename apps/cowswap-frontend/src/{legacy/state/logs/updater.ts => common/updaters/LogsUpdater.ts} (86%) rename apps/cowswap-frontend/src/{legacy/state/sentry/updater/index.ts => common/updaters/SentryUpdater.ts} (71%) rename apps/cowswap-frontend/src/{legacy/state/user/updater.tsx => common/updaters/UserUpdater.tsx} (89%) rename apps/cowswap-frontend/src/{legacy/state/orders/updaters => common/updaters/orders}/CancelledOrdersUpdater.ts (95%) rename apps/cowswap-frontend/src/{legacy/state/orders/updaters => common/updaters/orders}/ExpiredOrdersUpdater.ts (95%) rename apps/cowswap-frontend/src/{legacy/state/orders/updaters => common/updaters/orders}/GpOrdersUpdater.ts (97%) rename apps/cowswap-frontend/src/{legacy/state/orders/updaters => common/updaters/orders}/PendingOrdersUpdater.ts (95%) rename apps/cowswap-frontend/src/{legacy/state/orders/updaters => common/updaters/orders}/SpotPricesUpdater.ts (93%) rename apps/cowswap-frontend/src/{legacy/state/orders/updaters => common/updaters/orders}/UnfillableOrdersUpdater.ts (94%) rename apps/cowswap-frontend/src/{legacy/state/orders/updaters => common/updaters/orders}/index.ts (100%) rename apps/cowswap-frontend/src/{legacy/state/orders/updaters => common/updaters/orders}/utils.ts (96%) rename apps/cowswap-frontend/src/{utils => cow-react}/sentry.ts (93%) delete mode 100644 apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonRadioChecked.tsx rename apps/cowswap-frontend/src/{modules/wallet/web3-react => legacy/components/Web3Provider}/hooks/useEagerlyConnect.ts (73%) rename apps/cowswap-frontend/src/{modules/wallet/web3-react => legacy/components/Web3Provider}/hooks/useOrderedConnections.ts (79%) delete mode 100644 apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts delete mode 100644 apps/cowswap-frontend/src/legacy/constants/chains.ts delete mode 100644 apps/cowswap-frontend/src/legacy/constants/proposals/index.ts delete mode 100644 apps/cowswap-frontend/src/legacy/constants/proposals/polygon_proposal_title.ts delete mode 100644 apps/cowswap-frontend/src/legacy/constants/proposals/uniswap_grants_proposal_description.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useAccountRiskCheck.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useAllCurrencyCombinations.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useApeModeQueryParamReader.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useArgentWalletContract.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useColor/index.ts create mode 100644 apps/cowswap-frontend/src/legacy/hooks/useCombinedBalance.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useENSAddress.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useENSAvatar.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useENSContentHash.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useENSName.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useIsAmbireWallet.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useIsArgentWallet.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useLocationLinkProps.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useNetworkName.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useTheme.ts delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useTokenInfoFromActiveList.ts create mode 100644 apps/cowswap-frontend/src/legacy/state/claim/hooks/const.ts create mode 100644 apps/cowswap-frontend/src/legacy/state/claim/hooks/types.ts rename apps/cowswap-frontend/src/{pages/Claim => legacy/state/claim}/types.ts (89%) delete mode 100644 apps/cowswap-frontend/src/legacy/state/connection/hooks.ts delete mode 100644 apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/index.tsx create mode 100644 apps/cowswap-frontend/src/legacy/state/multicall.tsx rename apps/cowswap-frontend/src/{modules/orders/utils => legacy/state/orders}/flatOrdersStateNetwork.ts (78%) rename apps/cowswap-frontend/src/{api/gnosisProtocol/legacy => legacy/state/price}/types.ts (87%) rename apps/cowswap-frontend/src/legacy/{components/TransactionConfirmationModal => state}/types.ts (73%) delete mode 100644 apps/cowswap-frontend/src/legacy/utils/constructSameAddressMap.ts delete mode 100644 apps/cowswap-frontend/src/legacy/utils/listVersionLabel.ts delete mode 100644 apps/cowswap-frontend/src/lib/state/multicall.tsx delete mode 100644 apps/cowswap-frontend/src/lib/utils/contenthashToUri.test.skip.ts rename apps/cowswap-frontend/src/modules/{wallet/web3-react => account}/hooks/useDisconnectWallet.ts (100%) rename apps/cowswap-frontend/src/{legacy/state/swap/hooks.test.ts => modules/swap/hooks/useSwapState.test.ts} (95%) rename apps/cowswap-frontend/src/{legacy/state/swap/hooks.tsx => modules/swap/hooks/useSwapState.tsx} (95%) rename apps/cowswap-frontend/src/{legacy/state/orders/middleware => modules/twap/state}/composableOrdersPopupMiddleware.ts (64%) delete mode 100644 apps/cowswap-frontend/src/modules/wallet/api/assets/formatic.png delete mode 100644 apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/index.tsx delete mode 100644 apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts rename apps/cowswap-frontend/src/modules/wallet/{web3-react => }/containers/AccountSelectorModal/index.tsx (87%) rename apps/cowswap-frontend/src/modules/wallet/{web3-react => }/containers/AccountSelectorModal/state.ts (100%) rename apps/cowswap-frontend/src/modules/wallet/{web3-react => }/containers/AccountSelectorModal/styled.tsx (89%) rename apps/cowswap-frontend/src/modules/wallet/{web3-react => }/containers/AddToMetamask/index.tsx (66%) create mode 100644 apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx rename apps/cowswap-frontend/src/{legacy/components/Popups => modules/wallet/containers}/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx (97%) rename apps/cowswap-frontend/src/{legacy/components/Popups => modules/wallet/containers}/FollowPendingTxPopup/index.tsx (91%) rename apps/cowswap-frontend/src/modules/wallet/{web3-react => }/containers/WalletModal/index.tsx (86%) rename apps/cowswap-frontend/src/modules/wallet/{web3-react => }/containers/Web3Status/index.tsx (59%) delete mode 100644 apps/cowswap-frontend/src/modules/wallet/index.ts rename apps/cowswap-frontend/src/modules/wallet/{api => }/pure/AddToMetamask/index.tsx (83%) rename apps/cowswap-frontend/src/modules/wallet/{api => }/pure/PendingView/index.tsx (96%) rename apps/cowswap-frontend/src/modules/wallet/{api => }/pure/StatusIcon/index.tsx (64%) rename apps/cowswap-frontend/src/modules/wallet/{api => }/pure/WalletModal/index.tsx (93%) rename apps/cowswap-frontend/src/modules/wallet/{api => }/pure/WalletModal/styled.tsx (93%) rename apps/cowswap-frontend/src/modules/wallet/{api => }/pure/Web3StatusInner/index.tsx (82%) rename apps/cowswap-frontend/src/modules/wallet/{api => }/pure/Web3StatusInner/styled.ts (96%) rename apps/cowswap-frontend/src/{legacy/state/application/atoms.ts => modules/wallet/state/followPendingTxPopupAtom.ts} (96%) delete mode 100644 apps/cowswap-frontend/src/modules/wallet/web3-react/connection/formatic.tsx delete mode 100644 apps/cowswap-frontend/src/modules/wallet/web3-react/connection/index.tsx delete mode 100644 apps/cowswap-frontend/src/pages/KitchenSink/index.tsx create mode 100644 libs/analytics/.babelrc create mode 100644 libs/analytics/.eslintrc.json create mode 100644 libs/analytics/README.md create mode 100644 libs/analytics/jest.config.ts create mode 100644 libs/analytics/package.json create mode 100644 libs/analytics/project.json rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/events/cowFortune.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/events/listEvents.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/events/otherEvents.ts (94%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/events/settingsEvents.ts (95%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/events/swapEvents.ts (75%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/events/themeEvents.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/events/transactionEvents.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/events/twapEvents.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/events/walletEvents.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/googleAnalytics.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/index.ts (87%) create mode 100644 libs/analytics/src/pixel/constants.ts rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/pixel/facebook.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/pixel/index.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/pixel/linkedin.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/pixel/microsoft.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/pixel/paved.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/pixel/reddit.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/pixel/sendAllPixels.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/pixel/twitter.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/pixel/types.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/pixel/utils.ts (100%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/provider/index.ts (98%) rename {apps/cowswap-frontend/src/legacy/components/analytics => libs/analytics/src}/types.ts (100%) create mode 100644 libs/analytics/tsconfig.json create mode 100644 libs/analytics/tsconfig.lib.json create mode 100644 libs/analytics/tsconfig.spec.json create mode 100644 libs/analytics/vite.config.ts create mode 100644 libs/assets/.babelrc create mode 100644 libs/assets/.eslintrc.json create mode 100644 libs/assets/README.md create mode 100644 libs/assets/jest.config.ts create mode 100644 libs/assets/package.json create mode 100644 libs/assets/project.json rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/CowError.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/alert-circle.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/alert.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/0x.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/1inch.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/baoswap.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/curve.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/elk.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/honeyswap.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/levinswap.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/matcha.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/paraswap.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/sushi.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/swapr.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/symmetric.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ammslogo/uniswap.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/anniversary-icons.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/arrow.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/arrowDownRight.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/attention.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/carret-down.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/check-singular.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/check.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/checkmark.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/code.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cookie-policy.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cow-404.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cow-load.gif (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cow-load.webp (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cow-no-connection.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cow.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cow_v2.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cowprotocol.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cowswap-diagram.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cowswap-logo.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cursor1.gif (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cursor2.gif (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cursor3.gif (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/cursor4.gif (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/discord.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/doc.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/etherscan-icon.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/exclamation.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/experiment.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/feedback.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/finish.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/fortune-cookie.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/game.gif (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/gasless.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/gno.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/halloween-bats.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/halloween-spider.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/important.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/info.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/loading.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/meditating-cow-v2.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/menu.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/mev.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/moon.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/network-gnosis-chain-logo.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/network-goerli-logo.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/network-mainnet-logo.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/network-rinkeby-logo.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/ninja-cow.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/order-cancelled.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/order-check.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/order-cross.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/order-expired.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/order-open.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/order-presignature-pending.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/orderExecution.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/pie.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/plus.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/privacy-policy.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/protection.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/question.ts (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/refund.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/round-arrow.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet/api/assets => libs/assets/src/cow-swap}/safe-logo.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/savings.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/send.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/sun.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/surplus-cow.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/terms-and-conditions.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/transaction-arrows.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/transaction-confirmed.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/twitter.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/usdc.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/vCOW.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/wallet-plus.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/wxdai.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/x.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/cow-swap/xdai.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/amms-graph-gc.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/amms-graph.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/arrow-down-blue.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/arrow-down-grey.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/big_unicorn.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/blue-loader.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/circle-grey.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/circle.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/cow-graph.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/cow-meditating-smoooth.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/cow-meditating.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/dropdown-blue.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/dropdown.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/dropup-blue.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/ethereum-logo.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/gas-icon.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/link.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/magnifying-glass.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/menu.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/noise.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/plus-blue.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/plus-grey.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/portisIcon.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/question-mark.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/question.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/router-icon-grey.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/sandtexture.webp (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/santa-hat.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/spinner.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/squiggle.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/survey-orb.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/token-list-logo.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/token-list/lists-dark.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/token-list/lists-light.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/token-logo.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/tokenlistsgrouped.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/trustWallet.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/ukraine.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/widget-screenshot.png (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/x.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/images/xl_uni.png (100%) create mode 100644 libs/assets/src/index.ts rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/styles/styled.ts (88%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/QR.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/arbitrum_logo.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/celo_logo.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/dot_line.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/lightcircle.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/logo.svg (99%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/logo_pink.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/matic-token-icon.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/optimism_logo.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/optimistic_ethereum.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/polygon-matic-logo.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/question.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/static_route.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/switch.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/tokenlist.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/wordmark.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/wordmark_pink.svg (100%) rename {apps/cowswap-frontend/src/legacy/assets => libs/assets/src}/svg/wordmark_white.svg (100%) create mode 100644 libs/assets/tsconfig.json create mode 100644 libs/assets/tsconfig.lib.json create mode 100644 libs/assets/tsconfig.spec.json create mode 100644 libs/assets/vite.config.ts create mode 100644 libs/common-const/.babelrc create mode 100644 libs/common-const/.eslintrc.json create mode 100644 libs/common-const/README.md create mode 100644 libs/common-const/jest.config.ts create mode 100644 libs/common-const/package.json create mode 100644 libs/common-const/project.json rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/addresses.ts (63%) rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/chainInfo.ts (89%) rename apps/cowswap-frontend/src/legacy/constants/index.ts => libs/common-const/src/common.ts (96%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-const/src}/gnosis_chain/constants.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-const/src}/gnosis_chain/hack.ts (52%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-const/src}/goerli/constants.ts (100%) create mode 100644 libs/common-const/src/index.ts rename {apps/cowswap-frontend/src/common/constants => libs/common-const/src}/intl.ts (100%) rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/ipfs.ts (100%) rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/lists.ts (98%) rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/locales.ts (100%) rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/misc.ts (100%) rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/networks.ts (100%) rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/routing.ts (95%) rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/tokenLists/broken.tokenlist.json (100%) rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/tokenLists/unsupported.tokenlist.json (100%) rename {apps/cowswap-frontend/src/legacy/constants => libs/common-const/src}/tokens.ts (95%) create mode 100644 libs/common-const/tsconfig.json create mode 100644 libs/common-const/tsconfig.lib.json create mode 100644 libs/common-const/tsconfig.spec.json create mode 100644 libs/common-const/vite.config.ts create mode 100644 libs/common-hooks/.babelrc create mode 100644 libs/common-hooks/.eslintrc.json create mode 100644 libs/common-hooks/README.md create mode 100644 libs/common-hooks/jest.config.ts create mode 100644 libs/common-hooks/package.json create mode 100644 libs/common-hooks/project.json create mode 100644 libs/common-hooks/src/index.ts rename {apps/cowswap-frontend/src/lib/hooks => libs/common-hooks/src}/useBlockNumber.tsx (95%) rename apps/cowswap-frontend/src/legacy/hooks/useColor/useColorMod.ts => libs/common-hooks/src/useColor/index.ts (95%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useContract.ts (82%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useCopyClipboard.ts (85%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useDebounce.ts (92%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useDebouncedChangeHandler.tsx (95%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useFetchFile.ts (93%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useFilterTokens.ts (88%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useGetReceipt.ts (78%) rename {apps/cowswap-frontend/src/lib/hooks => libs/common-hooks/src}/useInterval.ts (89%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useIsMounted.ts (89%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useIsOnline.ts (95%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useIsWindowVisible.ts (93%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useLast.ts (94%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useLoadingWithTimeout.ts (92%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useMachineTime.ts (52%) create mode 100644 libs/common-hooks/src/useNetworkName.ts rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useOnClickOutside.tsx (100%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useParsedQueryString.ts (90%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/usePrevious.ts (90%) create mode 100644 libs/common-hooks/src/useTheme.ts rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useTimeAgo.ts (84%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useToggle.ts (70%) rename {apps/cowswap-frontend/src/legacy/hooks => libs/common-hooks/src}/useWindowSize.ts (100%) create mode 100644 libs/common-hooks/tsconfig.json create mode 100644 libs/common-hooks/tsconfig.lib.json create mode 100644 libs/common-hooks/tsconfig.spec.json create mode 100644 libs/common-hooks/vite.config.ts create mode 100644 libs/common-utils/.babelrc create mode 100644 libs/common-utils/.env create mode 100644 libs/common-utils/.eslintrc.json create mode 100644 libs/common-utils/README.md create mode 100644 libs/common-utils/jest.config.ts create mode 100644 libs/common-utils/package.json create mode 100644 libs/common-utils/project.json rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/amountFormat/README.md (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/amountFormat/index.test.ts (97%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/amountFormat/index.ts (89%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/amountFormat/utils.ts (94%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/anonymizeLink.test.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/anonymizeLink.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/appzi.ts (96%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/areFractionsEqual.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/async.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/blocks.ts (100%) rename {apps/cowswap-frontend/src/modules/utils/orderUtils => libs/common-utils/src}/buildPriceFromCurrencyAmounts.ts (91%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/calculateGasMargin.test.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/calculateGasMargin.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/calculatePriceImpact.test.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/calculateSlippageAmount.test.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/calculateSlippageAmount.ts (74%) rename {apps/cowswap-frontend/src/lib/utils => libs/common-utils/src}/contenthashToUri.ts (94%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/currencyAmountToTokenAmount.ts (64%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/currencyId.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/deepEqual.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/deterministicHash.test.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/deterministicHash.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/displayTime.tsx (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/doesTokenMatchSymbolOrAddress.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/env.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/environments.test.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/environments.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/explorer.ts (93%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/featureFlags.ts (88%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/format.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/formatCurrencyAmount.ts (88%) rename {apps/cowswap-frontend/src/lib/utils => libs/common-utils/src}/formatLocaleNumber.test.ts (87%) rename {apps/cowswap-frontend/src/lib/utils => libs/common-utils/src}/formatLocaleNumber.ts (94%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/fractionUtils.test.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/fractionUtils.ts (80%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/genericPropsChecker.test.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/genericPropsChecker.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/getAddress.ts (54%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/getCurrentChainIdFromUrl.test.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/getCurrentChainIdFromUrl.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/getDoesMessageIncludeToken.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/getExplorerLink.test.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/getExplorerLink.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/getIntOrFloat.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/getIsNativeToken.ts (83%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/getIsWrapOrUnwrap.ts (84%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/getQuoteUnsupportedToken.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/getRandomInt.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/getUserAgent.ts (100%) create mode 100644 libs/common-utils/src/index.ts rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/isEnoughAmount.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/isFractionFalsy.ts (100%) rename {apps/cowswap-frontend/src/common/utils => libs/common-utils/src}/isInjectedWidget.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/isNotNullish.ts (77%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/isZero.ts (68%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/jotai/atomWithPartialUpdate.ts (82%) rename apps/cowswap-frontend/src/legacy/utils/index.test.ts => libs/common-utils/src/legacyAddressUtils.test.ts (89%) rename apps/cowswap-frontend/src/legacy/utils/index.ts => libs/common-utils/src/legacyAddressUtils.ts (90%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/listSort.ts (74%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/localStorage.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/logging/index.ts (90%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/maxAmountSpend.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/misc.ts (98%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/node.ts (100%) rename {apps/cowswap-frontend/src/lib/utils => libs/common-utils/src}/parseENSAddress.test.ts (95%) rename {apps/cowswap-frontend/src/lib/utils => libs/common-utils/src}/parseENSAddress.ts (64%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/rawToTokenAmount.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/request.ts (100%) rename {apps/cowswap-frontend/src/lib/utils => libs/common-utils/src}/resolveENSContentHash.ts (93%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/retry.test.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/retry.ts (94%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/safeNamehash.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/sound.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/swapErrorToUserReadableMessage.tsx (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/time.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/toggleBodyClass.ts (100%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/tokens.ts (82%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/tooltips.ts (89%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/trimTrailingZeros.test.ts (100%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/trimTrailingZeros.ts (100%) rename {apps/cowswap-frontend/src/lib/utils => libs/common-utils/src}/tryParseCurrencyAmount.ts (78%) rename {apps/cowswap-frontend/src/utils => libs/common-utils/src}/tryParseFractionalAmount.ts (90%) create mode 100644 libs/common-utils/src/types.ts rename {apps/cowswap-frontend/src/lib/utils => libs/common-utils/src}/uriToHttp.test.ts (96%) rename {apps/cowswap-frontend/src/lib/utils => libs/common-utils/src}/uriToHttp.ts (81%) rename {apps/cowswap-frontend/src/legacy/utils => libs/common-utils/src}/userAgent.ts (100%) create mode 100644 libs/common-utils/tsconfig.json create mode 100644 libs/common-utils/tsconfig.lib.json create mode 100644 libs/common-utils/tsconfig.spec.json create mode 100644 libs/common-utils/vite.config.ts create mode 100644 libs/core/.babelrc create mode 100644 libs/core/.eslintrc.json create mode 100644 libs/core/README.md create mode 100644 libs/core/jest.config.ts create mode 100644 libs/core/package.json create mode 100644 libs/core/project.json rename {apps/cowswap-frontend/src/modules => libs/core/src}/gasPirce/index.ts (100%) rename {apps/cowswap-frontend/src/modules => libs/core/src}/gasPirce/state/gasPriceAtom.ts (100%) rename {apps/cowswap-frontend/src/api => libs/core/src}/gnosisSafe/index.ts (97%) create mode 100644 libs/core/src/index.ts rename {apps/cowswap-frontend => libs/core}/src/jotaiStore.ts (100%) create mode 100644 libs/core/tsconfig.json create mode 100644 libs/core/tsconfig.lib.json create mode 100644 libs/core/tsconfig.spec.json create mode 100644 libs/core/vite.config.ts create mode 100644 libs/ens/.babelrc create mode 100644 libs/ens/.eslintrc.json create mode 100644 libs/ens/README.md create mode 100644 libs/ens/jest.config.ts create mode 100644 libs/ens/package.json create mode 100644 libs/ens/project.json rename {apps/cowswap-frontend/src/legacy => libs/ens/src}/hooks/useENS.ts (79%) create mode 100644 libs/ens/src/hooks/useENSAddress.ts create mode 100644 libs/ens/src/hooks/useENSAvatar.ts create mode 100644 libs/ens/src/hooks/useENSContentHash.ts create mode 100644 libs/ens/src/hooks/useENSName.ts create mode 100644 libs/ens/src/hooks/useENSRegistrarContract.ts create mode 100644 libs/ens/src/hooks/useENSResolver.ts create mode 100644 libs/ens/src/hooks/useENSResolverContract.ts create mode 100644 libs/ens/src/hooks/useENSResolverMethod.ts create mode 100644 libs/ens/src/index.ts create mode 100644 libs/ens/tsconfig.json create mode 100644 libs/ens/tsconfig.lib.json create mode 100644 libs/ens/tsconfig.spec.json create mode 100644 libs/ens/vite.config.ts create mode 100644 libs/ui/src/consts.ts rename {apps/cowswap-frontend/src/legacy/theme => libs/ui/src}/enum.ts (100%) delete mode 100644 libs/ui/src/lib/ui.spec.tsx delete mode 100644 libs/ui/src/lib/ui.tsx rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Button/ButtonMod.tsx (83%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Button/__fixtures__/Button.tsx (100%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Button/__fixtures__/ButtonConfirmed.tsx (100%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Button/__fixtures__/ButtonDropdown.tsx (100%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Button/__fixtures__/ButtonDropdownLight.tsx (100%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Button/__fixtures__/ButtonError.tsx (100%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Button/__fixtures__/cosmos.decorator.tsx (92%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Button/index.tsx (92%) create mode 100644 libs/ui/src/pure/ExternalLink/index.tsx rename {apps/cowswap-frontend/src/common => libs/ui/src}/pure/FiatAmount/index.tsx (68%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Loader/index.tsx (82%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Loader/styled.tsx (92%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Popover/PopoverMod.tsx (89%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Popover/index.tsx (96%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Row/index.tsx (91%) create mode 100644 libs/ui/src/pure/SelectDropdown/index.tsx rename {apps/cowswap-frontend/src/common => libs/ui/src}/pure/TokenAmount/index.tsx (78%) rename {apps/cowswap-frontend/src/common => libs/ui/src}/pure/TokenSymbol/index.tsx (86%) rename {apps/cowswap-frontend/src/legacy/components => libs/ui/src/pure}/Tooltip/index.tsx (91%) create mode 100644 libs/ui/src/types.ts create mode 100644 libs/wallet/.babelrc create mode 100644 libs/wallet/.eslintrc.json create mode 100644 libs/wallet/README.md create mode 100644 libs/wallet/jest.config.ts create mode 100644 libs/wallet/package.json create mode 100644 libs/wallet/project.json rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/alpha.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/ambire.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/arrow-right-white.png (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/arrow-right.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/coinbase.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/keystone.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/ledger.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/metamask.png (100%) create mode 100644 libs/wallet/src/api/assets/safe-logo.svg rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/tally.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/trezor.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/trust.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/wallet-connect-v2.png (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/walletConnectIcon.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/assets/zengo.svg (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/container/Identicon/index.tsx (86%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/hooks.ts (85%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/pure/ConnectWalletOption/index.tsx (95%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/pure/Identicon/index.tsx (91%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/state.ts (87%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/types.ts (97%) rename {apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal => libs/wallet/src/api/utils}/accountsLoaders.ts (66%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/utils/connection.ts (94%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/utils/getHwAccount.ts (86%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/utils/getWalletType.ts (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/api/utils/getWalletTypeLabel.ts (100%) create mode 100644 libs/wallet/src/assets.ts rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/constants.ts (100%) create mode 100644 libs/wallet/src/index.ts create mode 100644 libs/wallet/src/types.d.ts rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/alpha.tsx (58%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/ambire.tsx (58%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/asyncConnector.ts (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/coinbase.tsx (55%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/injected.tsx (57%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/injectedWidget.tsx (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/keystone.tsx (67%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/ledger.tsx (62%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/network.tsx (73%) create mode 100644 libs/wallet/src/web3-react/connection/onError.ts rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/safe.tsx (91%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/tally.tsx (58%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/trezor.tsx (74%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/trust.tsx (62%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/walletConnect.tsx (69%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connection/walletConnectV2.tsx (84%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connectors/Injected/IFrameEthereumProvider.ts (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connectors/Injected/index.tsx (98%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connectors/LedgerConnector.tsx (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connectors/TrezorConnector/TrezorProvider.ts (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connectors/TrezorConnector/getAccountsList.ts (97%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connectors/TrezorConnector/index.ts (97%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts (95%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connectors/TrezorConnector/signTypedDataHandler.ts (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/connectors/WalletConnectV2Connector/index.tsx (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/containers/WalletConnectLabeledOption/index.tsx (77%) create mode 100644 libs/wallet/src/web3-react/hooks/useIsActiveConnection.ts create mode 100644 libs/wallet/src/web3-react/hooks/useIsSmartContractWallet.ts rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/hooks/useIsWalletConnect.ts (88%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/hooks/useSafeAppsSdk.ts (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/hooks/useSafeAppsSdkInfo.test.tsx (100%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/hooks/useSafeAppsSdkInfo.ts (87%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/hooks/useWalletMetadata.ts (92%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/pure/AccountIndexSelect/index.cosmos.tsx (89%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/pure/AccountIndexSelect/index.tsx (83%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/pure/AccountIndexSelect/styled.tsx (88%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/types.ts (58%) rename {apps/cowswap-frontend/src/modules/wallet => libs/wallet/src}/web3-react/updater.ts (84%) create mode 100644 libs/wallet/src/web3-react/utils/getIsHardWareWallet.ts create mode 100644 libs/wallet/src/web3-react/utils/getWeb3ReactConnection.ts create mode 100644 libs/wallet/src/web3-react/utils/isChainAllowed.ts rename {apps/cowswap-frontend/src/modules/wallet/web3-react/hooks => libs/wallet/src/web3-react/utils}/switchChain.ts (84%) create mode 100644 libs/wallet/tsconfig.json create mode 100644 libs/wallet/tsconfig.lib.json create mode 100644 libs/wallet/tsconfig.spec.json create mode 100644 libs/wallet/vite.config.ts rename {apps/cowswap-frontend/testing => testing}/imgMock.js (100%) rename {apps/cowswap-frontend/testing => testing}/svgrMock.js (100%) create mode 100644 tools/getReactProcessEnv.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd61e41274..873ea894a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,7 +129,6 @@ jobs: key: ${{ runner.os }}-generatedFiles-${{ hashFiles('**/yarn.lock') }} - name: Run eslint - if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login != github.repository_owner }} run: yarn lint integration-tests: diff --git a/apps/cowswap-frontend/.eslintrc.json b/apps/cowswap-frontend/.eslintrc.json index b2c745ef49..6ed98b0c25 100644 --- a/apps/cowswap-frontend/.eslintrc.json +++ b/apps/cowswap-frontend/.eslintrc.json @@ -57,7 +57,7 @@ "position": "before" }, { - "pattern": "{@cowswap,@cowprotocol,@uniswap,@safe-global,@ethersproject,@web3-react}/**", + "pattern": "{@cowprotocol,@cowprotocol,@uniswap,@safe-global,@ethersproject,@web3-react}/**", "group": "external", "position": "before" }, diff --git a/apps/cowswap-frontend/jest.config.ts b/apps/cowswap-frontend/jest.config.ts index 23c90f2f6e..db7f62924a 100644 --- a/apps/cowswap-frontend/jest.config.ts +++ b/apps/cowswap-frontend/jest.config.ts @@ -3,7 +3,7 @@ /* eslint-disable */ export default { displayName: 'cowswap', - preset: './jest.preset.js', + preset: '../../jest.preset.js', transform: { '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], diff --git a/apps/cowswap-frontend/jest.preset.js b/apps/cowswap-frontend/jest.preset.js deleted file mode 100644 index 098821875b..0000000000 --- a/apps/cowswap-frontend/jest.preset.js +++ /dev/null @@ -1,11 +0,0 @@ -const nxPreset = require('@nx/jest/preset').default - -module.exports = { - ...nxPreset, - moduleNameMapper: { - '\\.svg': '/testing/svgrMock.js', - '\\.gif': '/testing/imgMock.js', - '\\.webp': '/testing/imgMock.js', - '\\.png': '/testing/imgMock.js', - }, -} diff --git a/apps/cowswap-frontend/project.json b/apps/cowswap-frontend/project.json index e483f72f76..7e3ecd7bdf 100644 --- a/apps/cowswap-frontend/project.json +++ b/apps/cowswap-frontend/project.json @@ -9,7 +9,7 @@ "outputs": ["{options.outputPath}"], "defaultConfiguration": "production", "options": { - "outputPath": "dist/apps/cowswap-frontend" + "outputPath": "build" }, "configurations": { "development": { diff --git a/apps/cowswap-frontend/src/api/1inch/index.ts b/apps/cowswap-frontend/src/api/1inch/index.ts index 23e0101787..02381b7e58 100644 --- a/apps/cowswap-frontend/src/api/1inch/index.ts +++ b/apps/cowswap-frontend/src/api/1inch/index.ts @@ -1,12 +1,12 @@ +import { getTokensFromMarket } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/contracts' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { PriceInformation } from 'types' -import { getTokensFromMarket } from 'legacy/utils/misc' +import { LegacyPriceQuoteParams } from 'legacy/state/price/types' import { getValidParams } from 'legacy/utils/price' -import { LegacyPriceQuoteParams } from 'api/gnosisProtocol/legacy/types' import { fetchWithRateLimit } from 'common/utils/fetch' export const API_NAME = '1inch' diff --git a/apps/cowswap-frontend/src/legacy/utils/blocknative.ts b/apps/cowswap-frontend/src/api/blocknative.ts similarity index 96% rename from apps/cowswap-frontend/src/legacy/utils/blocknative.ts rename to apps/cowswap-frontend/src/api/blocknative.ts index 3da30ab01b..02e8ff218e 100644 --- a/apps/cowswap-frontend/src/legacy/utils/blocknative.ts +++ b/apps/cowswap-frontend/src/api/blocknative.ts @@ -1,8 +1,8 @@ +import { ALL_SUPPORTED_CHAIN_IDS } from '@cowprotocol/cow-sdk' + import * as Sentry from '@sentry/browser' import BlocknativeSdk from 'bnc-sdk' -import { ALL_SUPPORTED_CHAIN_IDS } from 'legacy/constants/chains' - const BLOCKNATIVE_API_KEY = process.env.REACT_APP_BLOCKNATIVE_API_KEY interface SDKError { diff --git a/apps/cowswap-frontend/src/api/gasPrices/index.ts b/apps/cowswap-frontend/src/api/gasPrices/index.ts index 35b24aa52b..6da9ca3898 100644 --- a/apps/cowswap-frontend/src/api/gasPrices/index.ts +++ b/apps/cowswap-frontend/src/api/gasPrices/index.ts @@ -1,8 +1,6 @@ +import { DEFAULT_NETWORK_FOR_LISTS, GAS_API_KEYS, GAS_FEE_ENDPOINTS } from '@cowprotocol/common-const' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' -import { GAS_FEE_ENDPOINTS, GAS_API_KEYS } from 'legacy/constants' -import { DEFAULT_NETWORK_FOR_LISTS } from 'legacy/constants/lists' - import { fetchWithRateLimit } from 'common/utils/fetch' const fetchRateLimitted = fetchWithRateLimit({ diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts b/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts index 2eece9971d..87646e78ea 100644 --- a/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts +++ b/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts @@ -1,3 +1,5 @@ +import { ZERO_ADDRESS } from '@cowprotocol/common-const' +import { isBarn, isDev, isLocal, isPr, toErc20Address, toNativeBuyAddress } from '@cowprotocol/common-utils' import { Address, CowEnv, @@ -19,17 +21,13 @@ import { import { orderBookApi } from 'cowSdk' -import { ZERO_ADDRESS } from 'legacy/constants/misc' -import { isBarn, isDev, isLocal, isPr } from 'legacy/utils/environments' -import { toErc20Address, toNativeBuyAddress } from 'legacy/utils/tokens' +import { LegacyFeeQuoteParams as FeeQuoteParams } from 'legacy/state/price/types' import { getAppData } from 'modules/appData' import { ApiErrorCodes, ApiErrorObject } from 'api/gnosisProtocol/errors/OperatorError' import GpQuoteError, { GpQuoteErrorDetails, mapOperatorErrorToQuoteError } from 'api/gnosisProtocol/errors/QuoteError' -import { LegacyFeeQuoteParams as FeeQuoteParams } from './legacy/types' - function getProfileUrl(): Partial> { if (isLocal || isDev || isPr || isBarn) { return { diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/hooks.ts b/apps/cowswap-frontend/src/api/gnosisProtocol/hooks.ts index 971dd6ac5a..82e70ad753 100644 --- a/apps/cowswap-frontend/src/api/gnosisProtocol/hooks.ts +++ b/apps/cowswap-frontend/src/api/gnosisProtocol/hooks.ts @@ -1,11 +1,10 @@ +import { GP_ORDER_UPDATE_INTERVAL } from '@cowprotocol/common-const' import { EnrichedOrder } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import useSWR from 'swr' -import { GP_ORDER_UPDATE_INTERVAL } from 'legacy/constants' - import { useSWROrdersRequest } from 'modules/orders/hooks/useSWROrdersRequest' -import { useWalletInfo } from 'modules/wallet' import { getOrders } from './api' diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/priceApi.ts b/apps/cowswap-frontend/src/api/gnosisProtocol/priceApi.ts index cf9f0cb12a..0ba9d83320 100644 --- a/apps/cowswap-frontend/src/api/gnosisProtocol/priceApi.ts +++ b/apps/cowswap-frontend/src/api/gnosisProtocol/priceApi.ts @@ -1,8 +1,8 @@ +import { RAW_CODE_LINK } from '@cowprotocol/common-const' +import { environmentName } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { RAW_CODE_LINK } from 'legacy/constants' import { GpPriceStrategy } from 'legacy/state/gas/atoms' -import { environmentName } from 'legacy/utils/environments' const API_NAME = 'CoW Protocol' const STRATEGY_URL_BASE = RAW_CODE_LINK + '/configuration/config/' diff --git a/apps/cowswap-frontend/src/api/matcha-0x/index.ts b/apps/cowswap-frontend/src/api/matcha-0x/index.ts index 6c9a7017ff..4482a577a0 100644 --- a/apps/cowswap-frontend/src/api/matcha-0x/index.ts +++ b/apps/cowswap-frontend/src/api/matcha-0x/index.ts @@ -1,12 +1,12 @@ +import { getTokensFromMarket } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/contracts' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { PriceInformation } from 'types' -import { getTokensFromMarket } from 'legacy/utils/misc' +import { LegacyPriceQuoteParams } from 'legacy/state/price/types' import { getValidParams } from 'legacy/utils/price' -import { LegacyPriceQuoteParams } from 'api/gnosisProtocol/legacy/types' import { fetchWithRateLimit } from 'common/utils/fetch' // copy/pasting as the library types correspond to the internal types, not API response diff --git a/apps/cowswap-frontend/src/api/proxy/hooks.ts b/apps/cowswap-frontend/src/api/proxy/hooks.ts index 97326bd6b7..4d1d43bc92 100644 --- a/apps/cowswap-frontend/src/api/proxy/hooks.ts +++ b/apps/cowswap-frontend/src/api/proxy/hooks.ts @@ -1,17 +1,15 @@ import { atom, useAtomValue, useSetAtom } from 'jotai' +import { isAddress } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { ALL_SUPPORTED_CHAIN_IDS } from '@cowprotocol/cow-sdk' import * as Sentry from '@sentry/react' import useSWR from 'swr' - -import { ALL_SUPPORTED_CHAIN_IDS } from 'legacy/constants/chains' -import { isAddress } from 'legacy/utils' +import { Nullish } from 'types' import { getTokens } from './api' -import { Nullish } from '../../types' - import type { Chain, FetchTokensApiResult, FetchTokensResult, TokenLogoCache } from './types' function isValidQuery(query: string): boolean { diff --git a/apps/cowswap-frontend/src/common/constants/featureFlags.ts b/apps/cowswap-frontend/src/common/constants/featureFlags.ts index bb23b1417d..d947ca6461 100644 --- a/apps/cowswap-frontend/src/common/constants/featureFlags.ts +++ b/apps/cowswap-frontend/src/common/constants/featureFlags.ts @@ -1,4 +1,3 @@ -export const AMOUNTS_FORMATTING_FEATURE_FLAG = 'highlight-amounts-formatting' export const ordersTableFeatures = { // Temporary hide estimated execution price because it requires rework and retest DISPLAY_EST_EXECUTION_PRICE: false, diff --git a/apps/cowswap-frontend/src/common/constants/routes.ts b/apps/cowswap-frontend/src/common/constants/routes.ts index c13ebd8665..91d41b6ddf 100644 --- a/apps/cowswap-frontend/src/common/constants/routes.ts +++ b/apps/cowswap-frontend/src/common/constants/routes.ts @@ -1,4 +1,4 @@ -import { isInjectedWidget } from 'common/utils/isInjectedWidget' +import { isInjectedWidget } from '@cowprotocol/common-utils' export const TRADE_WIDGET_PREFIX = isInjectedWidget() ? '/widget' : '' @@ -31,7 +31,6 @@ export const Routes = { DOCS: '/docs', STATS: '/stats', TWITTER: '/twitter', - KITCHEN_SINK: '/kitchen-sink', } as const export type RoutesKeys = keyof typeof Routes diff --git a/apps/cowswap-frontend/src/common/containers/ImportTokenModal/index.tsx b/apps/cowswap-frontend/src/common/containers/ImportTokenModal/index.tsx index ed8254fd3d..b3d32f64fc 100644 --- a/apps/cowswap-frontend/src/common/containers/ImportTokenModal/index.tsx +++ b/apps/cowswap-frontend/src/common/containers/ImportTokenModal/index.tsx @@ -1,22 +1,21 @@ import { useAtomValue } from 'jotai' import { useCallback, useEffect, useMemo, useState } from 'react' +import { TOKEN_SHORTHANDS, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' +import { useDebounce } from '@cowprotocol/common-hooks' +import { isInjectedWidget } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Token } from '@uniswap/sdk-core' import TokenWarningModal from 'legacy/components/TokenWarningModal' -import { TOKEN_SHORTHANDS, WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' import { useSearchInactiveTokenLists } from 'legacy/hooks/Tokens' -import useDebounce from 'legacy/hooks/useDebounce' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { useAddUserToken } from 'legacy/state/user/hooks' import { tokensByAddressAtom, tokensBySymbolAtom } from 'modules/tokensList/state/tokensListAtom' import { useNavigateOnCurrencySelection } from 'modules/trade/hooks/useNavigateOnCurrencySelection' import { useTradeState } from 'modules/trade/hooks/useTradeState' -import { isInjectedWidget } from 'common/utils/isInjectedWidget' - export interface ImportTokenModalProps { chainId: SupportedChainId } diff --git a/apps/cowswap-frontend/src/common/containers/MultipleOrdersCancellationModal/index.tsx b/apps/cowswap-frontend/src/common/containers/MultipleOrdersCancellationModal/index.tsx index 7a3acd8a85..305d779af0 100644 --- a/apps/cowswap-frontend/src/common/containers/MultipleOrdersCancellationModal/index.tsx +++ b/apps/cowswap-frontend/src/common/containers/MultipleOrdersCancellationModal/index.tsx @@ -1,14 +1,14 @@ import { useAtomValue, useSetAtom } from 'jotai' import React, { useCallback, useState } from 'react' -import { ButtonPrimary } from 'legacy/components/Button' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' +import { isRejectRequestProviderError } from '@cowprotocol/common-utils' +import { ButtonPrimary } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' + import { LegacyConfirmationModalContent } from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationModalContent' import { LegacyConfirmationPendingContent } from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent' import { useRequestOrderCancellation } from 'legacy/state/orders/hooks' -import { isRejectRequestProviderError } from 'legacy/utils/misc' - -import { useWalletInfo } from 'modules/wallet' +import { ConfirmOperationType } from 'legacy/state/types' import { ordersToCancelAtom, updateOrdersToCancelAtom } from 'common/hooks/useMultipleOrdersCancellation/state' import { useCancelMultipleOrders } from 'common/hooks/useMultipleOrdersCancellation/useCancelMultipleOrders' diff --git a/apps/cowswap-frontend/src/common/containers/TradeApprove/TradeApproveModal.tsx b/apps/cowswap-frontend/src/common/containers/TradeApprove/TradeApproveModal.tsx index ae8551e5da..da418b2659 100644 --- a/apps/cowswap-frontend/src/common/containers/TradeApprove/TradeApproveModal.tsx +++ b/apps/cowswap-frontend/src/common/containers/TradeApprove/TradeApproveModal.tsx @@ -1,9 +1,10 @@ import { useAtom } from 'jotai' import React from 'react' -import { TransactionConfirmationModal, ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' +import { TokenSymbol } from '@cowprotocol/ui' -import { TokenSymbol } from 'common/pure/TokenSymbol' +import { TransactionConfirmationModal } from 'legacy/components/TransactionConfirmationModal' +import { ConfirmOperationType } from 'legacy/state/types' import { tradeApproveStateAtom } from './tradeApproveStateAtom' diff --git a/apps/cowswap-frontend/src/common/containers/TradeApprove/useTradeApproveCallback.ts b/apps/cowswap-frontend/src/common/containers/TradeApprove/useTradeApproveCallback.ts index 13fc68b5ec..bd0d54c884 100644 --- a/apps/cowswap-frontend/src/common/containers/TradeApprove/useTradeApproveCallback.ts +++ b/apps/cowswap-frontend/src/common/containers/TradeApprove/useTradeApproveCallback.ts @@ -1,12 +1,11 @@ import { useSetAtom } from 'jotai' import { useCallback } from 'react' +import { approvalAnalytics } from '@cowprotocol/analytics' +import { isRejectRequestProviderError } from '@cowprotocol/common-utils' import { TransactionResponse } from '@ethersproject/providers' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { approvalAnalytics } from 'legacy/components/analytics' -import { isRejectRequestProviderError } from 'legacy/utils/misc' - import { useApproveCallback } from 'common/hooks/useApproveCallback' import { useTradeSpenderAddress } from 'common/hooks/useTradeSpenderAddress' diff --git a/apps/cowswap-frontend/src/common/containers/WalletUnsupportedNetworkBanner/index.tsx b/apps/cowswap-frontend/src/common/containers/WalletUnsupportedNetworkBanner/index.tsx index bb55a359df..2adb5e0422 100644 --- a/apps/cowswap-frontend/src/common/containers/WalletUnsupportedNetworkBanner/index.tsx +++ b/apps/cowswap-frontend/src/common/containers/WalletUnsupportedNetworkBanner/index.tsx @@ -1,10 +1,10 @@ +import { getChainInfo } from '@cowprotocol/common-const' +import { ALL_SUPPORTED_CHAIN_IDS } from '@cowprotocol/cow-sdk' + import { Trans } from '@lingui/macro' import { AlertCircle } from 'react-feather' import styled from 'styled-components/macro' -import { getChainInfo } from 'legacy/constants/chainInfo' -import { ALL_SUPPORTED_CHAIN_IDS } from 'legacy/constants/chains' - import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' export const UNSUPPORTED_WALLET_TEXT = ( diff --git a/apps/cowswap-frontend/src/common/containers/ZeroApprovalModal/ZeroApprovalModal.tsx b/apps/cowswap-frontend/src/common/containers/ZeroApprovalModal/ZeroApprovalModal.tsx index 7cce503f84..b8a11da4a5 100644 --- a/apps/cowswap-frontend/src/common/containers/ZeroApprovalModal/ZeroApprovalModal.tsx +++ b/apps/cowswap-frontend/src/common/containers/ZeroApprovalModal/ZeroApprovalModal.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useState } from 'react' -import { useWalletDetails, useWalletDisplayedAddress } from 'modules/wallet' +import { useWalletDetails, useWalletDisplayedAddress } from '@cowprotocol/wallet' import { ConfirmationPendingContent } from 'common/pure/ConfirmationPendingContent' import { CowModal } from 'common/pure/Modal' diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts b/apps/cowswap-frontend/src/common/hooks/useAnalyticsReporter.ts similarity index 86% rename from apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts rename to apps/cowswap-frontend/src/common/hooks/useAnalyticsReporter.ts index 4397c75772..c41f6db6e8 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useAnalyticsReporter.ts +++ b/apps/cowswap-frontend/src/common/hooks/useAnalyticsReporter.ts @@ -1,25 +1,28 @@ import { useEffect } from 'react' +import { + Dimensions, + GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY, + googleAnalytics, + PixelEvent, + sendAllPixels, +} from '@cowprotocol/analytics' +import { usePrevious } from '@cowprotocol/common-hooks' +import { + getConnectionName, + getIsMetaMask, + getWeb3ReactConnection, + useWalletDetails, + useWalletInfo, +} from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import ReactGA from 'react-ga4' import { useLocation } from 'react-router-dom' import { getCLS, getFCP, getFID, getLCP, Metric } from 'web-vitals' -// Mod imports -import usePrevious from 'legacy/hooks/usePrevious' - -import { useWalletDetails, useWalletInfo } from 'modules/wallet' -import { getConnectionName, getIsMetaMask } from 'modules/wallet/api/utils/connection' -import { getWeb3ReactConnection } from 'modules/wallet/web3-react/connection' - import { useGetMarketDimension } from './useGetMarketDimension' -import { googleAnalytics } from '../googleAnalytics' -import { GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY } from '../index' -import { PixelEvent, sendAllPixels } from '../pixel' -import { Dimensions } from '../types' - export function sendTiming(timingCategory: any, timingVar: any, timingValue: any, timingLabel: any) { return googleAnalytics.gaCommandSendTiming(timingCategory, timingVar, timingValue, timingLabel) } diff --git a/apps/cowswap-frontend/src/common/hooks/useApproveCallback.ts b/apps/cowswap-frontend/src/common/hooks/useApproveCallback.ts index 53333ae140..8a279423ac 100644 --- a/apps/cowswap-frontend/src/common/hooks/useApproveCallback.ts +++ b/apps/cowswap-frontend/src/common/hooks/useApproveCallback.ts @@ -1,17 +1,16 @@ import { useCallback } from 'react' -import { Erc20 } from '@cowswap/abis' +import { Erc20 } from '@cowprotocol/abis' +import { useTokenContract } from '@cowprotocol/common-hooks' +import { calculateGasMargin } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { BigNumber } from '@ethersproject/bignumber' import { MaxUint256 } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { APPROVE_GAS_LIMIT_DEFAULT } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' -import { useTokenContract } from 'legacy/hooks/useContract' import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' -import { calculateGasMargin } from 'legacy/utils/calculateGasMargin' - -import { useWalletInfo } from 'modules/wallet' export async function estimateApprove( tokenContract: Erc20, diff --git a/apps/cowswap-frontend/src/common/hooks/useApproveState.ts b/apps/cowswap-frontend/src/common/hooks/useApproveState.ts index 3b9bddf8d2..d2278e88c6 100644 --- a/apps/cowswap-frontend/src/common/hooks/useApproveState.ts +++ b/apps/cowswap-frontend/src/common/hooks/useApproveState.ts @@ -1,19 +1,17 @@ import { useMemo } from 'react' +import { usePrevious } from '@cowprotocol/common-hooks' +import { FractionUtils } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { Nullish } from 'types' -import usePrevious from 'legacy/hooks/usePrevious' +import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' import { useTokenAllowance } from 'legacy/hooks/useTokenAllowance' import { useHasPendingApproval } from 'legacy/state/enhancedTransactions/hooks' -import { useWalletInfo } from 'modules/wallet' - import { useSafeMemo } from 'common/hooks/useSafeMemo' -import { FractionUtils } from 'utils/fractionUtils' - -import { ApprovalState } from '../../legacy/hooks/useApproveCallback/useApproveCallbackMod' function getCurrencyToApprove(amountToApprove: Nullish>): Token | undefined { if (!amountToApprove) return undefined diff --git a/apps/cowswap-frontend/src/common/hooks/useAreThereTokensWithSameSymbol.ts b/apps/cowswap-frontend/src/common/hooks/useAreThereTokensWithSameSymbol.ts index b939c8456f..cbc61ffca8 100644 --- a/apps/cowswap-frontend/src/common/hooks/useAreThereTokensWithSameSymbol.ts +++ b/apps/cowswap-frontend/src/common/hooks/useAreThereTokensWithSameSymbol.ts @@ -1,7 +1,7 @@ import { useAtomValue } from 'jotai' import { useCallback } from 'react' -import { isAddress } from 'legacy/utils' +import { isAddress } from '@cowprotocol/common-utils' import { tokensBySymbolAtom } from 'modules/tokensList/state/tokensListAtom' diff --git a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/index.ts b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/index.ts index 90bd592da4..12945cc6b1 100644 --- a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/index.ts +++ b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/index.ts @@ -2,15 +2,16 @@ import { useSetAtom } from 'jotai' import { useResetAtom } from 'jotai/utils' import { useCallback } from 'react' +import { calculateGasMargin } from '@cowprotocol/common-utils' +import { useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' + import { useCloseModal, useOpenModal } from 'legacy/state/application/hooks' import { ApplicationModal } from 'legacy/state/application/reducer' import { useGasPrices } from 'legacy/state/gas/hooks' import { Order, OrderStatus } from 'legacy/state/orders/actions' -import { calculateGasMargin } from 'legacy/utils/calculateGasMargin' import { getIsEthFlowOrder } from 'modules/swap/containers/EthFlowStepper' import { getSwapErrorMessage } from 'modules/trade/utils/swapErrorHelper' -import { useWalletDetails, useWalletInfo } from 'modules/wallet' import { useGetOnChainCancellation } from 'common/hooks/useCancelOrder/useGetOnChainCancellation' import { isOrderCancellable } from 'common/utils/isOrderCancellable' diff --git a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/onChainCancellation.ts b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/onChainCancellation.ts index 898b11501a..b1d2b6c910 100644 --- a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/onChainCancellation.ts +++ b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/onChainCancellation.ts @@ -1,8 +1,8 @@ -import { GPv2Settlement, CoWSwapEthFlow } from '@cowswap/abis' +import { GPv2Settlement, CoWSwapEthFlow } from '@cowprotocol/abis' +import { calculateGasMargin } from '@cowprotocol/common-utils' import { BigNumber } from '@ethersproject/bignumber' import { Order } from 'legacy/state/orders/actions' -import { calculateGasMargin } from 'legacy/utils/calculateGasMargin' import { logTradeFlowError } from 'modules/trade/utils/logger' diff --git a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useGetOnChainCancellation.ts b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useGetOnChainCancellation.ts index e96ebcb006..aeb2a9ee56 100644 --- a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useGetOnChainCancellation.ts +++ b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useGetOnChainCancellation.ts @@ -1,6 +1,7 @@ import { useCallback } from 'react' -import { useEthFlowContract, useGP2SettlementContract } from 'legacy/hooks/useContract' +import { useEthFlowContract, useGP2SettlementContract } from '@cowprotocol/common-hooks' + import { Order } from 'legacy/state/orders/actions' import { getIsEthFlowOrder } from 'modules/swap/containers/EthFlowStepper' diff --git a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useOffChainCancelOrder.ts b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useOffChainCancelOrder.ts index a9062a06fe..fa52b7e520 100644 --- a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useOffChainCancelOrder.ts +++ b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useOffChainCancelOrder.ts @@ -1,13 +1,12 @@ import { useCallback } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { Order } from 'legacy/state/orders/actions' import { useRequestOrderCancellation } from 'legacy/state/orders/hooks' import { sendOrderCancellation } from 'legacy/utils/trade' -import { useWalletInfo } from 'modules/wallet' - export function useOffChainCancelOrder() { const { provider } = useWeb3React() const { account, chainId } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.test.ts b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.test.ts index d100e08744..b7680f9e67 100644 --- a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.test.ts +++ b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.test.ts @@ -1,16 +1,14 @@ +import { COW, NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' +import { useEthFlowContract, useGP2SettlementContract } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' import { BigNumber } from '@ethersproject/bignumber' import { renderHook } from '@testing-library/react-hooks' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' -import { COW } from 'legacy/constants/tokens' -import { useEthFlowContract, useGP2SettlementContract } from 'legacy/hooks/useContract' import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' import { Order } from 'legacy/state/orders/actions' import { useRequestOrderCancellation, useSetOrderCancellationHash } from 'legacy/state/orders/hooks' -import { useWalletInfo } from 'modules/wallet' - import { useSendOnChainCancellation } from './useSendOnChainCancellation' import { WithMockedWeb3 } from '../../../test-utils' @@ -20,15 +18,21 @@ const settlementCancellationTxHash = '0xcfwj23g4fwe111' const ethFlowCancellationTxHash = '0xcfwj23g4fwe222' jest.mock('legacy/state/orders/hooks') -jest.mock('modules/wallet', () => { +jest.mock('@cowprotocol/wallet', () => { return { - ...jest.requireActual('modules/wallet'), + ...jest.requireActual('@cowprotocol/wallet'), useWalletInfo: jest.fn().mockReturnValue({ chainId }), } }) +jest.mock('@cowprotocol/common-hooks', () => { + return { + ...jest.requireActual('@cowprotocol/common-hooks'), + useEthFlowContract: jest.fn(), + useGP2SettlementContract: jest.fn(), + } +}) jest.mock('legacy/state/enhancedTransactions/hooks') -jest.mock('legacy/hooks/useContract') -jest.mock('legacy/components/analytics/hooks/useAnalyticsReporter.ts') +jest.mock('common/hooks/useAnalyticsReporter') const orderMock = { id: 'xx1', diff --git a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.ts b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.ts index 0ef191e21e..7167570bef 100644 --- a/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.ts +++ b/apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.ts @@ -1,12 +1,13 @@ import { useCallback } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' + import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' import { Order } from 'legacy/state/orders/actions' import { useRequestOrderCancellation, useSetOrderCancellationHash } from 'legacy/state/orders/hooks' import { getIsEthFlowOrder } from 'modules/swap/containers/EthFlowStepper' import { useSetPartOrderCancelling } from 'modules/twap/hooks/useSetPartOrderCancelling' -import { useWalletInfo } from 'modules/wallet' import { CancelledOrderInfo } from './onChainCancellation' import { useGetOnChainCancellation } from './useGetOnChainCancellation' diff --git a/apps/cowswap-frontend/src/common/hooks/useConfirmPriceImpactWithoutFee.ts b/apps/cowswap-frontend/src/common/hooks/useConfirmPriceImpactWithoutFee.ts index d018aa2ad7..e08532f148 100644 --- a/apps/cowswap-frontend/src/common/hooks/useConfirmPriceImpactWithoutFee.ts +++ b/apps/cowswap-frontend/src/common/hooks/useConfirmPriceImpactWithoutFee.ts @@ -1,9 +1,8 @@ import { useCallback, useState } from 'react' +import { ALLOWED_PRICE_IMPACT_HIGH, PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN } from '@cowprotocol/common-const' import { Percent } from '@uniswap/sdk-core' -import { ALLOWED_PRICE_IMPACT_HIGH, PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN } from 'legacy/constants/misc' - import { useConfirmationRequest } from 'common/hooks/useConfirmationRequest' function getDescription(priceImpactWithoutFee: Percent) { diff --git a/apps/cowswap-frontend/src/common/hooks/useExternalTokenSearch.ts b/apps/cowswap-frontend/src/common/hooks/useExternalTokenSearch.ts index 80062b15cc..6a28ceb4e0 100644 --- a/apps/cowswap-frontend/src/common/hooks/useExternalTokenSearch.ts +++ b/apps/cowswap-frontend/src/common/hooks/useExternalTokenSearch.ts @@ -1,9 +1,8 @@ import { useMemo } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' -import { useWalletInfo } from 'modules/wallet' - import { useProxyTokens } from 'api/proxy' export function useExternalTokenSearch(query: string, existingTokens: Map): Token[] { diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/hooks/useGetMarketDimension.ts b/apps/cowswap-frontend/src/common/hooks/useGetMarketDimension.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/hooks/useGetMarketDimension.ts rename to apps/cowswap-frontend/src/common/hooks/useGetMarketDimension.ts diff --git a/apps/cowswap-frontend/src/common/hooks/useGetSurplusFiatValue.ts b/apps/cowswap-frontend/src/common/hooks/useGetSurplusFiatValue.ts index 65c8f83f18..8ef03b1dfe 100644 --- a/apps/cowswap-frontend/src/common/hooks/useGetSurplusFiatValue.ts +++ b/apps/cowswap-frontend/src/common/hooks/useGetSurplusFiatValue.ts @@ -1,10 +1,10 @@ import { useMemo } from 'react' +import { MIN_FIAT_SURPLUS_VALUE, MIN_FIAT_SURPLUS_VALUE_MODAL, MIN_SURPLUS_UNITS } from '@cowprotocol/common-const' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { MIN_FIAT_SURPLUS_VALUE, MIN_FIAT_SURPLUS_VALUE_MODAL, MIN_SURPLUS_UNITS } from 'legacy/constants' import { Order } from 'legacy/state/orders/actions' import { useUsdAmount } from 'modules/usdAmount' diff --git a/apps/cowswap-frontend/src/common/hooks/useIsSmartContractWallet.ts b/apps/cowswap-frontend/src/common/hooks/useIsSmartContractWallet.ts deleted file mode 100644 index c55ef81dad..0000000000 --- a/apps/cowswap-frontend/src/common/hooks/useIsSmartContractWallet.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { useState, useEffect } from 'react' - -import { useWeb3React } from '@web3-react/core' - -import useSWR from 'swr' - -import useIsAmbireWallet from 'legacy/hooks/useIsAmbireWallet' -import useIsArgentWallet from 'legacy/hooks/useIsArgentWallet' - -import { useWalletInfo } from 'modules/wallet' - -function useCheckIsSmartContract(): boolean | undefined { - const { provider } = useWeb3React() - const { account } = useWalletInfo() - - const { data } = useSWR(['isSmartContract', account, provider], async () => { - if (!account || !provider) { - return false - } - - try { - const code = await provider.getCode(account) - return code !== '0x' - } catch (e: any) { - console.debug(`checkIsSmartContractWallet: failed to check address ${account}`, e.message) - return false - } - }) - - return data -} - -export function useIsSmartContractWallet(): boolean { - const [isSmartContractWallet, setIsSmartContractWallet] = useState(false) - - const { account } = useWalletInfo() - - const isArgentWallet = useIsArgentWallet() - const isSmartContract = useCheckIsSmartContract() - const isAmbireWallet = useIsAmbireWallet() - - useEffect(() => { - if (!account) { - setIsSmartContractWallet(false) - return - } - - if (isAmbireWallet || isArgentWallet || isSmartContract) { - setIsSmartContractWallet(true) - } - }, [account, isAmbireWallet, isArgentWallet, isSmartContract]) - - return isSmartContractWallet -} diff --git a/apps/cowswap-frontend/src/common/hooks/useLegacySetChainIdToUrl.ts b/apps/cowswap-frontend/src/common/hooks/useLegacySetChainIdToUrl.ts index bec8b623eb..d2cbbd1f67 100644 --- a/apps/cowswap-frontend/src/common/hooks/useLegacySetChainIdToUrl.ts +++ b/apps/cowswap-frontend/src/common/hooks/useLegacySetChainIdToUrl.ts @@ -1,11 +1,10 @@ import { useCallback } from 'react' +import { getChainInfo } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { useLocation, useNavigate } from 'react-router-dom' -import { getChainInfo } from 'legacy/constants/chainInfo' - import { useTradeTypeInfo } from 'modules/trade' /** diff --git a/apps/cowswap-frontend/src/common/hooks/useMultipleOrdersCancellation/useCancelMultipleOrders.ts b/apps/cowswap-frontend/src/common/hooks/useMultipleOrdersCancellation/useCancelMultipleOrders.ts index 20a14be3d1..bb08231d0b 100644 --- a/apps/cowswap-frontend/src/common/hooks/useMultipleOrdersCancellation/useCancelMultipleOrders.ts +++ b/apps/cowswap-frontend/src/common/hooks/useMultipleOrdersCancellation/useCancelMultipleOrders.ts @@ -1,12 +1,11 @@ import { useCallback } from 'react' import { OrderSigningUtils } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { orderBookApi } from 'cowSdk' -import { useWalletInfo } from 'modules/wallet' - import { CancellableOrder, isOrderCancellable } from 'common/utils/isOrderCancellable' export function useCancelMultipleOrders(): (orders: CancellableOrder[]) => Promise { diff --git a/apps/cowswap-frontend/src/common/hooks/useNeedsApproval.ts b/apps/cowswap-frontend/src/common/hooks/useNeedsApproval.ts index 6f4622707d..d3478d41f1 100644 --- a/apps/cowswap-frontend/src/common/hooks/useNeedsApproval.ts +++ b/apps/cowswap-frontend/src/common/hooks/useNeedsApproval.ts @@ -1,12 +1,12 @@ +import { isEnoughAmount } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' import { useBalancesAndAllowances } from 'modules/tokens' -import { useWalletInfo } from 'modules/wallet' import { useTradeSpenderAddress } from 'common/hooks/useTradeSpenderAddress' -import { isEnoughAmount } from 'utils/isEnoughAmount' /** * Hook to check if a token needs approval diff --git a/apps/cowswap-frontend/src/common/hooks/useNeedsZeroApproval.ts b/apps/cowswap-frontend/src/common/hooks/useNeedsZeroApproval.ts index ad4e917180..dbc96cf941 100644 --- a/apps/cowswap-frontend/src/common/hooks/useNeedsZeroApproval.ts +++ b/apps/cowswap-frontend/src/common/hooks/useNeedsZeroApproval.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' -import { Erc20 } from '@cowswap/abis' +import { Erc20 } from '@cowprotocol/abis' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { Nullish } from 'types' diff --git a/apps/cowswap-frontend/src/common/hooks/useOnSelectNetwork.ts b/apps/cowswap-frontend/src/common/hooks/useOnSelectNetwork.ts index f09bec350c..a77499dc6a 100644 --- a/apps/cowswap-frontend/src/common/hooks/useOnSelectNetwork.ts +++ b/apps/cowswap-frontend/src/common/hooks/useOnSelectNetwork.ts @@ -1,6 +1,8 @@ import { useCallback } from 'react' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { getWeb3ReactConnection } from '@cowprotocol/wallet' +import { switchChain } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { useAddPopup, useCloseModal } from 'legacy/state/application/hooks' @@ -8,9 +10,6 @@ import { ApplicationModal } from 'legacy/state/application/reducer' import { updateConnectionError } from 'legacy/state/connection/reducer' import { useAppDispatch } from 'legacy/state/hooks' -import { getWeb3ReactConnection } from 'modules/wallet/web3-react/connection' -import { switchChain } from 'modules/wallet/web3-react/hooks/switchChain' - import { useLegacySetChainIdToUrl } from './useLegacySetChainIdToUrl' export function useOnSelectNetwork(): (chainId: SupportedChainId, skipClose?: boolean) => Promise { diff --git a/apps/cowswap-frontend/src/common/hooks/usePrice.ts b/apps/cowswap-frontend/src/common/hooks/usePrice.ts index 6e3b9db800..c5f6118763 100644 --- a/apps/cowswap-frontend/src/common/hooks/usePrice.ts +++ b/apps/cowswap-frontend/src/common/hooks/usePrice.ts @@ -1,9 +1,8 @@ +import { buildPriceFromCurrencyAmounts } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Price } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { buildPriceFromCurrencyAmounts } from 'modules/utils/orderUtils/buildPriceFromCurrencyAmounts' - import { useSafeMemo } from 'common/hooks/useSafeMemo' export function usePrice( diff --git a/apps/cowswap-frontend/src/common/hooks/useRateInfoParams.ts b/apps/cowswap-frontend/src/common/hooks/useRateInfoParams.ts index 11a28941c4..de4c03d2ac 100644 --- a/apps/cowswap-frontend/src/common/hooks/useRateInfoParams.ts +++ b/apps/cowswap-frontend/src/common/hooks/useRateInfoParams.ts @@ -1,16 +1,16 @@ import { useCallback } from 'react' +import { tryParseCurrencyAmount } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' import { useTradeUsdAmounts } from 'modules/usdAmount' -import { useWalletInfo } from 'modules/wallet' import { usePrice } from 'common/hooks/usePrice' import { useSafeMemoObject } from 'common/hooks/useSafeMemo' import { RateInfoParams } from 'common/pure/RateInfo' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' export function useRateInfoParams( inputCurrencyAmount: Nullish>, diff --git a/apps/cowswap-frontend/src/api/gnosisSafe/hooks/useSafeApiKit.ts b/apps/cowswap-frontend/src/common/hooks/useSafeApiKit.ts similarity index 83% rename from apps/cowswap-frontend/src/api/gnosisSafe/hooks/useSafeApiKit.ts rename to apps/cowswap-frontend/src/common/hooks/useSafeApiKit.ts index ac936afa20..90bd897a9c 100644 --- a/apps/cowswap-frontend/src/api/gnosisSafe/hooks/useSafeApiKit.ts +++ b/apps/cowswap-frontend/src/common/hooks/useSafeApiKit.ts @@ -1,12 +1,10 @@ import { useEffect, useState } from 'react' +import { createSafeApiKitInstance } from '@cowprotocol/core' +import { useIsSafeWallet, useWalletInfo } from '@cowprotocol/wallet' import SafeApiKit from '@safe-global/api-kit' import { useWeb3React } from '@web3-react/core' -import { useIsSafeWallet, useWalletInfo } from 'modules/wallet' - -import { createSafeApiKitInstance } from 'api/gnosisSafe' - export function useSafeApiKit(): SafeApiKit | null { const [safeApiClient, setSafeApiClient] = useState(null) const { chainId } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/shouldZeroApprove.ts b/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/shouldZeroApprove.ts index eb36850036..545796d95e 100644 --- a/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/shouldZeroApprove.ts +++ b/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/shouldZeroApprove.ts @@ -1,4 +1,4 @@ -import { Erc20 } from '@cowswap/abis' +import { Erc20 } from '@cowprotocol/abis' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' diff --git a/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/useShouldZeroApprove.ts b/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/useShouldZeroApprove.ts index d05993c1b6..0246824844 100644 --- a/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/useShouldZeroApprove.ts +++ b/apps/cowswap-frontend/src/common/hooks/useShouldZeroApprove/useShouldZeroApprove.ts @@ -1,11 +1,10 @@ import { useEffect, useState } from 'react' +import { useTokenContract } from '@cowprotocol/common-hooks' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { useTokenContract } from 'legacy/hooks/useContract' - import { useApprovalStateForSpender } from 'lib/hooks/useApproval' import { shouldZeroApprove as shouldZeroApproveFn } from './shouldZeroApprove' diff --git a/apps/cowswap-frontend/src/common/hooks/useTokenBySymbolOrAddress.ts b/apps/cowswap-frontend/src/common/hooks/useTokenBySymbolOrAddress.ts index 677cadec7c..5bc0025f73 100644 --- a/apps/cowswap-frontend/src/common/hooks/useTokenBySymbolOrAddress.ts +++ b/apps/cowswap-frontend/src/common/hooks/useTokenBySymbolOrAddress.ts @@ -1,6 +1,7 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' +import { doesTokenMatchSymbolOrAddress } from '@cowprotocol/common-utils' import { NativeCurrency, Token } from '@uniswap/sdk-core' import { useFavouriteTokens } from 'legacy/state/user/hooks' @@ -8,7 +9,6 @@ import { useFavouriteTokens } from 'legacy/state/user/hooks' import { tokensByAddressAtom, tokensBySymbolAtom } from 'modules/tokensList/state/tokensListAtom' import useNativeCurrency from 'lib/hooks/useNativeCurrency' -import { doesTokenMatchSymbolOrAddress } from 'utils/doesTokenMatchSymbolOrAddress' export function useTokenBySymbolOrAddress(symbolOrAddress?: string | null): Token | NativeCurrency | null { const tokensByAddress = useAtomValue(tokensByAddressAtom) diff --git a/apps/cowswap-frontend/src/common/hooks/useTradeSpenderAddress.ts b/apps/cowswap-frontend/src/common/hooks/useTradeSpenderAddress.ts index dc8ecc1af2..2115b5b5f3 100644 --- a/apps/cowswap-frontend/src/common/hooks/useTradeSpenderAddress.ts +++ b/apps/cowswap-frontend/src/common/hooks/useTradeSpenderAddress.ts @@ -1,8 +1,7 @@ import { useMemo } from 'react' -import { GP_VAULT_RELAYER } from 'legacy/constants' - -import { useWalletInfo } from 'modules/wallet' +import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' export function useTradeSpenderAddress(): string | undefined { const { chainId } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/common/hooks/useWalletStatusIcon.ts b/apps/cowswap-frontend/src/common/hooks/useWalletStatusIcon.ts index de738b1d5c..8d246eb0f2 100644 --- a/apps/cowswap-frontend/src/common/hooks/useWalletStatusIcon.ts +++ b/apps/cowswap-frontend/src/common/hooks/useWalletStatusIcon.ts @@ -1,7 +1,7 @@ +import { useWalletDetails } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { getStatusIcon } from 'modules/account/containers/AccountDetails' -import { useWalletDetails } from 'modules/wallet' export function useWalletStatusIcon(): JSX.Element | null { const walletDetails = useWalletDetails() diff --git a/apps/cowswap-frontend/src/common/hooks/useZeroApprove.ts b/apps/cowswap-frontend/src/common/hooks/useZeroApprove.ts index 7380cda8a4..48ccc0ece2 100644 --- a/apps/cowswap-frontend/src/common/hooks/useZeroApprove.ts +++ b/apps/cowswap-frontend/src/common/hooks/useZeroApprove.ts @@ -1,19 +1,17 @@ import { useSetAtom } from 'jotai' import { useCallback } from 'react' +import { useIsSafeWallet, walletConnectConnection } from '@cowprotocol/wallet' import SafeApiKit from '@safe-global/api-kit' import { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { useIsActiveWallet } from 'legacy/hooks/useIsActiveWallet' -import { useIsSafeWallet } from 'modules/wallet' -import { walletConnectConnection } from 'modules/wallet/web3-react/connection/walletConnect' - -import { useSafeApiKit } from 'api/gnosisSafe/hooks/useSafeApiKit' import { pollUntil } from 'common/utils/pollUntil' import { useApproveCallback } from './useApproveCallback' +import { useSafeApiKit } from './useSafeApiKit' import { useTradeSpenderAddress } from './useTradeSpenderAddress' import { zeroApprovalState } from '../state/useZeroApprovalState' diff --git a/apps/cowswap-frontend/src/common/pure/AnimatedConfirmation/index.tsx b/apps/cowswap-frontend/src/common/pure/AnimatedConfirmation/index.tsx index 038e8339d3..5116334866 100644 --- a/apps/cowswap-frontend/src/common/pure/AnimatedConfirmation/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/AnimatedConfirmation/index.tsx @@ -1,6 +1,6 @@ -import styled, { keyframes } from 'styled-components/macro' +import { useTheme } from '@cowprotocol/common-hooks' -import useTheme from 'legacy/hooks/useTheme' +import styled, { keyframes } from 'styled-components/macro' const Wrapper = styled.div` height: 90px; diff --git a/apps/cowswap-frontend/src/common/pure/ApproveButton/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/ApproveButton/index.cosmos.tsx index c946e29f17..90b6b42274 100644 --- a/apps/cowswap-frontend/src/common/pure/ApproveButton/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/common/pure/ApproveButton/index.cosmos.tsx @@ -1,9 +1,9 @@ +import { COW, GNO } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { DemoContainer } from 'cosmos.decorator' import { useSelect } from 'react-cosmos/client' -import { COW, GNO } from 'legacy/constants/tokens' import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' import { ApproveButton } from '.' diff --git a/apps/cowswap-frontend/src/common/pure/ApproveButton/index.tsx b/apps/cowswap-frontend/src/common/pure/ApproveButton/index.tsx index fd4adbac7c..7803251226 100644 --- a/apps/cowswap-frontend/src/common/pure/ApproveButton/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/ApproveButton/index.tsx @@ -1,20 +1,16 @@ import { useContext, useMemo } from 'react' +import { ButtonSize, Loader, TokenSymbol, AutoRow, ButtonConfirmed } from '@cowprotocol/ui' +import { MouseoverTooltip } from '@cowprotocol/ui' import { Currency } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { CheckCircle, HelpCircle } from 'react-feather' import { ThemeContext } from 'styled-components/macro' -import { ButtonConfirmed } from 'legacy/components/Button' -import Loader from 'legacy/components/Loader' -import { AutoRow } from 'legacy/components/Row' -import { MouseoverTooltip } from 'legacy/components/Tooltip' import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' -import { ButtonSize } from 'legacy/theme/enum' import { CurrencyLogo } from 'common/pure/CurrencyLogo' -import { TokenSymbol } from 'common/pure/TokenSymbol' export interface ApproveButtonProps { currency: Currency | undefined | null diff --git a/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx b/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx index 5db6020bcf..47f7520166 100644 --- a/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx +++ b/apps/cowswap-frontend/src/common/pure/CancellationModal/RequestCancellationModal.tsx @@ -1,5 +1,6 @@ import React, { useCallback, useState } from 'react' +import { TokenAmount, ButtonPrimary } from '@cowprotocol/ui' import type { BigNumber } from '@ethersproject/bignumber' import { CurrencyAmount, NativeCurrency } from '@uniswap/sdk-core' @@ -7,7 +8,6 @@ import { ArrowRight, ArrowLeft } from 'react-feather' import { NavHashLink } from 'react-router-hash-link' import styled from 'styled-components/macro' -import { ButtonPrimary } from 'legacy/components/Button' import NotificationBanner from 'legacy/components/NotificationBanner' import { LegacyConfirmationModalContent } from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationModalContent' import { LinkStyledButton } from 'legacy/theme' @@ -15,7 +15,6 @@ import { LinkStyledButton } from 'legacy/theme' import { Routes } from 'common/constants/routes' import { UI } from 'common/constants/theme' import { CancellationType } from 'common/hooks/useCancelOrder/state' -import { TokenAmount } from 'common/pure/TokenAmount' export type RequestCancellationModalProps = { summary?: string diff --git a/apps/cowswap-frontend/src/common/pure/CancellationModal/index.tsx b/apps/cowswap-frontend/src/common/pure/CancellationModal/index.tsx index c2782961e3..ea5d19324a 100644 --- a/apps/cowswap-frontend/src/common/pure/CancellationModal/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/CancellationModal/index.tsx @@ -1,8 +1,9 @@ import { useMemo } from 'react' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' +import { shortenOrderId } from '@cowprotocol/common-utils' + import { LegacyConfirmationPendingContent } from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent' -import { shortenOrderId } from 'legacy/utils' +import { ConfirmOperationType } from 'legacy/state/types' import { CancellationModalContext } from 'common/hooks/useCancelOrder/state' import { CowModal as Modal } from 'common/pure/Modal' diff --git a/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/ConfirmationPendingContent.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/ConfirmationPendingContent.cosmos.tsx index c5ff82c2ad..89f5958975 100644 --- a/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/ConfirmationPendingContent.cosmos.tsx +++ b/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/ConfirmationPendingContent.cosmos.tsx @@ -1,4 +1,4 @@ -import { Identicon } from 'modules/wallet' +import { Identicon } from '@cowprotocol/wallet' import { ConfirmationPendingContent } from './ConfirmationPendingContent' diff --git a/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/styled.tsx b/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/styled.tsx index 2e725a3030..c9640e8c95 100644 --- a/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/styled.tsx +++ b/apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/styled.tsx @@ -1,9 +1,11 @@ +import { RowBetween } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' + import { transparentize } from 'polished' import { Link } from 'react-router-dom' import styled, { css } from 'styled-components/macro' -import { RowBetween } from 'legacy/components/Row' -import { CloseIcon, ExternalLink } from 'legacy/theme' +import { CloseIcon } from 'legacy/theme' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/common/pure/ConfirmedButton/ConfirmedButton.tsx b/apps/cowswap-frontend/src/common/pure/ConfirmedButton/ConfirmedButton.tsx index cd4e60769a..aed8a57be4 100644 --- a/apps/cowswap-frontend/src/common/pure/ConfirmedButton/ConfirmedButton.tsx +++ b/apps/cowswap-frontend/src/common/pure/ConfirmedButton/ConfirmedButton.tsx @@ -1,8 +1,8 @@ import { ChangeEventHandler, KeyboardEventHandler, ReactNode, useCallback, useState } from 'react' -import styled from 'styled-components/macro' +import { ButtonError } from '@cowprotocol/ui' -import { ButtonError } from 'legacy/components/Button' +import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/common/pure/CowSwapSafeAppLink/index.tsx b/apps/cowswap-frontend/src/common/pure/CowSwapSafeAppLink/index.tsx index 973db4b64d..3b6ca0db35 100644 --- a/apps/cowswap-frontend/src/common/pure/CowSwapSafeAppLink/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/CowSwapSafeAppLink/index.tsx @@ -1,4 +1,4 @@ -import { ExternalLink } from 'legacy/theme' +import { ExternalLink } from '@cowprotocol/ui' import { SAFE_COW_APP_LINK } from 'common/constants/common' diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyAmountPreview/index.tsx b/apps/cowswap-frontend/src/common/pure/CurrencyAmountPreview/index.tsx index 2ad6e613c7..3d110c6844 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyAmountPreview/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencyAmountPreview/index.tsx @@ -1,3 +1,4 @@ +import { TokenAmount } from '@cowprotocol/ui' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' @@ -7,7 +8,6 @@ import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { CurrencySelectButton } from 'common/pure/CurrencySelectButton' import { FiatValue } from 'common/pure/FiatValue' -import { TokenAmount } from 'common/pure/TokenAmount' import * as styledEl from '../CurrencyInputPanel/styled' diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/index.tsx b/apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/index.tsx index 471fad4878..abbe36bc15 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencyArrowSeparator/index.tsx @@ -1,6 +1,6 @@ import React from 'react' -import loadingCowWebp from 'legacy/assets/cow-swap/cow-load.webp' +import loadingCowWebp from '@cowprotocol/assets/cow-swap/cow-load.webp' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx index 74e5d38d3c..f38f8fafcb 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx @@ -1,24 +1,24 @@ import React, { useCallback, useEffect, useState } from 'react' +import { setMaxSellTokensAnalytics } from '@cowprotocol/analytics' +import { formatInputAmount } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { TokenAmount } from '@cowprotocol/ui' +import { MouseoverTooltip } from '@cowprotocol/ui' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' -import { setMaxSellTokensAnalytics } from 'legacy/components/analytics' import CurrencySearchModal from 'legacy/components/SearchModal/CurrencySearchModal' -import { MouseoverTooltip } from 'legacy/components/Tooltip' import { BalanceAndSubsidy } from 'legacy/hooks/useCowBalanceAndSubsidy' import { PriceImpact } from 'legacy/hooks/usePriceImpact' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { ReceiveAmount } from 'modules/swap/pure/ReceiveAmount' import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types' import { CurrencySelectButton } from 'common/pure/CurrencySelectButton' import { FiatValue } from 'common/pure/FiatValue' -import { TokenAmount } from 'common/pure/TokenAmount' -import { formatInputAmount } from 'utils/amountFormat' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/defaultCurrencyInputProps.ts b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/defaultCurrencyInputProps.ts index 8f3cc64b58..4729bd4f10 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/defaultCurrencyInputProps.ts +++ b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/defaultCurrencyInputProps.ts @@ -1,9 +1,9 @@ +import { COW } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount, Percent } from '@uniswap/sdk-core' -import { COW } from 'legacy/constants/tokens' import { PriceImpact } from 'legacy/hooks/usePriceImpact' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { CurrencyInputPanelProps } from 'common/pure/CurrencyInputPanel/index' diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/index.cosmos.tsx index 35211285a6..fbe8c02dd5 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/index.cosmos.tsx @@ -1,12 +1,12 @@ +import { COW } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount, Percent } from '@uniswap/sdk-core' import { DemoContainer } from 'cosmos.decorator' import { useSelect, useValue } from 'react-cosmos/client' -import { COW } from 'legacy/constants/tokens' import { PriceImpact } from 'legacy/hooks/usePriceImpact' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { CurrencyInputPanel, CurrencyInputPanelProps } from './CurrencyInputPanel' import { defaultCurrencyInputPanelProps } from './defaultCurrencyInputProps' diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/styled.tsx b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/styled.tsx index b1f0e394a7..0df08c487e 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/styled.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/styled.tsx @@ -1,11 +1,11 @@ +import { TokenAmount, loadingOpacityMixin } from '@cowprotocol/ui' + import { transparentize } from 'polished' import styled from 'styled-components/macro' -import { loadingOpacityMixin } from 'legacy/components/Loader/styled' import Input from 'legacy/components/NumericalInput' import { UI } from 'common/constants/theme' -import { TokenAmount } from 'common/pure/TokenAmount' export const OuterWrapper = styled.div` max-width: 100%; diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/types.ts b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/types.ts index 41e89acbd1..1f4380dddd 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/types.ts +++ b/apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/types.ts @@ -1,6 +1,6 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { ReceiveAmountInfo } from 'modules/swap/helpers/tradeReceiveAmount' diff --git a/apps/cowswap-frontend/src/common/pure/CurrencyLogo/hooks/useCurrencyLogoURIs.ts b/apps/cowswap-frontend/src/common/pure/CurrencyLogo/hooks/useCurrencyLogoURIs.ts index 5bd9aa3aa5..17040c8aae 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencyLogo/hooks/useCurrencyLogoURIs.ts +++ b/apps/cowswap-frontend/src/common/pure/CurrencyLogo/hooks/useCurrencyLogoURIs.ts @@ -1,13 +1,11 @@ +import XDaiLogo from '@cowprotocol/assets/cow-swap/xdai.png' +import EthereumLogo from '@cowprotocol/assets/images/ethereum-logo.png' +import { NATIVE_CURRENCY_BUY_ADDRESS, ADDRESS_IMAGE_OVERRIDE } from '@cowprotocol/common-const' +import { uriToHttp } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency } from '@uniswap/sdk-core' -import XDaiLogo from 'legacy/assets/cow-swap/xdai.png' -import EthereumLogo from 'legacy/assets/images/ethereum-logo.png' -import { NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants' -import { ADDRESS_IMAGE_OVERRIDE } from 'legacy/constants/tokens' - import { useProxyTokenLogo } from 'api/proxy' -import uriToHttp from 'lib/utils/uriToHttp' type Network = 'ethereum' | 'xdai' diff --git a/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.cosmos.tsx index 2361ebdedd..738139d32a 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.cosmos.tsx @@ -1,9 +1,8 @@ +import { COW, GNO } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { useSelect } from 'react-cosmos/client' -import { COW, GNO } from 'legacy/constants/tokens' - import { CurrencySelectButton, CurrencySelectButtonProps } from 'common/pure/CurrencySelectButton/index' const COW_TOKEN = COW[SupportedChainId.MAINNET] diff --git a/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.tsx b/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.tsx index 444bac31ad..aba96807d2 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/index.tsx @@ -1,10 +1,10 @@ +import { TokenSymbol } from '@cowprotocol/ui' import { Currency } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { Nullish } from 'types' import { CurrencyLogo } from 'common/pure/CurrencyLogo' -import { TokenSymbol } from 'common/pure/TokenSymbol' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/styled.tsx b/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/styled.tsx index d6017e31d6..f03be68b0a 100644 --- a/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/styled.tsx +++ b/apps/cowswap-frontend/src/common/pure/CurrencySelectButton/styled.tsx @@ -1,8 +1,8 @@ +import { ReactComponent as DropDown } from '@cowprotocol/assets/images/dropdown.svg' + import { lighten, transparentize } from 'polished' import styled from 'styled-components/macro' -import { ReactComponent as DropDown } from 'legacy/assets/images/dropdown.svg' - export const CurrencySelectWrapper = styled.button<{ isLoading: boolean; $stubbed: boolean; readonlyMode: boolean }>` display: flex; justify-content: space-between; diff --git a/apps/cowswap-frontend/src/common/pure/ExecutedSummary/styled.ts b/apps/cowswap-frontend/src/common/pure/ExecutedSummary/styled.ts index f0e05b64de..af3fa38057 100644 --- a/apps/cowswap-frontend/src/common/pure/ExecutedSummary/styled.ts +++ b/apps/cowswap-frontend/src/common/pure/ExecutedSummary/styled.ts @@ -1,8 +1,6 @@ -import styled from 'styled-components/macro' - -import { TokenAmount } from 'common/pure/TokenAmount' +import { TokenAmount, FiatAmount } from '@cowprotocol/ui' -import { FiatAmount } from '../FiatAmount' +import styled from 'styled-components/macro' export const SummaryWrapper = styled.div` font-size: 1rem; diff --git a/apps/cowswap-frontend/src/common/pure/ExecutionPrice/hooks/useExecutionPriceFiat.ts b/apps/cowswap-frontend/src/common/pure/ExecutionPrice/hooks/useExecutionPriceFiat.ts index 9cf9119ffa..a5b66c3f85 100644 --- a/apps/cowswap-frontend/src/common/pure/ExecutionPrice/hooks/useExecutionPriceFiat.ts +++ b/apps/cowswap-frontend/src/common/pure/ExecutionPrice/hooks/useExecutionPriceFiat.ts @@ -1,9 +1,8 @@ +import { rawToTokenAmount } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Price } from '@uniswap/sdk-core' import { useUsdAmount } from 'modules/usdAmount' -import { rawToTokenAmount } from 'utils/rawToTokenAmount' - function getPriceQuoteAmount(price: Price, isInverted: boolean): CurrencyAmount { const executionPrice = isInverted ? price.invert() : price diff --git a/apps/cowswap-frontend/src/common/pure/ExecutionPrice/index.tsx b/apps/cowswap-frontend/src/common/pure/ExecutionPrice/index.tsx index d083c5cddf..b3ff29c995 100644 --- a/apps/cowswap-frontend/src/common/pure/ExecutionPrice/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/ExecutionPrice/index.tsx @@ -1,9 +1,7 @@ +import { tryParseCurrencyAmount } from '@cowprotocol/common-utils' +import { FiatAmount, TokenAmount } from '@cowprotocol/ui' import { Currency, Price } from '@uniswap/sdk-core' -import { FiatAmount } from 'common/pure/FiatAmount' -import { TokenAmount } from 'common/pure/TokenAmount' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' - import { useExecutionPriceFiat } from './hooks/useExecutionPriceFiat' export interface ExecutionPriceProps { diff --git a/apps/cowswap-frontend/src/common/pure/FiatValue/index.tsx b/apps/cowswap-frontend/src/common/pure/FiatValue/index.tsx index 97f0064c87..85a2691256 100644 --- a/apps/cowswap-frontend/src/common/pure/FiatValue/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/FiatValue/index.tsx @@ -1,3 +1,4 @@ +import { FiatAmount } from '@cowprotocol/ui' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import styled from 'styled-components/macro' @@ -6,7 +7,6 @@ import { Nullish } from 'types' import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { UI } from 'common/constants/theme' -import { FiatAmount } from 'common/pure/FiatAmount' import { PriceImpactIndicator } from '../PriceImpactIndicator' diff --git a/apps/cowswap-frontend/src/common/pure/HelpCircle/index.tsx b/apps/cowswap-frontend/src/common/pure/HelpCircle/index.tsx index abcdf92f63..a6a9c1722c 100644 --- a/apps/cowswap-frontend/src/common/pure/HelpCircle/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/HelpCircle/index.tsx @@ -1,7 +1,8 @@ +import { questionIcon } from '@cowprotocol/assets/cow-swap/question' + import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import { questionIcon } from 'legacy/assets/cow-swap/question' import { useIsDarkMode } from 'legacy/state/user/hooks' const HelpCircleWrapper = styled.div` diff --git a/apps/cowswap-frontend/src/common/pure/InlineBanner/banners.tsx b/apps/cowswap-frontend/src/common/pure/InlineBanner/banners.tsx index dff983b59e..84281bb088 100644 --- a/apps/cowswap-frontend/src/common/pure/InlineBanner/banners.tsx +++ b/apps/cowswap-frontend/src/common/pure/InlineBanner/banners.tsx @@ -1,9 +1,8 @@ +import { TokenAmount } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { TokenAmount } from 'common/pure/TokenAmount' - import { CowSwapSafeAppLink } from '../CowSwapSafeAppLink' import { InlineBanner } from './index' diff --git a/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx b/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx index 64bc0f1cc4..a2dcffa2e7 100644 --- a/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx @@ -1,14 +1,14 @@ import { ReactNode } from 'react' +import iconInformation from '@cowprotocol/assets/cow-swap/alert-circle.svg' +import iconAlert from '@cowprotocol/assets/cow-swap/alert.svg' +import iconDanger from '@cowprotocol/assets/cow-swap/alert.svg' +import iconSuccess from '@cowprotocol/assets/cow-swap/check.svg' + import { lighten, darken, transparentize } from 'polished' import SVG from 'react-inlinesvg' import styled, { useTheme } from 'styled-components/macro' // import useTheme -import iconInformation from 'legacy/assets/cow-swap/alert-circle.svg' -import iconAlert from 'legacy/assets/cow-swap/alert.svg' -import iconDanger from 'legacy/assets/cow-swap/alert.svg' -import iconSuccess from 'legacy/assets/cow-swap/check.svg' - type BannerType = 'alert' | 'information' | 'success' | 'danger' | 'savings' interface BannerConfig { diff --git a/apps/cowswap-frontend/src/common/pure/Modal/index.tsx b/apps/cowswap-frontend/src/common/pure/Modal/index.tsx index 3e82c46166..9b3c952155 100644 --- a/apps/cowswap-frontend/src/common/pure/Modal/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/Modal/index.tsx @@ -1,19 +1,17 @@ import React from 'react' +import { isMobile } from '@cowprotocol/common-utils' + import { useSpringValue, useTransition } from '@react-spring/web' import { useGesture } from '@use-gesture/react' import CLOSE_ICON from 'assets/icon/x.svg' import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import { isMobile } from 'legacy/utils/userAgent' - import { UI } from 'common/constants/theme' import { CloseIcon, ContentWrapper, HeaderRow, HoverText, StyledDialogContent, StyledDialogOverlay } from './styled' - - export * from './styled' interface ModalProps { @@ -67,9 +65,9 @@ export function Modal({ `translateY(${(y as number) > 0 ? y : 0}px)`) }, - } + ...bind(), + style: { transform: y.interpolate((y) => `translateY(${(y as number) > 0 ? y : 0}px)`) }, + } : {})} aria-label="dialog content" $minHeight={minHeight} @@ -89,7 +87,7 @@ export function Modal({ ) } -export const CowModal = styled(Modal) <{ +export const CowModal = styled(Modal)<{ maxWidth?: number | string backgroundColor?: string border?: string @@ -178,8 +176,8 @@ const NewCowModal = styled.div<{ maxWidth?: number | string; minHeight?: number overflow-y: auto; ${ModalInner} { - max-width: ${({ maxWidth }) => maxWidth ? `${maxWidth}px` : '100%'}; - min-height: ${({ minHeight }) => minHeight ? `${minHeight}px` : '100%'}; + max-width: ${({ maxWidth }) => (maxWidth ? `${maxWidth}px` : '100%')}; + min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : '100%')}; ${({ theme }) => theme.mediaWidth.upToSmall` max-width: 100%; @@ -224,7 +222,7 @@ const IconX = styled.div` } ` -const NewModalContent = styled.div<{ paddingTop?: number}>` +const NewModalContent = styled.div<{ paddingTop?: number }>` display: flex; align-items: center; justify-content: center; @@ -234,8 +232,8 @@ const NewModalContent = styled.div<{ paddingTop?: number}>` height: 100%; padding: 0 var(${UI.PADDING_NORMAL}) var(${UI.PADDING_NORMAL}); - h1, - h2, + h1, + h2, h3 { width: 100%; font-size: var(${UI.FONT_SIZE_LARGER}); @@ -290,26 +288,17 @@ interface NewModalProps { children?: React.ReactNode } -export function NewModal({ - maxWidth = 450, - minHeight = 450, - title, - children, - onDismiss, -}: NewModalProps) { - +export function NewModal({ maxWidth = 450, minHeight = 450, title, children, onDismiss }: NewModalProps) { return ( - {title && {title}} - - {children} - + {children} - onDismiss && onDismiss()}> - + onDismiss && onDismiss()}> + + ) } diff --git a/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx b/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx index a2ae882e45..04880fef18 100644 --- a/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/NetworksList/index.tsx @@ -1,12 +1,11 @@ +import { getChainInfo } from '@cowprotocol/common-const' +import { getExplorerBaseUrl } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { ALL_SUPPORTED_CHAIN_IDS } from '@cowprotocol/cow-sdk' +import { ExternalLink } from '@cowprotocol/ui' import { Trans } from '@lingui/macro' -import { getChainInfo } from 'legacy/constants/chainInfo' -import { ALL_SUPPORTED_CHAIN_IDS } from 'legacy/constants/chains' -import { ExternalLink } from 'legacy/theme' -import { getExplorerBaseUrl } from 'legacy/utils/explorer' - import * as styledEl from './styled' export interface NetworksListProps { diff --git a/apps/cowswap-frontend/src/common/pure/OrderSubmittedContent/index.tsx b/apps/cowswap-frontend/src/common/pure/OrderSubmittedContent/index.tsx index 371e4e54d3..d8551b7e69 100644 --- a/apps/cowswap-frontend/src/common/pure/OrderSubmittedContent/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/OrderSubmittedContent/index.tsx @@ -1,12 +1,12 @@ +import { isCowOrder } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { ButtonPrimary } from '@cowprotocol/ui' import { Trans } from '@lingui/macro' import styled from 'styled-components/macro' -import { ButtonPrimary } from 'legacy/components/Button' import { EnhancedTransactionLink } from 'legacy/components/EnhancedTransactionLink' import { HashType } from 'legacy/state/enhancedTransactions/reducer' -import { isCowOrder } from 'legacy/utils' import AnimatedConfirmation from 'common/pure/AnimatedConfirmation' diff --git a/apps/cowswap-frontend/src/common/pure/PriceImpactIndicator/index.tsx b/apps/cowswap-frontend/src/common/pure/PriceImpactIndicator/index.tsx index 0fe2fc1de7..4d18915b0d 100644 --- a/apps/cowswap-frontend/src/common/pure/PriceImpactIndicator/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/PriceImpactIndicator/index.tsx @@ -1,15 +1,14 @@ +import { formatPercent } from '@cowprotocol/common-utils' +import { Loader } from '@cowprotocol/ui' +import { MouseoverTooltip } from '@cowprotocol/ui' import { Percent } from '@uniswap/sdk-core' import { t } from '@lingui/macro' import styled, { DefaultTheme } from 'styled-components/macro' -import Loader from 'legacy/components/Loader' -import { MouseoverTooltip } from 'legacy/components/Tooltip' import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { warningSeverity } from 'legacy/utils/prices' -import { formatPercent } from 'utils/amountFormat' - export interface PriceImpactIndicatorProps { priceImpactParams?: PriceImpact } diff --git a/apps/cowswap-frontend/src/common/pure/RateInfo/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/RateInfo/index.cosmos.tsx index b21ff58f99..8d54cde44c 100644 --- a/apps/cowswap-frontend/src/common/pure/RateInfo/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/common/pure/RateInfo/index.cosmos.tsx @@ -1,13 +1,10 @@ +import { COW, GNO, DAI_GOERLI, USDT_GOERLI, WETH_GOERLI } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { TokenSymbol } from '@cowprotocol/ui' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import styled from 'styled-components/macro' -import { COW, GNO } from 'legacy/constants/tokens' -import { DAI_GOERLI, USDT_GOERLI, WETH_GOERLI } from 'legacy/utils/goerli/constants' - -import { TokenSymbol } from 'common/pure/TokenSymbol' - import { RateInfoParams, RateInfo } from './index' const inputCurrency = WETH_GOERLI diff --git a/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx b/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx index 814085e487..7ea915715a 100644 --- a/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/RateInfo/index.tsx @@ -1,6 +1,8 @@ import React, { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react' +import { getAddress } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { FiatAmount, TokenAmount, TokenSymbol } from '@cowprotocol/ui' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' @@ -11,11 +13,7 @@ import { Nullish } from 'types' import { UI } from 'common/constants/theme' import { usePrice } from 'common/hooks/usePrice' -import { FiatAmount } from 'common/pure/FiatAmount' -import { TokenAmount } from 'common/pure/TokenAmount' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { getQuoteCurrency } from 'common/services/getQuoteCurrency' -import { getAddress } from 'utils/getAddress' const DEFAULT_DECIMALS = 4 diff --git a/apps/cowswap-frontend/src/common/pure/SafeWalletLink/index.tsx b/apps/cowswap-frontend/src/common/pure/SafeWalletLink/index.tsx index 864694ae96..2df9622fa3 100644 --- a/apps/cowswap-frontend/src/common/pure/SafeWalletLink/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/SafeWalletLink/index.tsx @@ -1,6 +1,5 @@ -import { ExternalLink } from 'legacy/theme' - -import { getSafeWebUrl } from 'api/gnosisSafe' +import { getSafeWebUrl } from '@cowprotocol/core' +import { ExternalLink } from '@cowprotocol/ui' export function SafeWalletLink(props: { chainId: number diff --git a/apps/cowswap-frontend/src/common/pure/SelectDropdown/index.tsx b/apps/cowswap-frontend/src/common/pure/SelectDropdown/index.tsx deleted file mode 100644 index 76fe96f85b..0000000000 --- a/apps/cowswap-frontend/src/common/pure/SelectDropdown/index.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import styled from 'styled-components/macro' - -import { UI } from 'common/constants/theme' - -export const SelectDropdown = styled.select` - border-radius: 12px; - padding: 8px 34px 8px 8px; - border-radius: 12px; - appearance: none; - cursor: pointer; - transition: background 0.2s ease-in-out; - width: 100%; - outline: none; - border: 1px solid var(${UI.COLOR_BORDER}); - color: var(${UI.COLOR_TEXT1}); - background: linear-gradient(45deg, transparent 50%, var(${UI.COLOR_LIGHT_BLUE}) 50%) calc(100% - 13px) calc(13px) / 5px - 5px no-repeat, - linear-gradient(135deg, var(${UI.COLOR_LIGHT_BLUE}) 50%, transparent 50%) calc(100% - 8px) calc(13px) / 5px 5px - no-repeat, - linear-gradient(to right, var(${UI.COLOR_LIGHT_BLUE_OPACITY_90}), var(${UI.COLOR_LIGHT_BLUE_OPACITY_90})) 100% 0 / - 26px 100% no-repeat; - - &:hover { - background: linear-gradient(45deg, transparent 50%, var(${UI.COLOR_LIGHT_BLUE}) 50%) calc(100% - 13px) calc(13px) / - 5px 5px no-repeat, - linear-gradient(135deg, var(${UI.COLOR_LIGHT_BLUE}) 50%, transparent 50%) calc(100% - 8px) calc(13px) / 5px 5px - no-repeat, - linear-gradient(to right, var(${UI.COLOR_LIGHT_BLUE_OPACITY_80}), var(${UI.COLOR_LIGHT_BLUE_OPACITY_80})) 100% 0 / - 26px 100% no-repeat; - } -` diff --git a/apps/cowswap-frontend/src/common/pure/TradeLoadingButton/index.tsx b/apps/cowswap-frontend/src/common/pure/TradeLoadingButton/index.tsx index 790066f67a..0ef6a6110e 100644 --- a/apps/cowswap-frontend/src/common/pure/TradeLoadingButton/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/TradeLoadingButton/index.tsx @@ -1,10 +1,11 @@ import { useEffect, useState } from 'react' +import { LONG_LOAD_THRESHOLD } from '@cowprotocol/common-const' + import { Text } from 'rebass' import styled from 'styled-components/macro' import { Dots } from 'legacy/components/swap/styleds' -import { LONG_LOAD_THRESHOLD } from 'legacy/constants' import { ThemedText } from 'legacy/theme' const fadeIn = ` diff --git a/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.tsx b/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.tsx index 44491b0cc3..63aeeb57c7 100644 --- a/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/TransactionErrorContent/index.tsx @@ -1,8 +1,9 @@ +import { ButtonPrimary } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { AlertTriangle } from 'react-feather' import styled from 'styled-components/macro' -import { ButtonPrimary } from 'legacy/components/Button' import { CloseIcon } from 'legacy/theme' const Wrapper = styled.div` diff --git a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx index 2446e9c6a2..a0bf0e18cf 100644 --- a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx +++ b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/SurplusModal.tsx @@ -1,23 +1,21 @@ import React, { useCallback } from 'react' +import { sendEvent } from '@cowprotocol/analytics' +import CheckSingular from '@cowprotocol/assets/cow-swap/check-singular.svg' +import SurplusCow from '@cowprotocol/assets/cow-swap/surplus-cow.svg' +import twitterImage from '@cowprotocol/assets/cow-swap/twitter.svg' import { OrderKind } from '@cowprotocol/cow-sdk' +import { FiatAmount, TokenAmount, SymbolElement } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' import { transparentize } from 'polished' import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import CheckSingular from 'legacy/assets/cow-swap/check-singular.svg' -import SurplusCow from 'legacy/assets/cow-swap/surplus-cow.svg' -import twitterImage from 'legacy/assets/cow-swap/twitter.svg' import { Order } from 'legacy/state/orders/actions' -import { ExternalLink } from 'legacy/theme' import { UI } from 'common/constants/theme' import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue' -import { FiatAmount } from 'common/pure/FiatAmount' -import { TokenAmount, SymbolElement } from 'common/pure/TokenAmount' - -import { sendEvent } from '../../../legacy/components/analytics/googleAnalytics' const SELL_SURPLUS_WORD = 'got' const BUY_SURPLUS_WORD = 'saved' diff --git a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/index.tsx b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/index.tsx index e234c0603d..a39747a3d9 100644 --- a/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/TransactionSubmittedContent/index.tsx @@ -1,5 +1,6 @@ import React from 'react' +import GameIcon from '@cowprotocol/assets/cow-swap/game.gif' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { Currency } from '@uniswap/sdk-core' @@ -7,7 +8,6 @@ import { Link } from 'react-router-dom' import { Text } from 'rebass' import { Nullish } from 'types' -import GameIcon from 'legacy/assets/cow-swap/game.gif' import { OrderProgressBar } from 'legacy/components/OrderProgressBar' import { DisplayLink } from 'legacy/components/TransactionConfirmationModal/DisplayLink' import { getActivityState } from 'legacy/hooks/useActivityDerivedState' @@ -15,7 +15,7 @@ import { ActivityStatus } from 'legacy/hooks/useRecentActivity' import { ActivityDerivedState } from 'modules/account/containers/Transaction' import { EthFlowStepper } from 'modules/swap/containers/EthFlowStepper' -import AddToMetamask from 'modules/wallet/web3-react/containers/AddToMetamask' +import { AddToMetamask } from 'modules/wallet/containers/AddToMetamask' import { Routes } from 'common/constants/routes' diff --git a/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts b/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts index 4f528f1a19..524e2e4749 100644 --- a/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts +++ b/apps/cowswap-frontend/src/common/services/getQuoteCurrency/index.ts @@ -1,13 +1,12 @@ +import { DAI, USDC_MAINNET, USDT } from '@cowprotocol/common-const' +import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' +import { DAI_GOERLI, USDT_GOERLI, USDC_GOERLI } from '@cowprotocol/common-const' +import { USDC_GNOSIS_CHAIN, USDT_GNOSIS_CHAIN, WXDAI } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants' -import { DAI, USDC_MAINNET, USDT } from 'legacy/constants/tokens' -import { USDC_GNOSIS_CHAIN, USDT_GNOSIS_CHAIN, WXDAI } from 'legacy/utils/gnosis_chain/constants' -import { DAI_GOERLI, USDT_GOERLI, USDC_GOERLI } from 'legacy/utils/goerli/constants' - // TODO: Find a solution for using API: https://www.coingecko.com/en/categories/stablecoins const STABLE_COINS: { [key in SupportedChainId]: string[] } = { [SupportedChainId.MAINNET]: [USDC_MAINNET, USDT, DAI].map((token) => token.address.toLowerCase()), diff --git a/apps/cowswap-frontend/src/common/state/totalSurplusState/updaters.ts b/apps/cowswap-frontend/src/common/state/totalSurplusState/updaters.ts index 7bbd484135..b5993a80ff 100644 --- a/apps/cowswap-frontend/src/common/state/totalSurplusState/updaters.ts +++ b/apps/cowswap-frontend/src/common/state/totalSurplusState/updaters.ts @@ -1,12 +1,11 @@ import { useSetAtom } from 'jotai' import { useCallback, useEffect } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import useSWR from 'swr' -import { useWalletInfo } from 'modules/wallet' - import { getSurplusData } from 'api/gnosisProtocol/api' import useNativeCurrency from 'lib/hooks/useNativeCurrency' diff --git a/apps/cowswap-frontend/src/legacy/state/application/updater.ts b/apps/cowswap-frontend/src/common/updaters/ApplicationUpdater.ts similarity index 79% rename from apps/cowswap-frontend/src/legacy/state/application/updater.ts rename to apps/cowswap-frontend/src/common/updaters/ApplicationUpdater.ts index fffdf17284..343dd108e7 100644 --- a/apps/cowswap-frontend/src/legacy/state/application/updater.ts +++ b/apps/cowswap-frontend/src/common/updaters/ApplicationUpdater.ts @@ -1,18 +1,14 @@ import { useEffect, useState } from 'react' +import { usePrevious, useIsWindowVisible, useDebounce } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' -import useDebounce from 'legacy/hooks/useDebounce' -import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible' -import usePrevious from 'legacy/hooks/usePrevious' +import { updateChainId } from 'legacy/state/application/reducer' import { useAppDispatch } from 'legacy/state/hooks' import { updateSelectedWallet } from 'legacy/state/user/reducer' -import { useWalletInfo } from 'modules/wallet' - -import { updateChainId } from './reducer' - -export default function Updater(): null { +export function ApplicationUpdater(): null { const { chainId } = useWalletInfo() const { provider, account } = useWeb3React() const dispatch = useAppDispatch() diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/CancelReplaceTxUpdater.tsx b/apps/cowswap-frontend/src/common/updaters/CancelReplaceTxUpdater.tsx similarity index 94% rename from apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/CancelReplaceTxUpdater.tsx rename to apps/cowswap-frontend/src/common/updaters/CancelReplaceTxUpdater.tsx index 97ab21e5d9..46a31bc723 100644 --- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/CancelReplaceTxUpdater.tsx +++ b/apps/cowswap-frontend/src/common/updaters/CancelReplaceTxUpdater.tsx @@ -1,5 +1,6 @@ import { useEffect } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { Dispatch } from 'redux' @@ -7,9 +8,8 @@ import { Dispatch } from 'redux' import { replaceTransaction } from 'legacy/state/enhancedTransactions/actions' import { useAllTransactionHashes } from 'legacy/state/enhancedTransactions/hooks' import { useAppDispatch } from 'legacy/state/hooks' -import { sdk } from 'legacy/utils/blocknative' -import { useWalletInfo } from 'modules/wallet' +import { sdk } from 'api/blocknative' function watchTxChanges(pendingHashes: string[], chainId: number, dispatch: Dispatch) { for (const hash of pendingHashes) { @@ -60,7 +60,7 @@ function unwatchTxChanges(pendingHashes: string[], chainId: number) { } } -export default function CancelReplaceTxUpdater(): null { +export function CancelReplaceTxUpdater(): null { const { provider } = useWeb3React() const { chainId, account } = useWalletInfo() const dispatch = useAppDispatch() diff --git a/apps/cowswap-frontend/src/legacy/state/price/updater.ts b/apps/cowswap-frontend/src/common/updaters/FeesUpdater.ts similarity index 91% rename from apps/cowswap-frontend/src/legacy/state/price/updater.ts rename to apps/cowswap-frontend/src/common/updaters/FeesUpdater.ts index 7080f8aab9..dfaf831e1b 100644 --- a/apps/cowswap-frontend/src/legacy/state/price/updater.ts +++ b/apps/cowswap-frontend/src/common/updaters/FeesUpdater.ts @@ -1,39 +1,36 @@ import { useEffect, useMemo } from 'react' +import { DEFAULT_DECIMALS } from '@cowprotocol/common-const' +import { useDebounce, useIsOnline, useIsWindowVisible } from '@cowprotocol/common-hooks' +import { isAddress, tryParseCurrencyAmount } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/cow-sdk' +import { useENSAddress } from '@cowprotocol/ens' +import { useWalletInfo } from '@cowprotocol/wallet' -import { DEFAULT_DECIMALS } from 'legacy/constants' -import useDebounce from 'legacy/hooks/useDebounce' -import useENSAddress from 'legacy/hooks/useENSAddress' -import useIsOnline from 'legacy/hooks/useIsOnline' -import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible' import { useRefetchQuoteCallback } from 'legacy/hooks/useRefetchPriceCallback' import { useIsUnsupportedTokenGp } from 'legacy/state/lists/hooks' -import { Field } from 'legacy/state/swap/actions' -import { useDerivedSwapInfo, useSwapState } from 'legacy/state/swap/hooks' +import { useAllQuotes, useIsBestQuoteLoading, useSetQuoteError } from 'legacy/state/price/hooks' +import { QuoteInformationObject } from 'legacy/state/price/reducer' +import { LegacyFeeQuoteParams } from 'legacy/state/price/types' import { isWrappingTrade } from 'legacy/state/swap/utils' +import { Field } from 'legacy/state/types' import { useOrderValidTo } from 'legacy/state/user/hooks' -import { isAddress } from 'legacy/utils' import { useAppData } from 'modules/appData' import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow' +import { useDerivedSwapInfo, useSwapState } from 'modules/swap/hooks/useSwapState' import { useEnoughBalanceAndAllowance } from 'modules/tokens' -import { useWalletInfo } from 'modules/wallet' import { getPriceQuality } from 'api/gnosisProtocol/api' -import { LegacyFeeQuoteParams as LegacyFeeQuoteParamsFull } from 'api/gnosisProtocol/legacy/types' -import { useVerifiedQuotesEnabled } from 'common/hooks/featureFlags/useVerifiedQuotesEnabled' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' -import { useAllQuotes, useIsBestQuoteLoading, useSetQuoteError } from './hooks' -import { QuoteInformationObject } from './reducer' +import { useVerifiedQuotesEnabled } from '../hooks/featureFlags/useVerifiedQuotesEnabled' export const TYPED_VALUE_DEBOUNCE_TIME = 350 const REFETCH_CHECK_INTERVAL = 10000 // Every 10s const RENEW_FEE_QUOTES_BEFORE_EXPIRATION_TIME = 30000 // Will renew the quote if there's less than 30 seconds left for the quote to expire const WAITING_TIME_BETWEEN_EQUAL_REQUESTS = 5000 // Prevents from sending the same request to often (max, every 5s) -type FeeQuoteParams = Omit +type FeeQuoteParams = Omit /** * Returns if the quote has been recently checked @@ -122,7 +119,7 @@ function isRefetchQuoteRequired( return false } -export default function FeesUpdater(): null { +export function FeesUpdater(): null { const { chainId, account } = useWalletInfo() const verifiedQuotesEnabled = useVerifiedQuotesEnabled(chainId) diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/FinalizeTxUpdater.tsx b/apps/cowswap-frontend/src/common/updaters/FinalizeTxUpdater.tsx similarity index 95% rename from apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/FinalizeTxUpdater.tsx rename to apps/cowswap-frontend/src/common/updaters/FinalizeTxUpdater.tsx index cc7c7ebf4d..fcedf226cd 100644 --- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/FinalizeTxUpdater.tsx +++ b/apps/cowswap-frontend/src/common/updaters/FinalizeTxUpdater.tsx @@ -1,30 +1,32 @@ import { useSetAtom } from 'jotai' import { useEffect, useMemo } from 'react' +import { GetReceipt, useBlockNumber, useGetReceipt } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' import { TransactionReceipt } from '@ethersproject/abstract-provider' import { useWeb3React } from '@web3-react/core' import ms from 'ms.macro' -import { GetReceipt, useGetReceipt } from 'legacy/hooks/useGetReceipt' import { GetSafeInfo, useGetSafeInfo } from 'legacy/hooks/useGetSafeInfo' import { AppDispatch } from 'legacy/state' import { useAddPopup } from 'legacy/state/application/hooks' +import { + checkedTransaction, + finalizeTransaction, + updateSafeTransaction, +} from 'legacy/state/enhancedTransactions/actions' import { useAllTransactionsDetails } from 'legacy/state/enhancedTransactions/hooks' +import { EnhancedTransactionDetails, HashType } from 'legacy/state/enhancedTransactions/reducer' import { useAppDispatch } from 'legacy/state/hooks' import { invalidateOrdersBatch } from 'legacy/state/orders/actions' +import { CancelOrdersBatchCallback, useCancelOrdersBatch } from 'legacy/state/orders/hooks' import { partialOrderUpdate } from 'legacy/state/orders/utils' import { removeInFlightOrderIdAtom } from 'modules/swap/state/EthFlow/ethFlowInFlightOrderIdsAtom' -import { useWalletInfo } from 'modules/wallet' -import useBlockNumber from 'lib/hooks/useBlockNumber' import useNativeCurrency from 'lib/hooks/useNativeCurrency' -import { CancelOrdersBatchCallback, useCancelOrdersBatch } from '../../orders/hooks' -import { checkedTransaction, finalizeTransaction, updateSafeTransaction } from '../actions' -import { EnhancedTransactionDetails, HashType } from '../reducer' - const DELAY_REMOVAL_ETH_FLOW_ORDER_ID_MILLISECONDS = ms`2m` // Delay removing the order ID since the creation time its mined (minor precaution just to avoid edge cases of delay in indexing times affect the collision detection type TxInterface = Pick< @@ -252,7 +254,7 @@ function checkEthereumTransactions(params: CheckEthereumTransactions): Cancel[] }) } -export default function Updater(): null { +export function FinalizeTxUpdater(): null { const { provider } = useWeb3React() const { chainId, account } = useWalletInfo() const lastBlockNumber = useBlockNumber() @@ -260,7 +262,7 @@ export default function Updater(): null { const dispatch = useAppDispatch() const cancelOrdersBatch = useCancelOrdersBatch() - const getReceipt = useGetReceipt() + const getReceipt = useGetReceipt(chainId) const getSafeInfo = useGetSafeInfo() const addPopup = useAddPopup() const removeInFlightOrderId = useSetAtom(removeInFlightOrderIdAtom) diff --git a/apps/cowswap-frontend/src/legacy/state/gas/updater.tsx b/apps/cowswap-frontend/src/common/updaters/GasUpdater.tsx similarity index 55% rename from apps/cowswap-frontend/src/legacy/state/gas/updater.tsx rename to apps/cowswap-frontend/src/common/updaters/GasUpdater.tsx index 7b41d0f02c..0c8cef160d 100644 --- a/apps/cowswap-frontend/src/legacy/state/gas/updater.tsx +++ b/apps/cowswap-frontend/src/common/updaters/GasUpdater.tsx @@ -1,19 +1,37 @@ -import { useEffect } from 'react' +import { useSetAtom } from 'jotai/index' +import { useCallback, useEffect } from 'react' -import { GAS_PRICE_UPDATE_THRESHOLD } from 'legacy/constants' +import { GAS_PRICE_UPDATE_THRESHOLD } from '@cowprotocol/common-const' +import { useBlockNumber } from '@cowprotocol/common-hooks' +import { gasPriceAtom } from '@cowprotocol/core' +import { useWalletInfo } from '@cowprotocol/wallet' -import { useWalletInfo } from 'modules/wallet' +import { useDispatch } from 'react-redux' -import { gasFeeApi } from 'api/gasPrices' -import useBlockNumber from 'lib/hooks/useBlockNumber' +import { AppDispatch } from 'legacy/state' +import { updateGasPrices, UpdateGasPrices } from 'legacy/state/gas/actions' +import { useGasPrices } from 'legacy/state/gas/hooks' -import { useGasPrices, useUpdateGasPrices } from './hooks' +import { gasFeeApi } from 'api/gasPrices' function needsGasUpdate(now: number, lastUpdated: number, threshold: number) { return now - lastUpdated > threshold } -export default function GasUpdater(): null { +function useUpdateGasPrices() { + const dispatch = useDispatch() + const setGasPrice = useSetAtom(gasPriceAtom) + + return useCallback( + (gasParams: UpdateGasPrices) => { + dispatch(updateGasPrices(gasParams)) + setGasPrice(gasParams) + }, + [dispatch, setGasPrice] + ) +} + +export function GasUpdater(): null { const { chainId } = useWalletInfo() const gas = useGasPrices(chainId) const updateGasPrices = useUpdateGasPrices() diff --git a/apps/cowswap-frontend/src/modules/wallet/api/updaters/HwAccountIndexUpdater.tsx b/apps/cowswap-frontend/src/common/updaters/HwAccountIndexUpdater.tsx similarity index 89% rename from apps/cowswap-frontend/src/modules/wallet/api/updaters/HwAccountIndexUpdater.tsx rename to apps/cowswap-frontend/src/common/updaters/HwAccountIndexUpdater.tsx index 3430a75b4e..9a74887a6b 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/updaters/HwAccountIndexUpdater.tsx +++ b/apps/cowswap-frontend/src/common/updaters/HwAccountIndexUpdater.tsx @@ -1,14 +1,11 @@ import { useAtom } from 'jotai' import { useEffect, useMemo, useRef } from 'react' +import { getIsHardWareWallet, getWeb3ReactConnection, hwAccountIndexAtom, useWalletInfo } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { useAppSelector } from 'legacy/state/hooks' -import { getIsHardWareWallet, getWeb3ReactConnection } from '../../web3-react/connection' -import { useWalletInfo } from '../hooks' -import { hwAccountIndexAtom } from '../state' - const indexChanged = true export function HwAccountIndexUpdater() { diff --git a/apps/cowswap-frontend/src/legacy/state/lists/updater.ts b/apps/cowswap-frontend/src/common/updaters/ListsUpdater.ts similarity index 93% rename from apps/cowswap-frontend/src/legacy/state/lists/updater.ts rename to apps/cowswap-frontend/src/common/updaters/ListsUpdater.ts index 133d4a27bb..4998458b55 100644 --- a/apps/cowswap-frontend/src/legacy/state/lists/updater.ts +++ b/apps/cowswap-frontend/src/common/updaters/ListsUpdater.ts @@ -1,22 +1,19 @@ import { useCallback, useEffect } from 'react' +import { UNSUPPORTED_LIST_URLS } from '@cowprotocol/common-const' +import { useInterval, useIsWindowVisible } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' import { getVersionUpgrade, minVersionBump, VersionUpgrade } from '@uniswap/token-lists' import { useWeb3React } from '@web3-react/core' -import { UNSUPPORTED_LIST_URLS } from 'legacy/constants/lists' import { useFetchListCallback } from 'legacy/hooks/useFetchListCallback' -import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible' import { updateVersion } from 'legacy/state/global/actions' import { useAppDispatch } from 'legacy/state/hooks' import { acceptListUpdate } from 'legacy/state/lists/actions' import { useAllLists } from 'legacy/state/lists/hooks' import { useActiveListUrls } from 'legacy/state/lists/hooks' -import { useWalletInfo } from 'modules/wallet' - -import useInterval from 'lib/hooks/useInterval' - -export default function Updater(): null { +export function ListsUpdater(): null { const { provider } = useWeb3React() const { chainId } = useWalletInfo() const dispatch = useAppDispatch() diff --git a/apps/cowswap-frontend/src/legacy/state/logs/updater.ts b/apps/cowswap-frontend/src/common/updaters/LogsUpdater.ts similarity index 86% rename from apps/cowswap-frontend/src/legacy/state/logs/updater.ts rename to apps/cowswap-frontend/src/common/updaters/LogsUpdater.ts index 70240a597b..ef12aecdff 100644 --- a/apps/cowswap-frontend/src/legacy/state/logs/updater.ts +++ b/apps/cowswap-frontend/src/common/updaters/LogsUpdater.ts @@ -1,18 +1,15 @@ import { useEffect, useMemo } from 'react' +import { useBlockNumber } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' import { Filter } from '@ethersproject/providers' import { useWeb3React } from '@web3-react/core' -import { useWalletInfo } from 'modules/wallet' +import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' +import { fetchedLogs, fetchedLogsError, fetchingLogs } from 'legacy/state/logs/slice' +import { isHistoricalLog, keyToFilter } from 'legacy/state/logs/utils' -import useBlockNumber from 'lib/hooks/useBlockNumber' - -import { fetchedLogs, fetchedLogsError, fetchingLogs } from './slice' -import { isHistoricalLog, keyToFilter } from './utils' - -import { useAppDispatch, useAppSelector } from '../hooks' - -export default function Updater(): null { +export function LogsUpdater(): null { const dispatch = useAppDispatch() const state = useAppSelector((state) => state.logs) const { provider } = useWeb3React() diff --git a/apps/cowswap-frontend/src/legacy/state/sentry/updater/index.ts b/apps/cowswap-frontend/src/common/updaters/SentryUpdater.ts similarity index 71% rename from apps/cowswap-frontend/src/legacy/state/sentry/updater/index.ts rename to apps/cowswap-frontend/src/common/updaters/SentryUpdater.ts index e2893d1220..0b1d6faf3f 100644 --- a/apps/cowswap-frontend/src/legacy/state/sentry/updater/index.ts +++ b/apps/cowswap-frontend/src/common/updaters/SentryUpdater.ts @@ -1,13 +1,14 @@ import { useEffect } from 'react' +import { useIsWindowVisible } from '@cowprotocol/common-hooks' +import { SentryTag } from '@cowprotocol/common-utils' +import { useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' + import * as Sentry from '@sentry/browser' -import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible' import { useAppSelector } from 'legacy/state/hooks' -import { useDerivedSwapInfo } from 'legacy/state/swap/hooks' -import { SentryTag } from 'legacy/utils/logging' -import { useWalletDetails, useWalletInfo } from 'modules/wallet' +import { useTradeState } from 'modules/trade/hooks/useTradeState' /** * _getSentryChainId @@ -32,20 +33,16 @@ function _getSentryChainIdAndConnectionStatus(appChainId: number | null, connect return sentryChainId?.toString() || SentryTag.DISCONNECTED } -export default function Updater(): null { +export function SentryUpdater(): null { const { account, chainId: connectedChainId } = useWalletInfo() const { walletName } = useWalletDetails() // app chain id maintains state for users disconnected but browsing app const disconnectedChainId = useAppSelector((state) => state.application.chainId) const windowVisible = useIsWindowVisible() - const { - currencies: { INPUT: sellCurrency, OUTPUT: buyCurrency }, - currenciesIds: { INPUT: sellCurrencyId, OUTPUT: buyCurrencyId }, - } = useDerivedSwapInfo() + const { state } = useTradeState() - const { symbol: buySymbol, name: buyName } = buyCurrency || {} - const { symbol: sellSymbol, name: sellName } = sellCurrency || {} + const { inputCurrencyId, outputCurrencyId } = state || {} useEffect(() => { if (windowVisible) { @@ -55,8 +52,8 @@ export default function Updater(): null { // setup a context scope.setContext('user', { user: account || SentryTag.DISCONNECTED, - sellToken: `${sellCurrencyId} <${sellSymbol || sellName}>`, - buyToken: `${buyCurrencyId} <${buySymbol || buyName}>`, + sellToken: inputCurrencyId, + buyToken: outputCurrencyId, }) // also set tags for each session scope.setTag('chainId', chainId) @@ -73,12 +70,8 @@ export default function Updater(): null { disconnectedChainId, walletName, // tokens - sellSymbol, - sellName, - buySymbol, - buyName, - sellCurrencyId, - buyCurrencyId, + inputCurrencyId, + outputCurrencyId, // window visibility check windowVisible, ]) diff --git a/apps/cowswap-frontend/src/legacy/state/user/updater.tsx b/apps/cowswap-frontend/src/common/updaters/UserUpdater.tsx similarity index 89% rename from apps/cowswap-frontend/src/legacy/state/user/updater.tsx rename to apps/cowswap-frontend/src/common/updaters/UserUpdater.tsx index 1b73711638..20db1f7b2f 100644 --- a/apps/cowswap-frontend/src/legacy/state/user/updater.tsx +++ b/apps/cowswap-frontend/src/common/updaters/UserUpdater.tsx @@ -1,10 +1,9 @@ import { useEffect } from 'react' import { useAppDispatch } from 'legacy/state/hooks' +import { updateMatchesDarkMode } from 'legacy/state/user/reducer' -import { updateMatchesDarkMode } from './reducer' - -export default function Updater(): null { +export function UserUpdater(): null { const dispatch = useAppDispatch() // keep dark mode in sync with the system diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/CancelledOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/CancelledOrdersUpdater.ts similarity index 95% rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/CancelledOrdersUpdater.ts rename to apps/cowswap-frontend/src/common/updaters/orders/CancelledOrdersUpdater.ts index 6ce50042c0..ef9920e84d 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/CancelledOrdersUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/CancelledOrdersUpdater.ts @@ -1,16 +1,17 @@ import { useCallback, useEffect, useRef } from 'react' +import { CANCELLED_ORDERS_PENDING_TIME } from '@cowprotocol/common-const' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' -import { CANCELLED_ORDERS_PENDING_TIME } from 'legacy/constants' import { OrderFulfillmentData } from 'legacy/state/orders/actions' import { MARKET_OPERATOR_API_POLL_INTERVAL } from 'legacy/state/orders/consts' import { useCancelledOrders, useFulfillOrdersBatch } from 'legacy/state/orders/hooks' -import { fetchOrderPopupData, OrderLogPopupMixData } from 'legacy/state/orders/updaters/utils' import { OrderTransitionStatus } from 'legacy/state/orders/utils' import { useAddOrderToSurplusQueue } from 'modules/swap/state/surplusModal' -import { useWalletInfo } from 'modules/wallet' + +import { fetchOrderPopupData, OrderLogPopupMixData } from './utils' /** * Updater for cancelled orders. diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/ExpiredOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/ExpiredOrdersUpdater.ts similarity index 95% rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/ExpiredOrdersUpdater.ts rename to apps/cowswap-frontend/src/common/updaters/orders/ExpiredOrdersUpdater.ts index 5d823a8254..850cfd7201 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/ExpiredOrdersUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/ExpiredOrdersUpdater.ts @@ -1,14 +1,13 @@ import { useEffect, useCallback, useRef } from 'react' +import { EXPIRED_ORDERS_PENDING_TIME } from '@cowprotocol/common-const' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' -import { EXPIRED_ORDERS_PENDING_TIME } from 'legacy/constants' import { SetIsOrderRefundedBatch } from 'legacy/state/orders/actions' import { EXPIRED_ORDERS_CHECK_POLL_INTERVAL } from 'legacy/state/orders/consts' import { useExpiredOrders, useSetIsOrderRefundedBatch } from 'legacy/state/orders/hooks' -import { useWalletInfo } from 'modules/wallet' - import { getOrder } from 'api/gnosisProtocol' export function ExpiredOrdersUpdater(): null { diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/GpOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts similarity index 97% rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/GpOrdersUpdater.ts rename to apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts index 18dcae9e3b..88f51d14ca 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/GpOrdersUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts @@ -1,23 +1,24 @@ import { useSetAtom } from 'jotai' import { useCallback, useEffect, useMemo, useRef } from 'react' +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' import { EnrichedOrder, EthflowData, OrderClass, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' import { useAllTokens } from 'legacy/hooks/Tokens' import { Order, OrderStatus } from 'legacy/state/orders/actions' import { useAddOrUpdateOrders, useClearOrdersStorage } from 'legacy/state/orders/hooks' -import { computeOrderSummary } from 'legacy/state/orders/updaters/utils' import { classifyOrder, OrderTransitionStatus } from 'legacy/state/orders/utils' import { useTokensForOrdersList, getTokensListFromOrders } from 'modules/orders' import { apiOrdersAtom } from 'modules/orders/state/apiOrdersAtom' -import { useWalletInfo } from 'modules/wallet' import { useGpOrders } from 'api/gnosisProtocol/hooks' import { getTokenFromMapping } from 'utils/orderUtils/getTokenFromMapping' +import { computeOrderSummary } from './utils' + // TODO: update this for ethflow states const statusMapping: Record = { cancelled: OrderStatus.CANCELLED, diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/PendingOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts similarity index 95% rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/PendingOrdersUpdater.ts rename to apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts index 6db86d83fe..154a24b889 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/PendingOrdersUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts @@ -1,7 +1,14 @@ import { useSetAtom } from 'jotai' import { useCallback, useEffect, useRef } from 'react' +import { + getExplorerOrderLink, + isOrderInPendingTooLong, + openNpsAppziSometimes, + timeSinceInSeconds, +} from '@cowprotocol/common-utils' import { EthflowData, OrderClass, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { GetSafeInfo, useGetSafeInfo } from 'legacy/hooks/useGetSafeInfo' import { FulfillOrdersBatchParams, Order, OrderFulfillmentData, OrderStatus } from 'legacy/state/orders/actions' @@ -21,18 +28,16 @@ import { usePresignOrders, useUpdatePresignGnosisSafeTx, } from 'legacy/state/orders/hooks' -import { fetchOrderPopupData, OrderLogPopupMixData } from 'legacy/state/orders/updaters/utils' import { OrderTransitionStatus } from 'legacy/state/orders/utils' -import { isOrderInPendingTooLong, openNpsAppziSometimes } from 'legacy/utils/appzi' -import { getExplorerOrderLink } from 'legacy/utils/explorer' import { useAddOrderToSurplusQueue } from 'modules/swap/state/surplusModal' -import { useWalletInfo } from 'modules/wallet' import { getOrder, OrderID } from 'api/gnosisProtocol' -import { removeOrdersToCancelAtom } from 'common/hooks/useMultipleOrdersCancellation/state' -import { useTriggerTotalSurplusUpdateCallback } from 'common/state/totalSurplusState' -import { timeSinceInSeconds } from 'utils/time' + +import { fetchOrderPopupData, OrderLogPopupMixData } from './utils' + +import { removeOrdersToCancelAtom } from '../../hooks/useMultipleOrdersCancellation/state' +import { useTriggerTotalSurplusUpdateCallback } from '../../state/totalSurplusState' /** * Return the ids of the orders that we are not yet aware that are signed. diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/SpotPricesUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/SpotPricesUpdater.ts similarity index 93% rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/SpotPricesUpdater.ts rename to apps/cowswap-frontend/src/common/updaters/orders/SpotPricesUpdater.ts index 1bc75801b0..9f09e4af74 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/SpotPricesUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/SpotPricesUpdater.ts @@ -1,20 +1,20 @@ import { useSetAtom } from 'jotai' import { useCallback, useEffect, useRef } from 'react' +import { useIsWindowVisible } from '@cowprotocol/common-hooks' +import { FractionUtils } from '@cowprotocol/common-utils' import { OrderClass, SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' -import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible' import { SPOT_PRICE_CHECK_POLL_INTERVAL } from 'legacy/state/orders/consts' import { useCombinedPendingOrders } from 'legacy/state/orders/hooks' import { requestPrice } from 'modules/limitOrders/hooks/useGetInitialPrice' import { UpdateSpotPriceAtom, updateSpotPricesAtom } from 'modules/orders/state/spotPricesAtom' -import { useWalletInfo } from 'modules/wallet' -import { useSafeMemo } from 'common/hooks/useSafeMemo' -import { getCanonicalMarketChainKey } from 'common/utils/markets' -import { FractionUtils } from 'utils/fractionUtils' +import { useSafeMemo } from '../../hooks/useSafeMemo' +import { getCanonicalMarketChainKey } from '../../utils/markets' type MarketRecord = Record< string, diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/UnfillableOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater.ts similarity index 94% rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/UnfillableOrdersUpdater.ts rename to apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater.ts index d89fd64b21..20270205bc 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/UnfillableOrdersUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater.ts @@ -1,17 +1,18 @@ import { useSetAtom } from 'jotai' import { useCallback, useEffect, useMemo, useRef } from 'react' +import { priceOutOfRangeAnalytics } from '@cowprotocol/analytics' +import { GP_VAULT_RELAYER, NATIVE_CURRENCY_BUY_ADDRESS, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' +import { useIsWindowVisible } from '@cowprotocol/common-hooks' +import { getPromiseFulfilledValue } from '@cowprotocol/common-utils' import { timestamp } from '@cowprotocol/contracts' import { OrderClass, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount, Price } from '@uniswap/sdk-core' import { FeeInformation, PriceInformation } from 'types' -import { priceOutOfRangeAnalytics } from 'legacy/components/analytics' -import { GP_VAULT_RELAYER, NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants' -import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' import { useGetGpPriceStrategy } from 'legacy/hooks/useGetGpPriceStrategy' -import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible' import { GpPriceStrategy } from 'legacy/state/gas/atoms' import { Order } from 'legacy/state/orders/actions' import { PENDING_ORDERS_PRICE_CHECK_POLL_INTERVAL } from 'legacy/state/orders/consts' @@ -22,16 +23,15 @@ import { getRemainderAmount, isOrderUnfillable, } from 'legacy/state/orders/utils' -import { getPromiseFulfilledValue } from 'legacy/utils/misc' import { getBestQuote } from 'legacy/utils/price' import { updatePendingOrderPricesAtom } from 'modules/orders/state/pendingOrdersPricesAtom' import { hasEnoughBalanceAndAllowance, useBalancesAndAllowances } from 'modules/tokens' -import { useWalletInfo } from 'modules/wallet' import { getPriceQuality } from 'api/gnosisProtocol/api' -import { PRICE_QUOTE_VALID_TO_TIME } from 'common/constants/quote' -import { useVerifiedQuotesEnabled } from 'common/hooks/featureFlags/useVerifiedQuotesEnabled' + +import { PRICE_QUOTE_VALID_TO_TIME } from '../../constants/quote' +import { useVerifiedQuotesEnabled } from '../../hooks/featureFlags/useVerifiedQuotesEnabled' /** * Updater that checks whether pending orders are still "fillable" diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/index.ts b/apps/cowswap-frontend/src/common/updaters/orders/index.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/index.ts rename to apps/cowswap-frontend/src/common/updaters/orders/index.ts diff --git a/apps/cowswap-frontend/src/legacy/state/orders/updaters/utils.ts b/apps/cowswap-frontend/src/common/updaters/orders/utils.ts similarity index 96% rename from apps/cowswap-frontend/src/legacy/state/orders/updaters/utils.ts rename to apps/cowswap-frontend/src/common/updaters/orders/utils.ts index e1a916ef03..7fb3f3a37c 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/updaters/utils.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/utils.ts @@ -1,14 +1,12 @@ +import { formatSymbol, formatTokenAmount, shortenAddress } from '@cowprotocol/common-utils' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { EnrichedOrder, OrderKind } from '@cowprotocol/cow-sdk' import { Order, OrderFulfillmentData, OrderStatus } from 'legacy/state/orders/actions' import { classifyOrder, OrderTransitionStatus } from 'legacy/state/orders/utils' import { stringToCurrency } from 'legacy/state/swap/extension' -import { shortenAddress } from 'legacy/utils' import { getOrder, OrderID } from 'api/gnosisProtocol' -import { formatTokenAmount } from 'utils/amountFormat' -import { formatSymbol } from 'utils/format' import { getIsComposableCowChildOrder } from 'utils/orderUtils/getIsComposableCowChildOrder' export type OrderLogPopupMixData = OrderFulfillmentData | OrderID diff --git a/apps/cowswap-frontend/src/common/utils/isOrderCancellable.test.ts b/apps/cowswap-frontend/src/common/utils/isOrderCancellable.test.ts index ac2a9a0aea..c7fbeead13 100644 --- a/apps/cowswap-frontend/src/common/utils/isOrderCancellable.test.ts +++ b/apps/cowswap-frontend/src/common/utils/isOrderCancellable.test.ts @@ -1,5 +1,6 @@ -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' -import { COW } from 'legacy/constants/tokens' +import { COW } from '@cowprotocol/common-const' +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' + import { Order, OrderStatus } from 'legacy/state/orders/actions' import { isOrderCancellable } from './isOrderCancellable' diff --git a/apps/cowswap-frontend/src/common/utils/markets.ts b/apps/cowswap-frontend/src/common/utils/markets.ts index ceb8728937..e977992483 100644 --- a/apps/cowswap-frontend/src/common/utils/markets.ts +++ b/apps/cowswap-frontend/src/common/utils/markets.ts @@ -1,7 +1,4 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { Currency, Price } from '@uniswap/sdk-core' - -import invariant from 'tiny-invariant' /** * Convenient method to identify a market so it doesn't matter what is the sell token or buy token. @@ -51,11 +48,3 @@ export function getCanonicalMarketChainKey( marketInverted, } } - -export function assertSameMarket(price1: Price, price2: Price) { - // Assert I'm comparing apples with apples (prices should refer to market) - invariant( - price1.baseCurrency.equals(price2.baseCurrency) && price1.quoteCurrency.equals(price2.quoteCurrency), - 'Prices are not from the same market' - ) -} diff --git a/apps/cowswap-frontend/src/cosmos.decorator.tsx b/apps/cowswap-frontend/src/cosmos.decorator.tsx index f4afab8001..04bffb1c00 100644 --- a/apps/cowswap-frontend/src/cosmos.decorator.tsx +++ b/apps/cowswap-frontend/src/cosmos.decorator.tsx @@ -3,6 +3,10 @@ import './polyfills' import React, { StrictMode, useCallback, useContext, ReactNode } from 'react' +import IMAGE_MOON from '@cowprotocol/assets/cow-swap/moon.svg' +import IMAGE_SUN from '@cowprotocol/assets/cow-swap/sun.svg' +import { BlockNumberProvider } from '@cowprotocol/common-hooks' +import { WalletUpdater, injectedConnection } from '@cowprotocol/wallet' import { Web3ReactProvider } from '@web3-react/core' import { LanguageProvider } from 'i18n' @@ -13,19 +17,10 @@ import { Flex } from 'rebass' import styled from 'styled-components/macro' import { ThemeContext } from 'styled-components/macro' -import IMAGE_MOON from 'legacy/assets/cow-swap/moon.svg' -import IMAGE_SUN from 'legacy/assets/cow-swap/sun.svg' -import store from 'legacy/state' +import { cowSwapStore } from 'legacy/state' import { useDarkModeManager } from 'legacy/state/user/hooks' import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from 'legacy/theme' -import { injectedConnection } from 'modules/wallet/web3-react/connection/injected' - -import { UI } from 'common/constants/theme' -import { BlockNumberProvider } from 'lib/hooks/useBlockNumber' - -import { WalletUpdater } from './modules/wallet' - const DarkModeToggleButton = styled.button` display: flex; align-items: center; @@ -83,7 +78,7 @@ export const DemoContainer = styled.div` display: flex; flex-flow: column wrap; gap: 6px; - background: var(${UI.COLOR_CONTAINER_BG_01}); + background: ${({ theme }) => theme.bg1}; border: none; border-radius: 16px; box-shadow: ${({ theme }) => theme.boxShadow1}; @@ -99,7 +94,7 @@ const Fixture = ({ children }: { children: ReactNode }) => { return ( - + diff --git a/apps/cowswap-frontend/src/cow-react/index.tsx b/apps/cowswap-frontend/src/cow-react/index.tsx index f20b500682..550ac9907f 100644 --- a/apps/cowswap-frontend/src/cow-react/index.tsx +++ b/apps/cowswap-frontend/src/cow-react/index.tsx @@ -1,12 +1,15 @@ import '@reach/dialog/styles.css' import 'inter-ui' -import 'legacy/components/analytics' -import 'utils/sentry' +import '@cowprotocol/analytics' +import './sentry' import { Provider as AtomProvider } from 'jotai' import { StrictMode } from 'react' -import { SnackbarsWidget } from '@cowswap/snackbars' +import { BlockNumberProvider } from '@cowprotocol/common-hooks' +import { nodeRemoveChildFix } from '@cowprotocol/common-utils' +import { jotaiStore } from '@cowprotocol/core' +import { SnackbarsWidget } from '@cowprotocol/snackbars' import { LanguageProvider } from 'i18n' import { createRoot } from 'react-dom/client' @@ -17,9 +20,8 @@ import * as serviceWorkerRegistration from 'serviceWorkerRegistration' import AppziButton from 'legacy/components/AppziButton' import { Popups } from 'legacy/components/Popups' import Web3Provider from 'legacy/components/Web3Provider' -import store from 'legacy/state' +import { cowSwapStore } from 'legacy/state' import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from 'legacy/theme' -import { nodeRemoveChildFix } from 'legacy/utils/node' import { App } from 'modules/application/containers/App' import { Updaters } from 'modules/application/containers/App/Updaters' @@ -27,10 +29,8 @@ import { WithLDProvider } from 'modules/application/containers/WithLDProvider' import { FortuneWidget } from 'modules/fortune/containers/FortuneWidget' import { FeatureGuard } from 'common/containers/FeatureGuard' -import { BlockNumberProvider } from 'lib/hooks/useBlockNumber' import { WalletUnsupportedNetworkBanner } from '../common/containers/WalletUnsupportedNetworkBanner' -import { jotaiStore } from '../jotaiStore' // Node removeChild hackaround // based on: https://github.com/facebook/react/issues/11538#issuecomment-417504600 @@ -45,7 +45,7 @@ const root = createRoot(document.getElementById('root')!) root.render( - + diff --git a/apps/cowswap-frontend/src/utils/sentry.ts b/apps/cowswap-frontend/src/cow-react/sentry.ts similarity index 93% rename from apps/cowswap-frontend/src/utils/sentry.ts rename to apps/cowswap-frontend/src/cow-react/sentry.ts index 868867d629..43cd6d3e11 100644 --- a/apps/cowswap-frontend/src/utils/sentry.ts +++ b/apps/cowswap-frontend/src/cow-react/sentry.ts @@ -1,6 +1,6 @@ -import * as Sentry from '@sentry/react' +import { environmentName } from '@cowprotocol/common-utils' -import { environmentName } from 'legacy/utils/environments' +import * as Sentry from '@sentry/react' import { SENTRY_IGNORED_GP_QUOTE_ERRORS } from 'api/gnosisProtocol/errors/QuoteError' diff --git a/apps/cowswap-frontend/src/cowSdk.ts b/apps/cowswap-frontend/src/cowSdk.ts index 94b6582b6c..8fe22917e6 100644 --- a/apps/cowswap-frontend/src/cowSdk.ts +++ b/apps/cowswap-frontend/src/cowSdk.ts @@ -1,8 +1,7 @@ import { MetadataApi } from '@cowprotocol/app-data' +import { isBarnBackendEnv } from '@cowprotocol/common-utils' import { OrderBookApi } from '@cowprotocol/cow-sdk' -import { isBarnBackendEnv } from 'legacy/utils/environments' - const prodBaseUrls = process.env.REACT_APP_ORDER_BOOK_URLS ? JSON.parse(process.env.REACT_APP_ORDER_BOOK_URLS) : undefined diff --git a/apps/cowswap-frontend/src/i18n.tsx b/apps/cowswap-frontend/src/i18n.tsx index 43c79e78e9..bc78401fc2 100644 --- a/apps/cowswap-frontend/src/i18n.tsx +++ b/apps/cowswap-frontend/src/i18n.tsx @@ -1,6 +1,7 @@ import { ReactNode, useCallback } from 'react' -import { SupportedLocale } from 'legacy/constants/locales' +import { SupportedLocale } from '@cowprotocol/common-const' + import { initialLocale, useActiveLocale } from 'legacy/hooks/useActiveLocale' import { useUserLocaleManager } from 'legacy/state/user/hooks' diff --git a/apps/cowswap-frontend/src/legacy/components/AMMsLogo/index.tsx b/apps/cowswap-frontend/src/legacy/components/AMMsLogo/index.tsx index 219680b64a..eb8e1e0c3d 100644 --- a/apps/cowswap-frontend/src/legacy/components/AMMsLogo/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/AMMsLogo/index.tsx @@ -1,21 +1,20 @@ +import ZeroX from '@cowprotocol/assets/cow-swap/ammslogo/0x.png' +import Oneinch from '@cowprotocol/assets/cow-swap/ammslogo/1inch.png' +import Baoswap from '@cowprotocol/assets/cow-swap/ammslogo/baoswap.png' +import Curve from '@cowprotocol/assets/cow-swap/ammslogo/curve.png' +import Elk from '@cowprotocol/assets/cow-swap/ammslogo/elk.png' +import Honeyswap from '@cowprotocol/assets/cow-swap/ammslogo/honeyswap.png' +import Levinswap from '@cowprotocol/assets/cow-swap/ammslogo/levinswap.png' +import Matcha from '@cowprotocol/assets/cow-swap/ammslogo/matcha.png' +import Paraswap from '@cowprotocol/assets/cow-swap/ammslogo/paraswap.png' +import Sushi from '@cowprotocol/assets/cow-swap/ammslogo/sushi.png' +import Swapr from '@cowprotocol/assets/cow-swap/ammslogo/swapr.png' +import Symmetric from '@cowprotocol/assets/cow-swap/ammslogo/symmetric.png' +import Uniswap from '@cowprotocol/assets/cow-swap/ammslogo/uniswap.png' import { SupportedChainId } from '@cowprotocol/cow-sdk' import styled from 'styled-components/macro' -import ZeroX from 'legacy/assets/cow-swap/ammslogo/0x.png' -import Oneinch from 'legacy/assets/cow-swap/ammslogo/1inch.png' -import Baoswap from 'legacy/assets/cow-swap/ammslogo/baoswap.png' -import Curve from 'legacy/assets/cow-swap/ammslogo/curve.png' -import Elk from 'legacy/assets/cow-swap/ammslogo/elk.png' -import Honeyswap from 'legacy/assets/cow-swap/ammslogo/honeyswap.png' -import Levinswap from 'legacy/assets/cow-swap/ammslogo/levinswap.png' -import Matcha from 'legacy/assets/cow-swap/ammslogo/matcha.png' -import Paraswap from 'legacy/assets/cow-swap/ammslogo/paraswap.png' -import Sushi from 'legacy/assets/cow-swap/ammslogo/sushi.png' -import Swapr from 'legacy/assets/cow-swap/ammslogo/swapr.png' -import Symmetric from 'legacy/assets/cow-swap/ammslogo/symmetric.png' -import Uniswap from 'legacy/assets/cow-swap/ammslogo/uniswap.png' - import { imagesAnimationDelay, animationDelay, crossFade, fadeInOut, presentationTime } from './utils' export const Wrapper = styled.div<{ logosLength: number }>` diff --git a/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx b/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx index fd885621d9..a16f629887 100644 --- a/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/AddressInputPanel/index.tsx @@ -1,15 +1,16 @@ import { ChangeEvent, Context, ReactNode, useCallback, useContext } from 'react' +import { getBlockExplorerUrl as getExplorerLink } from '@cowprotocol/common-utils' +import { useENS } from '@cowprotocol/ens' +import { RowBetween } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' + import { t, Trans } from '@lingui/macro' import styled, { DefaultTheme, ThemeContext } from 'styled-components/macro' import { AutoColumn } from 'legacy/components/Column' -import { RowBetween } from 'legacy/components/Row' -import useENS from 'legacy/hooks/useENS' -import { ExternalLink, ThemedText } from 'legacy/theme' -import { getBlockExplorerUrl as getExplorerLink } from 'legacy/utils' - -import { useWalletInfo } from 'modules/wallet' +import { ThemedText } from 'legacy/theme' import { UI } from 'common/constants/theme' import { autofocus } from 'common/utils/autofocus' diff --git a/apps/cowswap-frontend/src/legacy/components/AppziButton/index.tsx b/apps/cowswap-frontend/src/legacy/components/AppziButton/index.tsx index 8eeb64cd96..a5070de79e 100644 --- a/apps/cowswap-frontend/src/legacy/components/AppziButton/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/AppziButton/index.tsx @@ -1,10 +1,10 @@ +import FeedbackIcon from '@cowprotocol/assets/cow-swap/feedback.svg' +import { isAppziEnabled, openFeedbackAppzi } from '@cowprotocol/common-utils' + import { transparentize } from 'polished' import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import FeedbackIcon from 'legacy/assets/cow-swap/feedback.svg' -import { isAppziEnabled, openFeedbackAppzi } from 'legacy/utils/appzi' - const Wrapper = styled.div` background: ${({ theme }) => transparentize(0.3, theme.bg2)}; backdrop-filter: blur(5px); diff --git a/apps/cowswap-frontend/src/legacy/components/Badge/RangeBadge.tsx b/apps/cowswap-frontend/src/legacy/components/Badge/RangeBadge.tsx index a7d4bb5293..65246370ef 100644 --- a/apps/cowswap-frontend/src/legacy/components/Badge/RangeBadge.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Badge/RangeBadge.tsx @@ -1,11 +1,11 @@ +import { MouseoverTooltip } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { AlertCircle } from 'react-feather' import styled from 'styled-components/macro' import Badge, { BadgeVariant } from 'legacy/components/Badge' -import { MouseoverTooltip } from '../Tooltip' - const BadgeWrapper = styled.div` font-size: 14px; display: flex; diff --git a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonRadioChecked.tsx b/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonRadioChecked.tsx deleted file mode 100644 index b4d4b772b8..0000000000 --- a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonRadioChecked.tsx +++ /dev/null @@ -1,9 +0,0 @@ -// ButtonRadioChecked.fixture.jsx -import { ButtonRadioChecked } from '../index' - -const fixtures = { - active: Active, - notActive: Not active, -} - -export default fixtures diff --git a/apps/cowswap-frontend/src/legacy/components/Confetti/index.tsx b/apps/cowswap-frontend/src/legacy/components/Confetti/index.tsx index de5837c7c1..46da1b428f 100644 --- a/apps/cowswap-frontend/src/legacy/components/Confetti/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Confetti/index.tsx @@ -1,6 +1,6 @@ -import ReactConfetti from 'react-confetti' +import { useWindowSize } from '@cowprotocol/common-hooks' -import { useWindowSize } from '../../hooks/useWindowSize' +import ReactConfetti from 'react-confetti' // eslint-disable-next-line react/prop-types export default function Confetti({ start, variant }: { start: boolean; variant?: string }) { diff --git a/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx b/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx index 0d1a40bc8d..25d9bea369 100644 --- a/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx @@ -1,11 +1,12 @@ import React from 'react' +import { useCopyClipboard } from '@cowprotocol/common-hooks' + import { Trans } from '@lingui/macro' import { CheckCircle, Copy } from 'react-feather' import styled from 'styled-components/macro' import { TransactionStatusText } from 'legacy/components/Copy/index' -import useCopyClipboard from 'legacy/hooks/useCopyClipboard' import { LinkStyledButton } from 'legacy/theme' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/CowBalance/index.tsx b/apps/cowswap-frontend/src/legacy/components/CowBalance/index.tsx index 9d43db3680..f9528ff5f7 100644 --- a/apps/cowswap-frontend/src/legacy/components/CowBalance/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/CowBalance/index.tsx @@ -1,10 +1,11 @@ +import { TokenAmount } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import styled from 'styled-components/macro' import CowProtocolLogo from 'legacy/components/CowProtocolLogo' import { CowSubsidyInfoProps } from 'legacy/components/CowSubsidyModal' -import { TokenAmount } from 'common/pure/TokenAmount' import { ClaimSummaryTitle, ClaimTotal, ClaimSummary as ClaimSummaryWrapper } from 'pages/Claim/styled' const Wrapper = styled(ClaimSummaryWrapper)` diff --git a/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx b/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx index 83d5564e8a..633bd9ca3e 100644 --- a/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/CowBalanceButton/index.tsx @@ -1,13 +1,14 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { TokenAmount } from '@cowprotocol/ui' import { transparentize } from 'polished' import styled, { css } from 'styled-components/macro' import CowProtocolLogo from 'legacy/components/CowProtocolLogo' -import { useCombinedBalance } from 'legacy/state/cowToken/hooks' import { UI } from 'common/constants/theme' -import { TokenAmount } from 'common/pure/TokenAmount' + +import { useCombinedBalance } from '../../hooks/useCombinedBalance' export const Wrapper = styled.div<{ isLoading: boolean }>` background-color: transparent; diff --git a/apps/cowswap-frontend/src/legacy/components/CowProtocolLogo/index.tsx b/apps/cowswap-frontend/src/legacy/components/CowProtocolLogo/index.tsx index deab9db9be..dc22834552 100644 --- a/apps/cowswap-frontend/src/legacy/components/CowProtocolLogo/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/CowProtocolLogo/index.tsx @@ -1,6 +1,6 @@ -import styled from 'styled-components/macro' +import CowProtocolIcon from '@cowprotocol/assets/cow-swap/cow_v2.svg' -import CowProtocolIcon from 'legacy/assets/cow-swap/cow_v2.svg' +import styled from 'styled-components/macro' export const Icon = styled.span` --defaultSize: 24px; diff --git a/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx b/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx index d4e937e956..fe3d6af20e 100644 --- a/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx +++ b/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/SubsidyTable.tsx @@ -1,14 +1,14 @@ +import { V_COW } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount } from '@uniswap/sdk-core' import { transparentize, lighten } from 'polished' import styled from 'styled-components/macro' -import { V_COW } from 'legacy/constants/tokens' import { useIsDarkMode } from 'legacy/state/user/hooks' import { UI } from 'common/constants/theme' -import { TokenAmount } from 'common/pure/TokenAmount' import { COW_SUBSIDY_DATA } from './constants' diff --git a/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/index.tsx b/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/index.tsx index b31882b08b..c6d522084d 100644 --- a/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/CowSubsidyModal/index.tsx @@ -1,27 +1,25 @@ import { useCallback } from 'react' +import { ExternalLink, Row } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Text } from 'rebass' import { AutoColumn } from 'legacy/components/Column' -import { ExternalLink } from 'legacy/components/Link' -import Row from 'legacy/components/Row' import { ConfirmationModalProps } from 'legacy/components/TransactionConfirmationModal' -import { - ConfirmationModalContentProps, - LegacyConfirmationModalContent, -} from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationModalContent' import useCowBalanceAndSubsidy from 'legacy/hooks/useCowBalanceAndSubsidy' -import { useWalletInfo } from 'modules/wallet' - import { CowModal } from 'common/pure/Modal' import { SUBSIDY_INFO_MESSAGE } from './constants' import SubsidyTable from './SubsidyTable' import CowBalance from '../CowBalance' +import { + ConfirmationModalContentProps, + LegacyConfirmationModalContent, +} from '../TransactionConfirmationModal/LegacyConfirmationModalContent' export type CowSubsidy = { tier: number; discount: number } export interface CowSubsidyInfoProps { diff --git a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ChunkLoadError.tsx b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ChunkLoadError.tsx index 04d8e6054e..2b97197d37 100644 --- a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ChunkLoadError.tsx +++ b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ChunkLoadError.tsx @@ -1,14 +1,16 @@ import React, { useCallback } from 'react' +import cowNoConnectionIMG from '@cowprotocol/assets/cow-swap/cow-no-connection.png' +import { DISCORD_LINK } from '@cowprotocol/common-const' +import { ButtonPrimary } from '@cowprotocol/ui' +import { AutoRow } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import styled from 'styled-components/macro' -import cowNoConnectionIMG from 'legacy/assets/cow-swap/cow-no-connection.png' -import { ButtonPrimary } from 'legacy/components/Button' import { AutoColumn } from 'legacy/components/Column' -import { AutoRow } from 'legacy/components/Row' -import { DISCORD_LINK } from 'legacy/constants' -import { ExternalLink, MEDIA_WIDTHS, ThemedText } from 'legacy/theme' +import { MEDIA_WIDTHS, ThemedText } from 'legacy/theme' import { Title } from 'modules/application/pure/Page' diff --git a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx index 33647df010..13adefa7f7 100644 --- a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx +++ b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/ErrorWithStackTrace.tsx @@ -1,16 +1,17 @@ import React from 'react' +import CowError from '@cowprotocol/assets/cow-swap/CowError.png' +import { CODE_LINK, DISCORD_LINK } from '@cowprotocol/common-const' +import { userAgent } from '@cowprotocol/common-utils' +import { AutoRow } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import styled from 'styled-components/macro' -import CowError from 'legacy/assets/cow-swap/CowError.png' import { AutoColumn } from 'legacy/components/Column' -import { AutoRow } from 'legacy/components/Row' -import { CODE_LINK, DISCORD_LINK } from 'legacy/constants' -import store, { AppState } from 'legacy/state' +import { cowSwapStore, AppState } from 'legacy/state' import { MEDIA_WIDTHS, ThemedText } from 'legacy/theme' -import { ExternalLink } from 'legacy/theme' -import { userAgent } from 'legacy/utils/userAgent' import { Title } from 'modules/application/pure/Page' @@ -145,7 +146,7 @@ ${ ? `## \`${relevantState}\` state \`\`\`json -${JSON.stringify(store.getState()[relevantState], null, 2)} +${JSON.stringify(cowSwapStore.getState()[relevantState], null, 2)} \`\`\` ` : '' diff --git a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx index 0e6c5343ae..74d286ca67 100644 --- a/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/ErrorBoundary/index.tsx @@ -1,5 +1,7 @@ import React, { ErrorInfo, PropsWithChildren } from 'react' +import { sendError } from '@cowprotocol/analytics' + import * as Sentry from '@sentry/react' import styled from 'styled-components/macro' @@ -13,8 +15,6 @@ import { Page } from 'modules/application/pure/Page' import { Routes } from 'common/constants/routes' -import { sendError } from '../analytics/googleAnalytics' - type ErrorBoundaryState = { error: Error | null } diff --git a/apps/cowswap-frontend/src/legacy/components/ExplorerLink/index.tsx b/apps/cowswap-frontend/src/legacy/components/ExplorerLink/index.tsx index ac4f142808..6f3974491c 100644 --- a/apps/cowswap-frontend/src/legacy/components/ExplorerLink/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/ExplorerLink/index.tsx @@ -1,13 +1,10 @@ import { PropsWithChildren } from 'react' +import { getExplorerLabel, getEtherscanLink } from '@cowprotocol/common-utils' +import { getSafeWebUrl } from '@cowprotocol/core' import { SupportedChainId } from '@cowprotocol/cow-sdk' - -import { ExternalLink } from 'legacy/theme' -import { getExplorerLabel, getEtherscanLink } from 'legacy/utils' - -import { useWalletInfo } from 'modules/wallet' - -import { getSafeWebUrl } from 'api/gnosisSafe' +import { ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' interface PropsBase extends PropsWithChildren { // type?: BlockExplorerLinkType diff --git a/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx b/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx index 03f72ca2a4..8658299810 100644 --- a/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/FlashingLoading/index.tsx @@ -1,9 +1,9 @@ +import CowIcon from '@cowprotocol/assets/cow-swap/cowprotocol.svg' + import { transparentize } from 'polished' import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import CowIcon from 'legacy/assets/cow-swap/cowprotocol.svg' - import { UI } from 'common/constants/theme' export const LoadingWrapper = styled.div` diff --git a/apps/cowswap-frontend/src/legacy/components/Header/ChainConnectivityWarning.tsx b/apps/cowswap-frontend/src/legacy/components/Header/ChainConnectivityWarning.tsx index 69948f4085..05491ca721 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/ChainConnectivityWarning.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/ChainConnectivityWarning.tsx @@ -1,14 +1,13 @@ +import { getChainInfo } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { Trans } from '@lingui/macro' import { AlertOctagon } from 'react-feather' import styled from 'styled-components/macro' -import { getChainInfo } from 'legacy/constants/chainInfo' import { MEDIA_WIDTHS } from 'legacy/theme' -import { useWalletInfo } from 'modules/wallet' - const BodyRow = styled.div` color: ${({ theme }) => theme.black}; font-size: 12px; diff --git a/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx index 99243a99e9..eb6cf28201 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/NetworkSelector/index.tsx @@ -1,5 +1,7 @@ import { useRef } from 'react' +import { getChainInfo } from '@cowprotocol/common-const' +import { useWalletInfo, getIsTallyWallet, useIsSmartContractWallet } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { Trans } from '@lingui/macro' @@ -7,18 +9,13 @@ import { transparentize, darken } from 'polished' import { AlertTriangle, ChevronDown } from 'react-feather' import styled from 'styled-components/macro' -import { getChainInfo } from 'legacy/constants/chainInfo' import { useMediaQuery, upToMedium } from 'legacy/hooks/useMediaQuery' import { useCloseModal, useModalIsOpen, useOpenModal, useToggleModal } from 'legacy/state/application/hooks' import { ApplicationModal } from 'legacy/state/application/reducer' import { MEDIA_WIDTHS } from 'legacy/theme' -import { useWalletInfo } from 'modules/wallet' -import { getIsTallyWallet } from 'modules/wallet/api/utils/connection' - import { UI } from 'common/constants/theme' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' -import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet' import { useOnSelectNetwork } from 'common/hooks/useOnSelectNetwork' import { NetworksList } from 'common/pure/NetworksList' diff --git a/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx b/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx index 0ab10a92fc..1e22b2748b 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/Polling.tsx @@ -1,28 +1,25 @@ import { useEffect, useState } from 'react' +import { getChainInfo } from '@cowprotocol/common-const' +import { useBlockNumber, useMachineTimeMs, useTheme } from '@cowprotocol/common-hooks' +import { ExplorerDataType, getExplorerLink } from '@cowprotocol/common-utils' +import { RowFixed } from '@cowprotocol/ui' +import { MouseoverTooltip, ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' + import { Trans } from '@lingui/macro' import JSBI from 'jsbi' import ms from 'ms.macro' import styled, { keyframes } from 'styled-components/macro' -import { RowFixed } from 'legacy/components/Row' -import { getChainInfo } from 'legacy/constants/chainInfo' import useCurrentBlockTimestamp from 'legacy/hooks/useCurrentBlockTimestamp' import useGasPrice from 'legacy/hooks/useGasPrice' -import useMachineTimeMs from 'legacy/hooks/useMachineTime' -import useTheme from 'legacy/hooks/useTheme' -import { ExternalLink, ThemedText } from 'legacy/theme' -import { ExplorerDataType, getExplorerLink } from 'legacy/utils/getExplorerLink' - -import { useWalletInfo } from 'modules/wallet' +import { ThemedText } from 'legacy/theme' import { UI } from 'common/constants/theme' -import useBlockNumber from 'lib/hooks/useBlockNumber' import { ChainConnectivityWarning } from './ChainConnectivityWarning' -import { MouseoverTooltip } from '../Tooltip' - export const StyledPolling = styled.div<{ warning: boolean }>` position: fixed; display: flex; diff --git a/apps/cowswap-frontend/src/legacy/components/Header/URLWarning/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/URLWarning/index.tsx index 83b6e26846..e55c067e71 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/URLWarning/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/URLWarning/index.tsx @@ -1,15 +1,14 @@ +import { useFetchFile } from '@cowprotocol/common-hooks' +import { hashCode } from '@cowprotocol/common-utils' +import { environmentName } from '@cowprotocol/common-utils' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { AlertTriangle } from 'react-feather' import styled from 'styled-components/macro' import { Markdown } from 'legacy/components/Markdown' -import useFetchFile from 'legacy/hooks/useFetchFile' import { useAnnouncementVisible, useCloseAnnouncement } from 'legacy/state/profile/hooks' -import { environmentName } from 'legacy/utils/environments' -import { hashCode } from 'legacy/utils/misc' - -import { useWalletInfo } from 'modules/wallet' import URLWarningUni, { PhishAlert, StyledClose } from './URLWarningMod' diff --git a/apps/cowswap-frontend/src/legacy/components/Header/index.tsx b/apps/cowswap-frontend/src/legacy/components/Header/index.tsx index b2f63f0a63..ced341809e 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/index.tsx @@ -1,17 +1,20 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react' +import { toggleDarkModeAnalytics } from '@cowprotocol/analytics' +import { isInjectedWidget } from '@cowprotocol/common-utils' +import { addBodyClass, removeBodyClass } from '@cowprotocol/common-utils' import { SupportedChainId as ChainId, SupportedChainId } from '@cowprotocol/cow-sdk' +import { TokenAmount } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import SVG from 'react-inlinesvg' import { useNavigate } from 'react-router-dom' -import { toggleDarkModeAnalytics } from 'legacy/components/analytics' import CowBalanceButton from 'legacy/components/CowBalanceButton' import { NetworkSelector } from 'legacy/components/Header/NetworkSelector' import { LargeAndUp, upToLarge, upToMedium, upToSmall, useMediaQuery } from 'legacy/hooks/useMediaQuery' import { useDarkModeManager } from 'legacy/state/user/hooks' import { cowSwapLogo } from 'legacy/theme/cowSwapAssets' -import { addBodyClass, removeBodyClass } from 'legacy/utils/toggleBodyClass' import { OrdersPanel } from 'modules/account/containers/OrdersPanel' import { useInjectedWidgetParams } from 'modules/injectedWidget' @@ -21,12 +24,11 @@ import { useSwapRawState } from 'modules/swap/hooks/useSwapRawState' import { useNativeCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalance' import { useTradeState } from 'modules/trade/hooks/useTradeState' import { getDefaultTradeRawState } from 'modules/trade/types/TradeRawState' -import { useWalletInfo, Web3Status } from 'modules/wallet' +import { Web3Status } from 'modules/wallet/containers/Web3Status' import { Routes } from 'common/constants/routes' +import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' -import { TokenAmount } from 'common/pure/TokenAmount' -import { isInjectedWidget } from 'common/utils/isInjectedWidget' import MobileMenuIcon from './MobileMenuIcon' import { @@ -54,6 +56,7 @@ export default function Header() { const isChainIdUnsupported = useIsProviderNetworkUnsupported() + const { pendingActivity } = useCategorizeRecentActivity() const userEthBalance = useNativeCurrencyBalances(account ? [account] : [])?.[account ?? ''] const nativeToken = CHAIN_CURRENCY_LABELS[chainId] || 'ETH' const [darkMode, toggleDarkModeAux] = useDarkModeManager() @@ -159,7 +162,7 @@ export default function Header() { )} - + diff --git a/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx b/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx index 23080235dd..0bdfd8fef0 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx @@ -1,5 +1,7 @@ import { PropsWithChildren } from 'react' +import { Row, RowFixed } from '@cowprotocol/ui' + import useScrollPosition from '@react-hook/window-scroll' import { transparentize, darken } from 'polished' import { NavLink } from 'react-router-dom' @@ -7,7 +9,6 @@ import { Text } from 'rebass' import styled, { css } from 'styled-components/macro' import { MenuFlyout, MenuSection, Content as MenuContent, MenuTitle } from 'legacy/components/MenuDropdown/styled' -import Row, { RowFixed } from 'legacy/components/Row' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/HoverInlineText/index.tsx b/apps/cowswap-frontend/src/legacy/components/HoverInlineText/index.tsx index b7351ee304..1f4b44e51f 100644 --- a/apps/cowswap-frontend/src/legacy/components/HoverInlineText/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/HoverInlineText/index.tsx @@ -1,8 +1,8 @@ import { useState } from 'react' -import styled from 'styled-components/macro' +import { Tooltip } from '@cowprotocol/ui' -import Tooltip from 'legacy/components/Tooltip' +import styled from 'styled-components/macro' export const TextWrapper = styled.span<{ margin: boolean diff --git a/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx b/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx index 79645741e0..eaae70599b 100644 --- a/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx @@ -1,10 +1,10 @@ import { ReactNode } from 'react' +import { MouseoverTooltipContent, TooltipContainer } from '@cowprotocol/ui' + import { Info } from 'react-feather' import styled from 'styled-components/macro' -import { MouseoverTooltipContent, TooltipContainer } from 'legacy/components/Tooltip' - import { UI } from 'common/constants/theme' const StyledInfoIcon = styled(Info)` diff --git a/apps/cowswap-frontend/src/legacy/components/Link/index.tsx b/apps/cowswap-frontend/src/legacy/components/Link/index.tsx index 192a934994..ce16f3850f 100644 --- a/apps/cowswap-frontend/src/legacy/components/Link/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Link/index.tsx @@ -1,7 +1,7 @@ +import { ExternalLink } from '@cowprotocol/ui' + import HashLink from 'legacy/components/HashLink' -import { ExternalLink } from 'legacy/theme' -export { ExternalLink } from 'legacy/theme' const SCROLL_OFFSET = 24 export interface LinkRendererProps { diff --git a/apps/cowswap-frontend/src/legacy/components/Loader/Logo/index.tsx b/apps/cowswap-frontend/src/legacy/components/Loader/Logo/index.tsx index dacadaf187..1f55d85414 100644 --- a/apps/cowswap-frontend/src/legacy/components/Loader/Logo/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Loader/Logo/index.tsx @@ -1,10 +1,10 @@ import { useState } from 'react' +import { useTheme } from '@cowprotocol/common-hooks' + import { Slash } from 'react-feather' import { ImageProps } from 'rebass' -import useTheme from 'legacy/hooks/useTheme' - const BAD_SRCS: { [tokenAddress: string]: true } = {} export interface LogoProps extends Pick { diff --git a/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx b/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx index 516a2f8915..0c60c40a12 100644 --- a/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx @@ -1,15 +1,15 @@ import { ReactNode } from 'react' +import { useFetchFile } from '@cowprotocol/common-hooks' + import ReactMarkdown, { ReactMarkdownPropsBase } from 'react-markdown' import ReactMarkdownHtml from 'react-markdown/with-html' import styled from 'styled-components/macro' import { WithClassName } from 'types' -// AmplitudeAnalytics import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { LinkScrollable, Link } from 'legacy/components/Link' -import useFetchFile from 'legacy/hooks/useFetchFile' import { Page, Title, Content } from 'modules/application/pure/Page' diff --git a/apps/cowswap-frontend/src/legacy/components/MenuDropdown/index.tsx b/apps/cowswap-frontend/src/legacy/components/MenuDropdown/index.tsx index 55b7dd1a78..0d6f5372d3 100644 --- a/apps/cowswap-frontend/src/legacy/components/MenuDropdown/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/MenuDropdown/index.tsx @@ -1,10 +1,11 @@ import { useState, useRef } from 'react' +import IMAGE_CARRET_DOWN from '@cowprotocol/assets/cow-swap/carret-down.svg' +import { useOnClickOutside } from '@cowprotocol/common-hooks' + import SVG from 'react-inlinesvg' -import IMAGE_CARRET_DOWN from 'legacy/assets/cow-swap/carret-down.svg' import { useMediaQuery, LargeAndUp } from 'legacy/hooks/useMediaQuery' -import { useOnClickOutside } from 'legacy/hooks/useOnClickOutside' import { MenuFlyout, Content } from './styled' diff --git a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx index 28ae411cf6..42fc0b07ea 100644 --- a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx +++ b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/NetworkAlert.tsx @@ -1,17 +1,17 @@ +import { getChainInfo } from '@cowprotocol/common-const' +import { useTheme } from '@cowprotocol/common-hooks' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { AutoRow } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { Trans } from '@lingui/macro' import { transparentize } from 'polished' import { ArrowUpRight } from 'react-feather' import styled from 'styled-components/macro' -import { AutoRow } from 'legacy/components/Row' -import { getChainInfo } from 'legacy/constants/chainInfo' -import useTheme from 'legacy/hooks/useTheme' import { useDarkModeManager } from 'legacy/state/user/hooks' -import { ExternalLink, HideSmall } from 'legacy/theme' - -import { useWalletInfo } from 'modules/wallet' +import { HideSmall } from 'legacy/theme' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts index bc150fbc24..3e9a04a57d 100644 --- a/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts +++ b/apps/cowswap-frontend/src/legacy/components/NetworkAlert/styles.ts @@ -1,6 +1,6 @@ -import styled from 'styled-components/macro' +import { ExternalLink } from '@cowprotocol/ui' -import { ExternalLink } from 'legacy/theme' +import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx b/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx index a462ca229a..40f25d7239 100644 --- a/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/NumericalInput/index.tsx @@ -1,12 +1,12 @@ import React from 'react' +import { escapeRegExp } from '@cowprotocol/common-utils' + import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' import { autofocus } from 'common/utils/autofocus' -import { escapeRegExp } from '../../utils' - const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: string }>` color: ${({ error, theme }) => (error ? theme.red1 : theme.text1)}; width: 0; diff --git a/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/index.tsx b/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/index.tsx index b277aec583..c92a266a40 100644 --- a/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/index.tsx @@ -1,24 +1,24 @@ import { useEffect, useMemo, useState } from 'react' +import loadingCowWebp from '@cowprotocol/assets/cow-swap/cow-load.webp' +import ammsGraphGC from '@cowprotocol/assets/images/amms-graph-gc.svg' +import ammsGraphEth from '@cowprotocol/assets/images/amms-graph.svg' +import cowGraph from '@cowprotocol/assets/images/cow-graph.svg' +import cowMeditatingSmooth from '@cowprotocol/assets/images/cow-meditating-smoooth.svg' +import cowMeditatingGraph from '@cowprotocol/assets/images/cow-meditating.svg' +import { getExplorerOrderLink } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useIsSmartContractWallet } from '@cowprotocol/wallet' import { useTransition } from '@react-spring/web' import ms from 'ms.macro' -import loadingCowWebp from 'legacy/assets/cow-swap/cow-load.webp' -import ammsGraphGC from 'legacy/assets/images/amms-graph-gc.svg' -import ammsGraphEth from 'legacy/assets/images/amms-graph.svg' -import cowGraph from 'legacy/assets/images/cow-graph.svg' -import cowMeditatingSmooth from 'legacy/assets/images/cow-meditating-smoooth.svg' -import cowMeditatingGraph from 'legacy/assets/images/cow-meditating.svg' import { AMMsLogo } from 'legacy/components/AMMsLogo' import { EXPECTED_EXECUTION_TIME, getPercentage } from 'legacy/components/OrderProgressBar/utils' -import { getExplorerOrderLink } from 'legacy/utils/explorer' import { ActivityDerivedState } from 'modules/account/containers/Transaction' import { useCancelOrder } from 'common/hooks/useCancelOrder' -import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet' import { CancelButton } from 'common/pure/CancelButton' import { diff --git a/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts b/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts index abe234b096..365aba86da 100644 --- a/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/OrderProgressBar/styled.ts @@ -1,10 +1,10 @@ +import CowProtocolLogo from '@cowprotocol/assets/cow-swap/cowprotocol.svg' +import { ExternalLink } from '@cowprotocol/ui' + import { animated } from '@react-spring/web' import { CheckCircle, Clock } from 'react-feather' import styled from 'styled-components/macro' -import CowProtocolLogo from 'legacy/assets/cow-swap/cowprotocol.svg' -import { ExternalLink } from 'legacy/theme' - import { UI } from 'common/constants/theme' export const ProgressBarWrapper = animated(styled.div` diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/FailedNetworkSwitchPopup.tsx b/apps/cowswap-frontend/src/legacy/components/Popups/FailedNetworkSwitchPopup.tsx index 0825bcd3d7..9f84c557de 100644 --- a/apps/cowswap-frontend/src/legacy/components/Popups/FailedNetworkSwitchPopup.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Popups/FailedNetworkSwitchPopup.tsx @@ -1,14 +1,14 @@ import { useContext } from 'react' +import { getChainInfo } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { AutoRow } from '@cowprotocol/ui' import { Trans } from '@lingui/macro' import { AlertCircle } from 'react-feather' import styled, { ThemeContext } from 'styled-components/macro' import { AutoColumn } from 'legacy/components/Column' -import { AutoRow } from 'legacy/components/Row' -import { getChainInfo } from 'legacy/constants/chainInfo' const RowNoFlex = styled(AutoRow)` flex-wrap: nowrap; diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/PopupItem.tsx b/apps/cowswap-frontend/src/legacy/components/Popups/PopupItem.tsx index 9042d107ca..6004c1f7da 100644 --- a/apps/cowswap-frontend/src/legacy/components/Popups/PopupItem.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Popups/PopupItem.tsx @@ -12,7 +12,7 @@ import { AnimatedFader, PopupWrapper, StyledClose } from './styled' import { TransactionPopup } from './TransactionPopup' /** - * @deprecated use @cowswap/snackbars instead + * @deprecated use @cowprotocol/snackbars instead */ export function PopupItem({ removeAfterMs, diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/TransactionPopup.tsx b/apps/cowswap-frontend/src/legacy/components/Popups/TransactionPopup.tsx index 69a30c03f1..43e2611136 100644 --- a/apps/cowswap-frontend/src/legacy/components/Popups/TransactionPopup.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Popups/TransactionPopup.tsx @@ -1,15 +1,15 @@ import { useContext } from 'react' +import { BlockExplorerLinkType } from '@cowprotocol/common-utils' +import { AutoRow } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' + import { AlertCircle, CheckCircle } from 'react-feather' import styled, { ThemeContext } from 'styled-components/macro' import { AutoColumn } from 'legacy/components/Column' import { ExplorerLink } from 'legacy/components/ExplorerLink' -import { AutoRow } from 'legacy/components/Row' import { ThemedText } from 'legacy/theme' -import { BlockExplorerLinkType } from 'legacy/utils' - -import { useWalletInfo } from 'modules/wallet' const RowNoFlex = styled(AutoRow)` flex-wrap: nowrap; diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/WarningPopup.tsx b/apps/cowswap-frontend/src/legacy/components/Popups/WarningPopup.tsx index cce6f893ca..38b94a90ec 100644 --- a/apps/cowswap-frontend/src/legacy/components/Popups/WarningPopup.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Popups/WarningPopup.tsx @@ -1,10 +1,11 @@ import { useContext } from 'react' +import { AutoRow } from '@cowprotocol/ui' + import { AlertCircle } from 'react-feather' import styled, { ThemeContext } from 'styled-components/macro' import { AutoColumn } from 'legacy/components/Column' -import { AutoRow } from 'legacy/components/Row' import { ThemedText } from 'legacy/theme' const RowNoFlex = styled(AutoRow)` diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/index.tsx b/apps/cowswap-frontend/src/legacy/components/Popups/index.tsx index 3ba3b376d0..35a1a41892 100644 --- a/apps/cowswap-frontend/src/legacy/components/Popups/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Popups/index.tsx @@ -1,6 +1,7 @@ import { MouseEvent, useCallback, useRef } from 'react' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { transparentize } from 'polished' import styled from 'styled-components/macro' @@ -11,8 +12,6 @@ import { useActivePopups, useRemovePopup } from 'legacy/state/application/hooks' import { useURLWarningVisible } from 'legacy/state/user/hooks' import { MEDIA_WIDTHS } from 'legacy/theme' -import { useWalletInfo } from 'modules/wallet' - export const MobilePopupInner = styled.div` height: 99%; overflow-x: auto; @@ -75,7 +74,7 @@ const FixedPopupColumn = styled(AutoColumn)<{ extraPadding: boolean; xlPadding: ` /** - * @deprecated use @cowswap/snackbars instead + * @deprecated use @cowprotocol/snackbars instead */ export function Popups() { // get all popups diff --git a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx index f734b09742..6e2abdee6c 100644 --- a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx @@ -1,9 +1,8 @@ import { useCallback, useState } from 'react' -import styled from 'styled-components/macro' +import { Tooltip, TooltipProps, renderTooltip } from '@cowprotocol/ui' -import Tooltip, { renderTooltip } from 'legacy/components/Tooltip' -import { TooltipProps } from 'legacy/components/Tooltip' +import styled from 'styled-components/macro' import { QuestionWrapper } from './index' diff --git a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx index 89711c44d5..907a17ddd6 100644 --- a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx @@ -1,11 +1,11 @@ import { ReactNode } from 'react' +import QuestionImage from '@cowprotocol/assets/svg/question.svg' +import { renderTooltip } from '@cowprotocol/ui' + import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import QuestionImage from 'legacy/assets/svg/question.svg' -import { renderTooltip } from 'legacy/components/Tooltip' - import { UI } from 'common/constants/theme' import QuestionHelperMod, { QuestionHelperProps } from './QuestionHelperMod' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx index b059f3410a..5cebfc1340 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx @@ -1,3 +1,5 @@ +import { currencyId } from '@cowprotocol/common-utils' +import { TokenSymbol, AutoRow } from '@cowprotocol/ui' import { Currency, Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' @@ -7,12 +9,9 @@ import styled from 'styled-components/macro' import { ElementName, Event, EventName } from 'legacy/components/AmplitudeAnalytics/constants' import { TraceEvent } from 'legacy/components/AmplitudeAnalytics/TraceEvent' import QuestionHelper from 'legacy/components/QuestionHelper' -import { AutoRow } from 'legacy/components/Row' import { useFavouriteOrCommonTokens } from 'legacy/hooks/useFavouriteOrCommonTokens' -import { currencyId } from 'legacy/utils/currencyId' import { CurrencyLogo } from 'common/pure/CurrencyLogo' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { BaseWrapper, CommonBasesRow, MobileWrapper } from './index' // mod diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/index.ts b/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/index.ts index c8f4cc0ac5..269b7f262b 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/index.ts +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/index.ts @@ -1,10 +1,10 @@ +import { AutoRow } from '@cowprotocol/ui' import { Currency } from '@uniswap/sdk-core' import { transparentize } from 'polished' import styled from 'styled-components/macro' import { AutoColumn as AutoColumnUni } from 'legacy/components/Column' -import { AutoRow } from 'legacy/components/Row' export { default } from './CommonBasesMod' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx index 8e4a427df0..a190f4ab4d 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx @@ -1,5 +1,10 @@ import { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react' +import TokenListLogo from '@cowprotocol/assets/svg/tokenlist.svg' +import { useTheme } from '@cowprotocol/common-hooks' +import { TokenAmount, TokenSymbol, Loader, RowBetween, RowFixed } from '@cowprotocol/ui' +import { MouseoverTooltip } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' @@ -7,29 +12,21 @@ import { FixedSizeList } from 'react-window' import { Text } from 'rebass' import styled from 'styled-components/macro' -import TokenListLogo from 'legacy/assets/svg/tokenlist.svg' import { ElementName, Event, EventName } from 'legacy/components/AmplitudeAnalytics/constants' import { TraceEvent } from 'legacy/components/AmplitudeAnalytics/TraceEvent' import { LightGreyCard } from 'legacy/components/Card' import Column from 'legacy/components/Column' -import Loader from 'legacy/components/Loader' import QuestionHelper from 'legacy/components/QuestionHelper' -import { RowBetween, RowFixed } from 'legacy/components/Row' import ImportRow from 'legacy/components/SearchModal/ImportRow' import { LoadingRows } from 'legacy/components/SearchModal/styleds' -import { MouseoverTooltip } from 'legacy/components/Tooltip' import { useAllTokens, useIsUserAddedToken } from 'legacy/hooks/Tokens' -import useTheme from 'legacy/hooks/useTheme' import { useIsUnsupportedTokenGp } from 'legacy/state/lists/hooks' import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo' import { ThemedText } from 'legacy/theme' import useCurrencyBalance from 'modules/tokens/hooks/useCurrencyBalance' -import { useWalletInfo } from 'modules/wallet' import { CurrencyLogo } from 'common/pure/CurrencyLogo' -import { TokenAmount } from 'common/pure/TokenAmount' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { Tag } from './styled' // mod @@ -139,7 +136,11 @@ function CurrencyRow({ isPermitCompatible: boolean // gp-added allTokens: { [address: string]: Token } // gp-added BalanceComponent?: (params: { balance: CurrencyAmount }) => JSX.Element // gp-swap added - TokenTagsComponent?: (params: { currency: Currency; isUnsupported: boolean; isPermitCompatible: boolean }) => JSX.Element // gp-swap added + TokenTagsComponent?: (params: { + currency: Currency + isUnsupported: boolean + isPermitCompatible: boolean + }) => JSX.Element // gp-swap added }) { const { account } = useWalletInfo() const key = currencyKey(currency) @@ -344,7 +345,7 @@ export default function CurrencyList({ const showImport = index > currencies.length const isUnsupported = !!isUnsupportedToken(token?.address) - const isPermitCompatible = false // TODO: Make dynamic + const isPermitCompatible = false // TODO: Make dynamic if (isLoading) { return ( diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx index d176f7e1a5..43987756c4 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/index.tsx @@ -1,19 +1,15 @@ +import { UNSUPPORTED_TOKENS_FAQ_URL } from '@cowprotocol/common-const' +import { TokenAmount } from '@cowprotocol/ui' +import { MouseoverTooltip } from '@cowprotocol/ui' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -// eslint-disable-next-line no-restricted-imports -// import { t } from '@lingui/macro' import ICON_GAS_FREE from 'assets/icon/gas-free.svg' import { HashLink } from 'react-router-hash-link' import styled from 'styled-components/macro' - import { MenuItem as MenuItemMod } from 'legacy/components/SearchModal/styleds' -import { MouseoverTooltip } from 'legacy/components/Tooltip' -import { UNSUPPORTED_TOKENS_FAQ_URL } from 'legacy/constants' import { TagInfo } from 'legacy/state/lists/wrappedTokenInfo' -import { TokenAmount } from 'common/pure/TokenAmount' - import CurrencyListMod, { StyledBalanceText, TagContainer } from './CurrencyListMod' import { Wrapper, Tag, TagLink } from './styled' @@ -34,8 +30,8 @@ const TOKEN_TAGS: Record = { icon: ICON_GAS_FREE, description: 'This token can be approved without spending gas, using the token Permit.', id: '1', - } -}; + }, +} export const MenuItem = styled(MenuItemMod)` &:hover { @@ -43,23 +39,17 @@ export const MenuItem = styled(MenuItemMod)` } ` -function TokenTags({ - isUnsupported, - isPermitCompatible -}: { - isUnsupported: boolean; - isPermitCompatible?: boolean; -}) { - const tagsToShow: TagInfo[] = []; +function TokenTags({ isUnsupported, isPermitCompatible }: { isUnsupported: boolean; isPermitCompatible?: boolean }) { + const tagsToShow: TagInfo[] = [] if (isUnsupported) { - tagsToShow.push(TOKEN_TAGS[Tags.UNSUPPORTED]); + tagsToShow.push(TOKEN_TAGS[Tags.UNSUPPORTED]) } else if (isPermitCompatible) { - tagsToShow.push(TOKEN_TAGS[Tags.GAS_FREE]); + tagsToShow.push(TOKEN_TAGS[Tags.GAS_FREE]) } if (tagsToShow.length === 0) { - return ; + return } return ( @@ -72,13 +62,13 @@ function TokenTags({ )} - ); + ) } -function TagDescriptor({ tags, children }: { children?: React.ReactNode; tags: TagInfo[]; }) { +function TagDescriptor({ tags, children }: { children?: React.ReactNode; tags: TagInfo[] }) { return ( - {tags.map(tag => ( + {tags.map((tag) => ( {tag.icon ? {tag.name} : null} @@ -88,7 +78,7 @@ function TagDescriptor({ tags, children }: { children?: React.ReactNode; tags: T ))} {children} - ); + ) } export function Balance({ balance }: { balance: CurrencyAmount }) { diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts index e140b9fa12..610ead735d 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/styled.ts @@ -1,8 +1,9 @@ +import { RowFixed } from '@cowprotocol/ui' + import styled from 'styled-components/macro' import { LightGreyCard } from 'legacy/components/Card' import Column from 'legacy/components/Column' -import { RowFixed } from 'legacy/components/Row' import { TagInfo } from 'legacy/state/lists/wrappedTokenInfo' import { UI } from 'common/constants/theme' @@ -11,8 +12,18 @@ import { StyledLogo } from 'common/pure/CurrencyLogo' export const Tag = styled.div<{ tag?: TagInfo }>` display: flex; align-items: center; - background: ${({ tag }) => (tag?.id === '0' ? `var(${UI.COLOR_DANGER_BG})` : tag?.id === '1' ? `var(${UI.COLOR_SUCCESS_BG})` : `var(${UI.COLOR_GREY})`)}; - color: ${({ tag }) => (tag?.id === '0' ? `var(${UI.COLOR_DANGER_TEXT})` : tag?.id === '1' ? `var(${UI.COLOR_SUCCESS_TEXT})` : `var(${UI.COLOR_TEXT1})`)}; + background: ${({ tag }) => + tag?.id === '0' + ? `var(${UI.COLOR_DANGER_BG})` + : tag?.id === '1' + ? `var(${UI.COLOR_SUCCESS_BG})` + : `var(${UI.COLOR_GREY})`}; + color: ${({ tag }) => + tag?.id === '0' + ? `var(${UI.COLOR_DANGER_TEXT})` + : tag?.id === '1' + ? `var(${UI.COLOR_SUCCESS_TEXT})` + : `var(${UI.COLOR_TEXT1})`}; font-size: 12px; font-weight: var(${UI.FONT_WEIGHT_MEDIUM}); border-radius: 4px; @@ -58,7 +69,7 @@ export const Wrapper = styled.div` color: var(${UI.COLOR_TEXT2}); font-weight: 400; } - + ${({ theme }) => theme.mediaWidth.upToSmall` max-width: 140px; `}; diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx index 867e383947..f4d26e2e04 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx @@ -1,5 +1,10 @@ import { ChangeEvent, KeyboardEvent, RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { searchByAddressAnalytics } from '@cowprotocol/analytics' +import { useTheme, useDebounce, useNetworkName, useOnClickOutside, useToggle } from '@cowprotocol/common-hooks' +import { isAddress } from '@cowprotocol/common-utils' +import { Row } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, Token } from '@uniswap/sdk-core' import { t, Trans } from '@lingui/macro' @@ -10,24 +15,19 @@ import styled, { DefaultTheme } from 'styled-components/macro' import { EventName, ModalName } from 'legacy/components/AmplitudeAnalytics/constants' import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' -import { searchByAddressAnalytics } from 'legacy/components/analytics' import Column from 'legacy/components/Column' -import Row /* RowBetween , RowFixed */ from 'legacy/components/Row' import CommonBases from 'legacy/components/SearchModal/CommonBases' import CurrencyList from 'legacy/components/SearchModal/CurrencyList' import ImportRow from 'legacy/components/SearchModal/ImportRow' import { PaddedColumn, SearchInput, Separator, PaddedRow } from 'legacy/components/SearchModal/styleds' -import { useAllTokens, useIsUserAddedToken, useSearchInactiveTokenLists, useToken } from 'legacy/hooks/Tokens' -import useDebounce from 'legacy/hooks/useDebounce' -import useNetworkName from 'legacy/hooks/useNetworkName' -import { useOnClickOutside } from 'legacy/hooks/useOnClickOutside' -import useTheme from 'legacy/hooks/useTheme' -import useToggle from 'legacy/hooks/useToggle' -import { useAllTokenBalances } from 'legacy/state/connection/hooks' +import { + useAllTokenBalances, + useAllTokens, + useIsUserAddedToken, + useSearchInactiveTokenLists, + useToken, +} from 'legacy/hooks/Tokens' import { ButtonText, CloseIcon, ThemedText } from 'legacy/theme' -import { isAddress } from 'legacy/utils' - -import { useWalletInfo } from 'modules/wallet' import { UI } from 'common/constants/theme' import { useExternalTokenSearch } from 'common/hooks/useExternalTokenSearch' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx index 82732aaf5f..568b8c912b 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/index.tsx @@ -1,3 +1,5 @@ +import { RowFixed } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { transparentize } from 'polished' import { Edit } from 'react-feather' @@ -5,7 +7,6 @@ import styled from 'styled-components/macro' import { DefaultTheme } from 'styled-components/macro' import Column from 'legacy/components/Column' -import { RowFixed } from 'legacy/components/Row' import { Separator } from 'legacy/components/SearchModal/styleds' import { IconWrapper, ThemedText } from 'legacy/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/sorting.ts b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/sorting.ts index 141f362f8a..c3fb6ccc26 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/sorting.ts +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/sorting.ts @@ -2,7 +2,7 @@ import { useMemo } from 'react' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' -import { useAllTokenBalances } from 'legacy/state/connection/hooks' +import { useAllTokenBalances } from 'legacy/hooks/Tokens' import { TokenAmounts } from 'modules/tokens' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearchModal.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearchModal.tsx index 403c1540a4..3fc6e94102 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearchModal.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearchModal.tsx @@ -1,20 +1,17 @@ import { useCallback, useEffect, useState } from 'react' +import { usePrevious, useLast } from '@cowprotocol/common-hooks' import { Currency, Token } from '@uniswap/sdk-core' import { TokenList } from '@uniswap/token-lists' -// import Modal from '../Modal' import { CurrencySearch } from 'legacy/components/SearchModal/CurrencySearch' import { ImportList } from 'legacy/components/SearchModal/ImportList' import { ImportToken } from 'legacy/components/SearchModal/ImportToken' import Manage from 'legacy/components/SearchModal/Manage' -import usePrevious from 'legacy/hooks/usePrevious' import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo' import { CowModal as Modal } from 'common/pure/Modal' -import useLast from '../../hooks/useLast' - export interface CurrencySearchModalProps { isOpen: boolean onDismiss: () => void diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/ImportListMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/ImportListMod.tsx index 3c925130d1..d047a1f786 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/ImportListMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/ImportListMod.tsx @@ -1,24 +1,25 @@ import { useCallback, useState } from 'react' +import { addListAnalytics } from '@cowprotocol/analytics' +import { useTheme } from '@cowprotocol/common-hooks' +import { ButtonPrimary } from '@cowprotocol/ui' +import { AutoRow, RowBetween, RowFixed } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { transparentize } from 'polished' import { AlertTriangle, ArrowLeft } from 'react-feather' import styled from 'styled-components/macro' -import { addListAnalytics } from 'legacy/components/analytics' -import { ButtonPrimary } from 'legacy/components/Button' import { AutoColumn } from 'legacy/components/Column' import ListLogo from 'legacy/components/ListLogo' -import { AutoRow, RowBetween, RowFixed } from 'legacy/components/Row' import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal' import { Card } from 'legacy/components/SearchModal/ManageLists' import { Checkbox, PaddedColumn, TextDot } from 'legacy/components/SearchModal/styleds' import { SectionBreak } from 'legacy/components/swap/styleds' import { useFetchListCallback } from 'legacy/hooks/useFetchListCallback' -import useTheme from 'legacy/hooks/useTheme' import { useAllLists } from 'legacy/state/lists/hooks' import { CloseIcon, ThemedText } from 'legacy/theme' -import { ExternalLink } from 'legacy/theme' import { ImportProps } from './index' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/index.tsx index b29590c17e..031b52b50c 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportList/index.tsx @@ -1,15 +1,14 @@ import { useCallback } from 'react' +import { DEFAULT_NETWORK_FOR_LISTS } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' import { TokenList } from '@uniswap/token-lists' import { useDispatch } from 'react-redux' import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal' -import { DEFAULT_NETWORK_FOR_LISTS } from 'legacy/constants/lists' import { enableList as enableListMod, removeList as removeListMod } from 'legacy/state/lists/actions' -import { useWalletInfo } from 'modules/wallet' - import { ImportList as ImportListMod } from './ImportListMod' export interface ImportProps { diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/ImportRowMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/ImportRowMod.tsx index 710e4a5256..628055712d 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/ImportRowMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/ImportRowMod.tsx @@ -1,17 +1,17 @@ import { CSSProperties } from 'react' +import { useTheme } from '@cowprotocol/common-hooks' +import { ButtonPrimary } from '@cowprotocol/ui' +import { AutoRow, RowFixed } from '@cowprotocol/ui' import { Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { CheckCircle } from 'react-feather' import styled from 'styled-components/macro' -import { ButtonPrimary } from 'legacy/components/Button' import { AutoColumn } from 'legacy/components/Column' import ListLogo from 'legacy/components/ListLogo' -import { AutoRow, RowFixed } from 'legacy/components/Row' import { useIsTokenActive, useIsUserAddedToken } from 'legacy/hooks/Tokens' -import useTheme from 'legacy/hooks/useTheme' import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo' import { ThemedText } from 'legacy/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx index a45c3c4679..24e27be063 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportRow/index.tsx @@ -1,12 +1,12 @@ import { CSSProperties } from 'react' +import { ButtonPrimary } from '@cowprotocol/ui' +import { AutoRow } from '@cowprotocol/ui' import { Token } from '@uniswap/sdk-core' import styled from 'styled-components/macro' -import { ButtonPrimary } from 'legacy/components/Button' import { StyledListLogo } from 'legacy/components/ListLogo' -import { AutoRow } from 'legacy/components/Row' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx index 8c35abf901..73fc7cca95 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx @@ -1,3 +1,6 @@ +import { useTheme } from '@cowprotocol/common-hooks' +import { ButtonPrimary } from '@cowprotocol/ui' +import { RowBetween } from '@cowprotocol/ui' import { Currency, Token } from '@uniswap/sdk-core' import { TokenList } from '@uniswap/token-lists' @@ -8,14 +11,11 @@ import styled from 'styled-components/macro' import { ElementName, Event, EventName } from 'legacy/components/AmplitudeAnalytics/constants' import { TraceEvent } from 'legacy/components/AmplitudeAnalytics/TraceEvent' -import { ButtonPrimary } from 'legacy/components/Button' import Card from 'legacy/components/Card' import { AutoColumn } from 'legacy/components/Column' -import { RowBetween } from 'legacy/components/Row' import { PaddedColumn } from 'legacy/components/SearchModal/styleds' import TokenImportCard from 'legacy/components/SearchModal/TokenImportCard' import { SectionBreak } from 'legacy/components/swap/styleds' -import useTheme from 'legacy/hooks/useTheme' import { useAddUserToken } from 'legacy/state/user/hooks' import { CloseIcon, ThemedText } from 'legacy/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx index 8d82573728..c06016c36d 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/index.tsx @@ -1,3 +1,5 @@ +import { getEtherscanLink as getExplorerLink } from '@cowprotocol/common-utils' +import { RowFixed, ExternalLink } from '@cowprotocol/ui' import { Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' @@ -8,11 +10,8 @@ import styled from 'styled-components/macro' import Card from 'legacy/components/Card' import { AutoColumn } from 'legacy/components/Column' import ListLogo from 'legacy/components/ListLogo' -import { RowFixed } from 'legacy/components/Row' import { PaddedColumn } from 'legacy/components/SearchModal/styleds' import { ThemedText } from 'legacy/theme' -import { ExternalLink } from 'legacy/theme/components' -import { getEtherscanLink as getExplorerLink } from 'legacy/utils' import { UI } from 'common/constants/theme' import { CurrencyLogo } from 'common/pure/CurrencyLogo' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/ManageMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/ManageMod.tsx index 85e4791b3f..1a186824d8 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/ManageMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/ManageMod.tsx @@ -1,10 +1,11 @@ import { useState } from 'react' +import { RowBetween } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { ArrowLeft } from 'react-feather' import { Text } from 'rebass' -import { RowBetween } from 'legacy/components/Row' import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal' import { ManageLists } from 'legacy/components/SearchModal/ManageLists' import ManageTokens from 'legacy/components/SearchModal/ManageTokens' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx index cb60a324c5..1c757d948d 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/Manage/index.tsx @@ -1,10 +1,10 @@ +import { RowBetween } from '@cowprotocol/ui' import { Token } from '@uniswap/sdk-core' import { TokenList } from '@uniswap/token-lists' import { transparentize } from 'polished' import styled from 'styled-components/macro' -import { RowBetween } from 'legacy/components/Row' import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal' import { SearchInput, Separator } from 'legacy/components/SearchModal/styleds' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx index 88fcd11ae3..6a4abd745f 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx @@ -1,39 +1,36 @@ import { ChangeEvent, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { TokenList } from '@uniswap/token-lists' +import { updateListAnalytics, removeListAnalytics, toggleListAnalytics } from '@cowprotocol/analytics' +import { useListColor, useTheme, useToggle, useOnClickOutside } from '@cowprotocol/common-hooks' +import { parseENSAddress, uriToHttp } from '@cowprotocol/common-utils' +import { Row, RowBetween, RowFixed, ButtonEmpty, ButtonPrimary, ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' +import { TokenList, Version } from '@uniswap/token-lists' import { t, Trans } from '@lingui/macro' import { CheckCircle, Settings } from 'react-feather' import { usePopper } from 'react-popper' import styled from 'styled-components/macro' -import { updateListAnalytics, removeListAnalytics, toggleListAnalytics } from 'legacy/components/analytics' -import { ButtonEmpty, ButtonPrimary } from 'legacy/components/Button' import Column, { AutoColumn } from 'legacy/components/Column' import ListLogo from 'legacy/components/ListLogo' -import Row, { RowBetween, RowFixed } from 'legacy/components/Row' import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal' import { PaddedColumn, SearchInput, Separator, SeparatorDark } from 'legacy/components/SearchModal/styleds' import Toggle from 'legacy/components/Toggle' -import { useListColor } from 'legacy/hooks/useColor' import { useFetchListCallback } from 'legacy/hooks/useFetchListCallback' -import { useOnClickOutside } from 'legacy/hooks/useOnClickOutside' -import useTheme from 'legacy/hooks/useTheme' -import useToggle from 'legacy/hooks/useToggle' import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' import { useActiveListUrls, useAllLists, useIsListActive } from 'legacy/state/lists/hooks' -import { ExternalLink, IconWrapper, LinkStyledButton, ThemedText } from 'legacy/theme' -import listVersionLabel from 'legacy/utils/listVersionLabel' - -import { useWalletInfo } from 'modules/wallet' +import { IconWrapper, LinkStyledButton, ThemedText } from 'legacy/theme' import { UI } from 'common/constants/theme' import { useConfirmationRequest } from 'common/hooks/useConfirmationRequest' -import parseENSAddress from 'lib/utils/parseENSAddress' -import uriToHttp from 'lib/utils/uriToHttp' import { ListRowProps, RowWrapper, Card } from './index' +function listVersionLabel(version: Version): string { + return `v${version.major}.${version.minor}.${version.patch}` +} + const Wrapper = styled(Column)` width: 100%; height: 100%; diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx index bd59cb5673..b43c63e955 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/index.tsx @@ -1,18 +1,17 @@ +import { UNSUPPORTED_LIST_URLS } from '@cowprotocol/common-const' +import { ButtonPrimary } from '@cowprotocol/ui' +import { Row, RowFixed, RowBetween } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { TokenList } from '@uniswap/token-lists' import { transparentize } from 'polished' import styled from 'styled-components/macro' -import { ButtonPrimary } from 'legacy/components/Button' import CardUni from 'legacy/components/Card' -import Row, { RowFixed, RowBetween } from 'legacy/components/Row' import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal' import { TextDot } from 'legacy/components/SearchModal/styleds' -import { UNSUPPORTED_LIST_URLS } from 'legacy/constants/lists' import { acceptListUpdate, removeList, disableList, enableList } from 'legacy/state/lists/actions' -import { useWalletInfo } from 'modules/wallet' - import { UI } from 'common/constants/theme' import { ManageLists as ManageListsMod, ListContainer, PopoverContainer } from './ManageListsMod' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/ManageTokensMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/ManageTokensMod.tsx index f288c3c4b8..5c8af0a5de 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/ManageTokensMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/ManageTokensMod.tsx @@ -1,26 +1,23 @@ import { ChangeEventHandler, RefObject, useCallback, useMemo, useRef, useState } from 'react' +import { useNetworkName, useTheme } from '@cowprotocol/common-hooks' +import { getEtherscanLink as getExplorerLink, isAddress } from '@cowprotocol/common-utils' +import { TokenSymbol, Row, RowBetween, RowFixed } from '@cowprotocol/ui' +import { ExternalLink, ExternalLinkIcon } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import styled from 'styled-components/macro' import Column from 'legacy/components/Column' -import Row, { RowBetween, RowFixed } from 'legacy/components/Row' import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal' import { PaddedColumn, SearchInput, Separator } from 'legacy/components/SearchModal/styleds' import { useToken } from 'legacy/hooks/Tokens' -import useNetworkName from 'legacy/hooks/useNetworkName' -import useTheme from 'legacy/hooks/useTheme' import { useRemoveUserAddedToken, useUserAddedTokens } from 'legacy/state/user/hooks' -import { ButtonText, ExternalLink, ExternalLinkIcon, ThemedText, TrashIcon } from 'legacy/theme' -import { isAddress } from 'legacy/utils' -import { getEtherscanLink as getExplorerLink } from 'legacy/utils' - -import { useWalletInfo } from 'modules/wallet' +import { ButtonText, ThemedText, TrashIcon } from 'legacy/theme' import { CurrencyLogo } from 'common/pure/CurrencyLogo' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { ImportTokensRowProps } from './index' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx index d8a85d6550..25b2642d96 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageTokens/index.tsx @@ -1,14 +1,15 @@ +import { Row, RowFixed, RowBetween } from '@cowprotocol/ui' +import { LinkIcon } from '@cowprotocol/ui' import { Token } from '@uniswap/sdk-core' import styled, { DefaultTheme } from 'styled-components/macro' import Card from 'legacy/components/Card' import Column from 'legacy/components/Column' -import Row, { RowFixed, RowBetween } from 'legacy/components/Row' import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal' import ImportRow from 'legacy/components/SearchModal/ImportRow' import { Separator } from 'legacy/components/SearchModal/styleds' -import { ButtonText, LinkIcon } from 'legacy/theme' +import { ButtonText } from 'legacy/theme' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/TokenImportCard/TokenImportCardMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/TokenImportCard/TokenImportCardMod.tsx index 97794db10d..e382e4e1da 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/TokenImportCard/TokenImportCardMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/TokenImportCard/TokenImportCardMod.tsx @@ -1,3 +1,7 @@ +import { getEtherscanLink as getExplorerLink } from '@cowprotocol/common-utils' +import { RowFixed } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' import { TokenList } from '@uniswap/token-lists' @@ -9,11 +13,7 @@ import styled, { useTheme } from 'styled-components/macro' import Card from 'legacy/components/Card' import { AutoColumn } from 'legacy/components/Column' import ListLogo from 'legacy/components/ListLogo' -import { RowFixed } from 'legacy/components/Row' -import { ExternalLink, ThemedText } from 'legacy/theme' -import { getEtherscanLink as getExplorerLink } from 'legacy/utils' - -import { useWalletInfo } from 'modules/wallet' +import { ThemedText } from 'legacy/theme' import { CurrencyLogo } from 'common/pure/CurrencyLogo' diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx index 09e2077735..652b80ed9c 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/styleds.tsx @@ -1,11 +1,10 @@ -import styled from 'styled-components/macro' +import { LoadingRows as BaseLoadingRows, RowBetween } from '@cowprotocol/ui' -import { LoadingRows as BaseLoadingRows } from 'legacy/components/Loader/styled' +import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' import { AutoColumn } from '../Column' -import { RowBetween } from '../Row' export const TextDot = styled.div` height: 3px; diff --git a/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx b/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx index 5da1bdf8ff..7d20b49b10 100644 --- a/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx @@ -1,21 +1,22 @@ import { useCallback, useContext, useRef, useState } from 'react' +import { + showExpertModeConfirmationAnalytics, + toggleExpertModeAnalytics, + toggleRecepientAddressAnalytics, +} from '@cowprotocol/analytics' +import { useOnClickOutside } from '@cowprotocol/common-hooks' +import { RowBetween, RowFixed } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { Settings } from 'react-feather' import { Text } from 'rebass' import styled, { ThemeContext } from 'styled-components/macro' -import { - showExpertModeConfirmationAnalytics, - toggleExpertModeAnalytics, - toggleRecepientAddressAnalytics, -} from 'legacy/components/analytics' import { AutoColumn } from 'legacy/components/Column' import QuestionHelper from 'legacy/components/QuestionHelper' -import { RowBetween, RowFixed } from 'legacy/components/Row' import Toggle from 'legacy/components/Toggle' import TransactionSettings from 'legacy/components/TransactionSettings' -import { useOnClickOutside } from 'legacy/hooks/useOnClickOutside' import { useModalIsOpen, useToggleSettingsMenu } from 'legacy/state/application/hooks' import { ApplicationModal } from 'legacy/state/application/reducer' import { useExpertModeManager, useRecipientToggleManager } from 'legacy/state/user/hooks' diff --git a/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx b/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx index 6b054b3bc2..c166d8cf30 100644 --- a/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Settings/index.tsx @@ -1,11 +1,10 @@ +import { RowFixed } from '@cowprotocol/ui' import { Percent } from '@uniswap/sdk-core' import { transparentize } from 'polished' import styled from 'styled-components/macro' import { WithClassName } from 'types' -import { RowFixed } from 'legacy/components/Row' - import { UI } from 'common/constants/theme' import SettingsMod, { StyledMenuButton, MenuFlyout, StyledMenuIcon, EmojiWrapper } from './SettingsMod' diff --git a/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx b/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx index 6afc897e6b..b06c382c86 100644 --- a/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Stepper/index.tsx @@ -1,8 +1,8 @@ +import CheckCircle from '@cowprotocol/assets/cow-swap/check.svg' + import { transparentize } from 'polished' import styled from 'styled-components/macro' -import CheckCircle from 'legacy/assets/cow-swap/check.svg' - import { UI } from 'common/constants/theme' export const Wrapper = styled.div<{ totalSteps: number }>` @@ -86,7 +86,11 @@ export const Step = styled.div<{ > b { color: ${({ isActiveStep, completedStep, theme }) => - completedStep ? `var(${UI.COLOR_TEXT1})` : isActiveStep ? `var(${UI.COLOR_TEXT1})` : transparentize(0.4, theme.text1)}; + completedStep + ? `var(${UI.COLOR_TEXT1})` + : isActiveStep + ? `var(${UI.COLOR_TEXT1})` + : transparentize(0.4, theme.text1)}; font-weight: ${({ isActiveStep, completedStep }) => (completedStep ? '300' : isActiveStep ? 'bold' : '300')}; text-align: center; diff --git a/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx b/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx index 598cac262a..75ff6f23cc 100644 --- a/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SwapWarnings/index.tsx @@ -1,15 +1,15 @@ import React, { useContext, useMemo } from 'react' +import { MouseoverTooltipContent } from '@cowprotocol/ui' import { Fraction } from '@uniswap/sdk-core' import { AlertTriangle } from 'react-feather' import styled, { ThemeContext } from 'styled-components/macro' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' -import { useHighFeeWarning } from 'legacy/state/swap/hooks' import TradeGp from 'legacy/state/swap/TradeGp' import { useIsDarkMode } from 'legacy/state/user/hooks' +import { useHighFeeWarning } from 'modules/swap/hooks/useSwapState' import { StyledInfoIcon } from 'modules/swap/pure/styled' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/BalanceCell.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/BalanceCell.tsx index 9f22e84b80..3c1029cba8 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/BalanceCell.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/BalanceCell.tsx @@ -1,12 +1,9 @@ +import { useTheme } from '@cowprotocol/common-hooks' +import { TokenAmount } from '@cowprotocol/ui' +import { Loader } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { Token, CurrencyAmount } from '@uniswap/sdk-core' -import Loader from 'legacy/components/Loader' -import useTheme from 'legacy/hooks/useTheme' - -import { useWalletInfo } from 'modules/wallet' - -import { TokenAmount } from 'common/pure/TokenAmount' - import { BalanceValue } from './styled' type BalanceCellProps = { diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx index a08ef71254..c87cbaecfb 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/FavouriteTokenButton.tsx @@ -1,11 +1,11 @@ import { MouseEventHandler, useCallback, useMemo } from 'react' +import { useTheme } from '@cowprotocol/common-hooks' +import { ButtonStar } from '@cowprotocol/ui' import { Token } from '@uniswap/sdk-core' import styled from 'styled-components/macro' -import { ButtonStar } from 'legacy/components/Button' -import useTheme from 'legacy/hooks/useTheme' import { useFavouriteTokens, useToggleFavouriteToken } from 'legacy/state/user/hooks' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/FiatBalanceCell.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/FiatBalanceCell.tsx index 09f9dd696c..a525a4d522 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/FiatBalanceCell.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/FiatBalanceCell.tsx @@ -1,13 +1,11 @@ +import { FiatAmount } from '@cowprotocol/ui' +import { MouseoverTooltip } from '@cowprotocol/ui' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' -import { MouseoverTooltip } from 'legacy/components/Tooltip' - import { useUsdAmount } from 'modules/usdAmount' -import { FiatAmount } from 'common/pure/FiatAmount' - import { BalanceValue, FiatValue, InfoCircle } from './styled' type FiatBalanceCellProps = { diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx index 71c5a5780e..e42ee2aed5 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTable.tsx @@ -1,16 +1,15 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useFilterTokens, usePrevious } from '@cowprotocol/common-hooks' import { Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { balanceComparator, useTokenComparator } from 'legacy/components/SearchModal/CurrencySearch/sorting' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal' -import useFilterTokens from 'legacy/hooks/useFilterTokens' -import usePrevious from 'legacy/hooks/usePrevious' import useTransactionConfirmationModal from 'legacy/hooks/useTransactionConfirmationModal' import { useToggleWalletModal } from 'legacy/state/application/hooks' +import { ConfirmOperationType } from 'legacy/state/types' import { TokenAmounts } from 'modules/tokens' diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx index 7ac7575b74..a633cc108d 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/TokensTableRow.tsx @@ -1,28 +1,24 @@ import { useCallback, useEffect, useMemo, useState } from 'react' +import EtherscanImage from '@cowprotocol/assets/cow-swap/etherscan-icon.svg' +import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' +import { usePrevious, useTheme } from '@cowprotocol/common-hooks' +import { getBlockExplorerUrl } from '@cowprotocol/common-utils' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { TokenAmount, TokenSymbol, Loader } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount, MaxUint256, Token } from '@uniswap/sdk-core' import SVG from 'react-inlinesvg' import { Link } from 'react-router-dom' -import EtherscanImage from 'legacy/assets/cow-swap/etherscan-icon.svg' -import Loader from 'legacy/components/Loader' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' -import { GP_VAULT_RELAYER } from 'legacy/constants' import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal' -import usePrevious from 'legacy/hooks/usePrevious' -import useTheme from 'legacy/hooks/useTheme' import { useTokenAllowance } from 'legacy/hooks/useTokenAllowance' -import { getBlockExplorerUrl } from 'legacy/utils' import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute' -import { useWalletInfo } from 'modules/wallet' import { Routes } from 'common/constants/routes' import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol' -import { TokenAmount } from 'common/pure/TokenAmount' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { CardsSpinner, ExtLink } from 'pages/Account/styled' import BalanceCell from './BalanceCell' @@ -40,6 +36,7 @@ import { } from './styled' import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback/useApproveCallbackMod' +import { ConfirmOperationType } from '../../state/types' type DataRowParams = { tokenData: Token diff --git a/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts b/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts index f27f6a8c10..f0eb8101d0 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/Tokens/styled.ts @@ -1,10 +1,10 @@ +import { BaseButton } from '@cowprotocol/ui' + import { transparentize } from 'polished' import { HelpCircle } from 'react-feather' import { Link } from 'react-router-dom' import styled from 'styled-components/macro' -import { BaseButton } from 'legacy/components/Button' - import { UI } from 'common/constants/theme' import { CurrencyLogo } from 'common/pure/CurrencyLogo' @@ -82,7 +82,7 @@ export const ResponsiveLogo = styled(CurrencyLogo)` height: 28px; border-radius: 28px; background: var(${UI.COLOR_CONTAINER_BG_01}); - color: var(${UI.COLOR_TEXT1})!important; // TODO: prevent styles override + color: var(${UI.COLOR_TEXT1}) !important; // TODO: prevent styles override ${({ theme }) => theme.mediaWidth.upToMedium` width: 21px; diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/DisplayLink.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/DisplayLink.tsx index 8e52480795..e8dbc87f05 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/DisplayLink.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/DisplayLink.tsx @@ -1,11 +1,12 @@ import React, { useContext } from 'react' +import { getBlockExplorerUrl, getEtherscanLink, getExplorerLabel } from '@cowprotocol/common-utils' + import { Text } from 'rebass' import { ThemeContext } from 'styled-components/macro' import { OrderStatus } from 'legacy/state/orders/actions' import { useOrder } from 'legacy/state/orders/hooks' -import { getBlockExplorerUrl, getEtherscanLink, getExplorerLabel } from 'legacy/utils' import { ExternalLinkCustom } from './styled' diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent.tsx index b85cbee668..f7f117013c 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent.tsx @@ -1,23 +1,27 @@ import React, { ReactNode, useMemo } from 'react' +import alertImage from '@cowprotocol/assets/cow-swap/alert-circle.svg' +import checkImage from '@cowprotocol/assets/cow-swap/check.svg' +import { getChainCurrencySymbols } from '@cowprotocol/common-const' +import { shortenAddress } from '@cowprotocol/common-utils' +import { ExternalLink } from '@cowprotocol/ui' +import { + getWeb3ReactConnection, + useGnosisSafeInfo, + useWalletDetails, + useWalletInfo, + getIsMetaMask, + injectedConnection, +} from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { t, Trans } from '@lingui/macro' import { CheckCircle, UserCheck } from 'react-feather' import SVG from 'react-inlinesvg' -import alertImage from 'legacy/assets/cow-swap/alert-circle.svg' -import checkImage from 'legacy/assets/cow-swap/check.svg' import { MediumAndUp, useMediaQuery } from 'legacy/hooks/useMediaQuery' -import { ExternalLink } from 'legacy/theme' -import { shortenAddress } from 'legacy/utils' -import { getChainCurrencySymbols } from 'legacy/utils/gnosis_chain/hack' import { getStatusIcon } from 'modules/account/containers/AccountDetails' -import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet' -import { getIsMetaMask } from 'modules/wallet/api/utils/connection' -import { getWeb3ReactConnection } from 'modules/wallet/web3-react/connection' -import { injectedConnection } from 'modules/wallet/web3-react/connection/injected' import { ApproveComparison, @@ -33,7 +37,8 @@ import { WalletIcon, Wrapper, } from './styled' -import { ConfirmOperationType } from './types' + +import { ConfirmOperationType } from '../../state/types' enum WalletType { SAFE, diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.cosmos.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.cosmos.tsx index 85175f9bf8..0a1630b537 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.cosmos.tsx @@ -1,14 +1,15 @@ +import { COW, GNO } from '@cowprotocol/common-const' import { OrderClass, OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import styled from 'styled-components/macro' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' -import { COW, GNO } from 'legacy/constants/tokens' -import store from 'legacy/state' import { addPendingOrder, OrderStatus } from 'legacy/state/orders/actions' +import { ConfirmOperationType } from 'legacy/state/types' import { LegacyConfirmationPendingContent } from './LegacyConfirmationPendingContent' +import { cowSwapStore } from '../../state' + const txHash = '0xe87e1d02b052daa9605abe018e8172feffd1bc38ed2284e6hhhhhh' + Date.now() const defaultProps = { @@ -40,7 +41,7 @@ const Fixtures = { ), } -store.dispatch( +cowSwapStore.dispatch( addPendingOrder({ id: txHash, chainId: 5, diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx index 321445cb45..c74ca9b696 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx @@ -1,23 +1,21 @@ import { useSetAtom } from 'jotai' import React, { ReactNode, useCallback, useEffect } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency } from '@uniswap/sdk-core' import { getActivityState, useActivityDerivedState } from 'legacy/hooks/useActivityDerivedState' import { useMultipleActivityDescriptors } from 'legacy/hooks/useRecentActivity' -import { handleFollowPendingTxPopupAtom } from 'legacy/state/application/atoms' +import { ConfirmOperationType } from 'legacy/state/types' import { useSetIsConfirmationModalOpen } from 'modules/swap/state/surplusModal' -import { useWalletInfo } from 'modules/wallet' +import { handleFollowPendingTxPopupAtom } from 'modules/wallet/state/followPendingTxPopupAtom' import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue' import { CowModal } from 'common/pure/Modal' import { TransactionSubmittedContent } from 'common/pure/TransactionSubmittedContent' import { LegacyConfirmationPendingContent } from './LegacyConfirmationPendingContent' -import { ConfirmOperationType } from './types' - -export * from './types' export interface ConfirmationModalProps { isOpen: boolean diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/styled.ts b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/styled.ts index 16e407a371..13a5b0eacb 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/styled.ts @@ -1,10 +1,12 @@ +import { RowBetween } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' + import { transparentize } from 'polished' import { Link } from 'react-router-dom' import styled, { css } from 'styled-components/macro' import { AutoColumn } from 'legacy/components/Column' -import { RowBetween } from 'legacy/components/Row' -import { CloseIcon, ExternalLink } from 'legacy/theme' +import { CloseIcon } from 'legacy/theme' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/index.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/index.tsx index 5f351f8b59..bcb94824a0 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/index.tsx @@ -1,6 +1,6 @@ +import cowMeditatingSmooth from '@cowprotocol/assets/images/cow-meditating-smoooth.svg' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import cowMeditatingSmooth from 'legacy/assets/images/cow-meditating-smoooth.svg' import { DisplayLink } from 'legacy/components/TransactionConfirmationModal/DisplayLink' import { Order } from 'legacy/state/orders/actions' diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/styled.ts b/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/styled.ts index 92b126fb5c..5dc912d358 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/TransactionExecutedContent/styled.ts @@ -1,7 +1,6 @@ -import styled from 'styled-components/macro' +import { FiatAmount, TokenAmount } from '@cowprotocol/ui' -import { FiatAmount } from 'common/pure/FiatAmount' -import { TokenAmount } from 'common/pure/TokenAmount' +import styled from 'styled-components/macro' export const ExecutedWrapper = styled.div` display: flex; diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx index e688df1d64..7b286b19a8 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/TransactionSettingsMod.tsx @@ -1,14 +1,7 @@ import { useContext, useState } from 'react' -import { Percent } from '@uniswap/sdk-core' - -import { Trans } from '@lingui/macro' -import { darken } from 'polished' -import styled, { ThemeContext } from 'styled-components/macro' - -import { orderExpirationTimeAnalytics, slippageToleranceAnalytics } from 'legacy/components/analytics' -import { AutoColumn } from 'legacy/components/Column' -import { RowBetween, RowFixed } from 'legacy/components/Row' +import { orderExpirationTimeAnalytics, slippageToleranceAnalytics } from '@cowprotocol/analytics' +import { DEFAULT_DEADLINE_FROM_NOW } from '@cowprotocol/common-const' import { DEFAULT_SLIPPAGE_BPS, HIGH_ETH_FLOW_SLIPPAGE_BIPS, @@ -20,15 +13,22 @@ import { MINIMUM_ETH_FLOW_SLIPPAGE, MINIMUM_ETH_FLOW_SLIPPAGE_BIPS, MINIMUM_ORDER_VALID_TO_TIME_SECONDS, -} from 'legacy/constants' -import { DEFAULT_DEADLINE_FROM_NOW } from 'legacy/constants/misc' +} from '@cowprotocol/common-const' +import { RowBetween, RowFixed } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' +import { Percent } from '@uniswap/sdk-core' + +import { Trans } from '@lingui/macro' +import { darken } from 'polished' +import styled, { ThemeContext } from 'styled-components/macro' + +import { AutoColumn } from 'legacy/components/Column' import { useSetUserSlippageTolerance, useUserSlippageTolerance, useUserTransactionTTL } from 'legacy/state/user/hooks' import { ThemedText } from 'legacy/theme' import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow' import { getNativeOrderDeadlineTooltip, getNonNativeOrderDeadlineTooltip } from 'modules/swap/pure/Row/RowDeadline' import { getNativeSlippageTooltip, getNonNativeSlippageTooltip } from 'modules/swap/pure/Row/RowSlippageContent' -import { useWalletInfo } from 'modules/wallet' import { UI } from 'common/constants/theme' import useNativeCurrency from 'lib/hooks/useNativeCurrency' diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx index 42b5906924..dfa63150f2 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionSettings/index.tsx @@ -1,8 +1,8 @@ +import { RowBetween, RowFixed } from '@cowprotocol/ui' + import { darken } from 'polished' import styled from 'styled-components/macro' -import { RowBetween, RowFixed } from 'legacy/components/Row' - import { UI } from 'common/constants/theme' import SlippageTabsMod, { TransactionSettingsProps, OptionCustom } from './TransactionSettingsMod' diff --git a/apps/cowswap-frontend/src/legacy/components/Version/index.tsx b/apps/cowswap-frontend/src/legacy/components/Version/index.tsx index 401903fc4a..ab78ef57e9 100644 --- a/apps/cowswap-frontend/src/legacy/components/Version/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Version/index.tsx @@ -1,15 +1,17 @@ +import { + CODE_LINK, + DEFAULT_NETWORK_FOR_LISTS, + GP_SETTLEMENT_CONTRACT_ADDRESS, + GP_VAULT_RELAYER, +} from '@cowprotocol/common-const' +import { getEtherscanLink } from '@cowprotocol/common-utils' import contractsPkg from '@cowprotocol/contracts/package.json' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import styled from 'styled-components/macro' -import { CODE_LINK, GP_VAULT_RELAYER, GP_SETTLEMENT_CONTRACT_ADDRESS } from 'legacy/constants' -import { DEFAULT_NETWORK_FOR_LISTS } from 'legacy/constants/lists' -import { ExternalLink } from 'legacy/theme' -import { getEtherscanLink } from 'legacy/utils' - -import { useWalletInfo } from 'modules/wallet' - import { UI } from 'common/constants/theme' // eslint-disable-next-line @nx/enforce-module-boundaries diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useEagerlyConnect.ts b/apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useEagerlyConnect.ts similarity index 73% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useEagerlyConnect.ts rename to apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useEagerlyConnect.ts index ddec61ccf5..cc5021f357 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useEagerlyConnect.ts +++ b/apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useEagerlyConnect.ts @@ -1,18 +1,16 @@ import { useEffect } from 'react' +import { getCurrentChainIdFromUrl, isInjectedWidget } from '@cowprotocol/common-utils' +import { + BACKFILLABLE_WALLETS, + getWeb3ReactConnection, + injectedWidgetConnection, + networkConnection, + gnosisSafeConnection, +} from '@cowprotocol/wallet' import { Connector } from '@web3-react/types' -import { useAppSelector } from 'legacy/state/hooks' - -import { BACKFILLABLE_WALLETS } from 'modules/wallet/api/types' - -import { isInjectedWidget } from 'common/utils/isInjectedWidget' -import { getCurrentChainIdFromUrl } from 'utils/getCurrentChainIdFromUrl' - -import { getWeb3ReactConnection } from '../connection' -import { injectedWidgetConnection } from '../connection/injectedWidget' -import { networkConnection } from '../connection/network' -import { gnosisSafeConnection } from '../connection/safe' +import { useAppSelector } from '../../../state/hooks' async function connect(connector: Connector) { const chainId = getCurrentChainIdFromUrl() diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useOrderedConnections.ts b/apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useOrderedConnections.ts similarity index 79% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useOrderedConnections.ts rename to apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useOrderedConnections.ts index 622c8df2cc..8203dc8bde 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useOrderedConnections.ts +++ b/apps/cowswap-frontend/src/legacy/components/Web3Provider/hooks/useOrderedConnections.ts @@ -1,13 +1,11 @@ import { useMemo } from 'react' -import { useAppSelector } from 'legacy/state/hooks' - -import { BACKFILLABLE_WALLETS, ConnectionType } from 'modules/wallet' -import { getWeb3ReactConnection } from 'modules/wallet/web3-react/connection' +import { isInjectedWidget } from '@cowprotocol/common-utils' +import { BACKFILLABLE_WALLETS, ConnectionType, getWeb3ReactConnection } from '@cowprotocol/wallet' -import { isInjectedWidget } from 'common/utils/isInjectedWidget' +import { useAppSelector } from 'legacy/state/hooks' -const SELECTABLE_WALLETS = [...BACKFILLABLE_WALLETS, ConnectionType.FORTMATIC] +const SELECTABLE_WALLETS = [...BACKFILLABLE_WALLETS] // TODO: The logic looks very similar with useEagerlyConnect export function useOrderedConnections() { diff --git a/apps/cowswap-frontend/src/legacy/components/Web3Provider/index.tsx b/apps/cowswap-frontend/src/legacy/components/Web3Provider/index.tsx index fb57ba9b28..934d45baf0 100644 --- a/apps/cowswap-frontend/src/legacy/components/Web3Provider/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Web3Provider/index.tsx @@ -1,14 +1,15 @@ import { ReactNode, useMemo } from 'react' +import { getConnectionName, Web3ReactConnection } from '@cowprotocol/wallet' import { Web3ReactHooks, Web3ReactProvider } from '@web3-react/core' import { Connector } from '@web3-react/types' -import { useOrderedConnections, useEagerlyConnect } from 'modules/wallet' -import { getConnectionName } from 'modules/wallet/api/utils/connection' -import { Web3ReactConnection } from 'modules/wallet/web3-react/types' +import { useEagerlyConnect } from './hooks/useEagerlyConnect' +import { useOrderedConnections } from './hooks/useOrderedConnections' export default function Web3Provider({ children }: { children: ReactNode }) { useEagerlyConnect() + const connections = useOrderedConnections() const connectors: [Connector, Web3ReactHooks][] = connections.map(({ hooks, connector }) => [connector, hooks]) diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts b/apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts deleted file mode 100644 index 03bab33f29..0000000000 --- a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { isEns, isProd } from 'legacy/utils/environments' - -export const PIXEL_ENABLED = isProd || isEns diff --git a/apps/cowswap-frontend/src/legacy/components/earn/styled.ts b/apps/cowswap-frontend/src/legacy/components/earn/styled.ts index d918821091..f5a38f2b46 100644 --- a/apps/cowswap-frontend/src/legacy/components/earn/styled.ts +++ b/apps/cowswap-frontend/src/legacy/components/earn/styled.ts @@ -1,8 +1,8 @@ -import styled from 'styled-components/macro' +import uImage from '@cowprotocol/assets/images/big_unicorn.png' +import noise from '@cowprotocol/assets/images/noise.png' +import xlUnicorn from '@cowprotocol/assets/images/xl_uni.png' -import uImage from 'legacy/assets/images/big_unicorn.png' -import noise from 'legacy/assets/images/noise.png' -import xlUnicorn from 'legacy/assets/images/xl_uni.png' +import styled from 'styled-components/macro' import { AutoColumn } from '../Column' diff --git a/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/hooks.tsx b/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/hooks.tsx index a9d2eea105..951d0d7237 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/hooks.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/hooks.tsx @@ -1,5 +1,6 @@ import { useMemo } from 'react' +import { TokenSymbol } from '@cowprotocol/ui' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' @@ -7,8 +8,6 @@ import { Nullish } from 'types' import { useIsSafeApprovalBundle } from 'modules/limitOrders/hooks/useIsSafeApprovalBundle' import { useIsSafeEthFlow } from 'modules/swap/hooks/useIsSafeEthFlow' -import { TokenSymbol } from 'common/pure/TokenSymbol' - export function useButtonText(slippageAdjustedSellAmount: Nullish>) { const isSafeApprovalBundle = useIsSafeApprovalBundle(slippageAdjustedSellAmount) const isSafeEthFlowBundle = useIsSafeEthFlow() diff --git a/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx index bc2d8bb3f0..fcc5b5cb53 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx @@ -1,24 +1,26 @@ import { useCallback, useMemo } from 'react' +import { TokenAmount } from '@cowprotocol/ui' +import { useWalletDetails } from '@cowprotocol/wallet' import { Percent } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { SwapModalFooter } from 'legacy/components/swap/SwapModalFooter' import SwapModalHeader from 'legacy/components/swap/SwapModalHeader' -import { ConfirmOperationType, TransactionConfirmationModal } from 'legacy/components/TransactionConfirmationModal' -import { LegacyConfirmationModalContent } from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationModalContent' +import { TransactionConfirmationModal } from 'legacy/components/TransactionConfirmationModal' import TradeGp from 'legacy/state/swap/TradeGp' +import { ConfirmOperationType } from 'legacy/state/types' import { SwapConfirmState } from 'modules/swap/state/swapConfirmAtom' -import { useWalletDetails } from 'modules/wallet' import { RateInfoParams } from 'common/pure/RateInfo' -import { TokenAmount } from 'common/pure/TokenAmount' import { TransactionErrorContent } from 'common/pure/TransactionErrorContent' import { useButtonText } from './hooks' +import { LegacyConfirmationModalContent } from '../../TransactionConfirmationModal/LegacyConfirmationModalContent' + type ConfirmSwapModalProps = { swapConfirmState: SwapConfirmState trade: TradeGp | undefined diff --git a/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx b/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx index 851afbc62b..6f67733acb 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx @@ -1,19 +1,18 @@ import React from 'react' +import { useTheme } from '@cowprotocol/common-hooks' +import { FiatAmount } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import styled from 'styled-components/macro' import QuestionHelper from 'legacy/components/QuestionHelper' import useCowBalanceAndSubsidy from 'legacy/hooks/useCowBalanceAndSubsidy' -import useTheme from 'legacy/hooks/useTheme' import TradeGp from 'legacy/state/swap/TradeGp' import { getInputReceiveAmountInfo, getOutputReceiveAmountInfo } from 'modules/swap/helpers/tradeReceiveAmount' import { ReceiveAmountInfoTooltip } from 'modules/swap/pure/ReceiveAmountInfo' -import { FiatAmount } from 'common/pure/FiatAmount' - interface FeeInformationTooltipProps { trade?: TradeGp label: React.ReactNode diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx index 5d9614d370..0c85c1d9c6 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapHeader/SwapHeaderMod.tsx @@ -1,8 +1,8 @@ +import { RowBetween, RowFixed } from '@cowprotocol/ui' import { Percent } from '@uniswap/sdk-core' import styled from 'styled-components/macro' -import { RowBetween, RowFixed } from 'legacy/components/Row' import SettingsTab from 'legacy/components/Settings' import { TradeWidgetLinks } from 'modules/application/containers/TradeWidgetLinks' diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx index 22f3794a3b..e65c8d691c 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalFooter/index.tsx @@ -1,13 +1,12 @@ import { ReactNode } from 'react' +import { ButtonSize, ButtonError, AutoRow, RowBetween, RowFixed } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { Text } from 'rebass' import styled from 'styled-components/macro' -import { ButtonError } from 'legacy/components/Button' -import { AutoRow, RowBetween, RowFixed } from 'legacy/components/Row' import { SwapCallbackError } from 'legacy/components/swap/styleds' -import { ButtonSize } from 'legacy/theme/enum' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx index a69b1e413e..5636f6f072 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx @@ -1,5 +1,8 @@ import React, { useContext, useMemo } from 'react' +import { INPUT_OUTPUT_EXPLANATION } from '@cowprotocol/common-const' +import { isAddress, shortenAddress } from '@cowprotocol/common-utils' +import { TokenAmount, TokenSymbol, RowBetween, RowFixed } from '@cowprotocol/ui' import { Percent, TradeType } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' @@ -9,15 +12,12 @@ import { Text } from 'rebass' import styled, { ThemeContext } from 'styled-components/macro' import { AutoColumn } from 'legacy/components/Column' -import { RowBetween, RowFixed } from 'legacy/components/Row' import { AdvancedSwapDetails } from 'legacy/components/swap/AdvancedSwapDetails' import { AuxInformationContainer, TruncatedText } from 'legacy/components/swap/styleds' import { WarningProps } from 'legacy/components/SwapWarnings' -import { INPUT_OUTPUT_EXPLANATION } from 'legacy/constants' -import { Field } from 'legacy/state/swap/actions' import TradeGp from 'legacy/state/swap/TradeGp' +import { Field } from 'legacy/state/types' import { ThemedText } from 'legacy/theme' -import { isAddress, shortenAddress } from 'legacy/utils' import { computeSlippageAdjustedAmounts } from 'legacy/utils/prices' import { PriceUpdatedBanner } from 'modules/trade/pure/PriceUpdatedBanner' @@ -26,8 +26,6 @@ import { useTradeUsdAmounts } from 'modules/usdAmount' import { CurrencyLogo } from 'common/pure/CurrencyLogo' import { FiatValue } from 'common/pure/FiatValue' import { RateInfo, RateInfoParams } from 'common/pure/RateInfo' -import { TokenAmount } from 'common/pure/TokenAmount' -import { TokenSymbol } from 'common/pure/TokenSymbol' import FeeInformationTooltip from '../FeeInformationTooltip' diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx index a017dec668..6aa4151c0e 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx @@ -1,5 +1,7 @@ import React from 'react' +import { useWalletDetails } from '@cowprotocol/wallet' + import { transparentize } from 'polished' import styled from 'styled-components/macro' @@ -8,7 +10,6 @@ import { SwapShowAcceptChanges } from 'legacy/components/swap/styleds' import { HighFeeWarning as HighFeeWarningBase } from 'legacy/components/SwapWarnings' import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning' -import { useWalletDetails } from 'modules/wallet' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx index e3e614b5c7..420a3b9338 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/UnsupportedCurrencyFooterMod.tsx @@ -1,19 +1,19 @@ import { useState } from 'react' +import { getEtherscanLink } from '@cowprotocol/common-utils' +import { ButtonEmpty } from '@cowprotocol/ui' +import { AutoRow, RowBetween } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import styled from 'styled-components/macro' -import { ButtonEmpty } from 'legacy/components/Button' import Card, { OutlineCard } from 'legacy/components/Card' import { AutoColumn } from 'legacy/components/Column' -import { AutoRow, RowBetween } from 'legacy/components/Row' import { useIsUnsupportedTokenGp } from 'legacy/state/lists/hooks' -import { CloseIcon, ExternalLink, ThemedText, Z_INDEX } from 'legacy/theme' -import { getEtherscanLink } from 'legacy/utils' - -import { useWalletInfo } from 'modules/wallet' +import { CloseIcon, ThemedText, Z_INDEX } from 'legacy/theme' import { UI } from 'common/constants/theme' import { CurrencyLogo } from 'common/pure/CurrencyLogo' diff --git a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/index.tsx index 377a9e79fe..8782215615 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/UnsupportedCurrencyFooter/index.tsx @@ -1,9 +1,9 @@ +import { UNSUPPORTED_TOKENS_FAQ_URL } from '@cowprotocol/common-const' + import { transparentize } from 'polished' import { HashLink } from 'react-router-hash-link' import styled from 'styled-components/macro' -import { UNSUPPORTED_TOKENS_FAQ_URL } from 'legacy/constants' - import UnsupportedCurrencyFooterMod, { UnsupportedCurrencyFooterParams, DetailsFooter, diff --git a/apps/cowswap-frontend/src/legacy/components/swap/confirmPriceImpactWithoutFee.ts b/apps/cowswap-frontend/src/legacy/components/swap/confirmPriceImpactWithoutFee.ts index a3febf01c4..89c6afecc1 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/confirmPriceImpactWithoutFee.ts +++ b/apps/cowswap-frontend/src/legacy/components/swap/confirmPriceImpactWithoutFee.ts @@ -1,8 +1,7 @@ /** Should not be used. */ +import { ALLOWED_PRICE_IMPACT_HIGH, PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN } from '@cowprotocol/common-const' import { Percent } from '@uniswap/sdk-core' -import { ALLOWED_PRICE_IMPACT_HIGH, PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN } from '../../constants/misc' - /** * Given the price impact, get user confirmation. * diff --git a/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx b/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx index 60a67186db..20444c6fe9 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/styleds.tsx @@ -1,11 +1,12 @@ import { MouseEventHandler, ReactNode } from 'react' +import { TooltipContainer } from '@cowprotocol/ui' + import { transparentize } from 'polished' import { AlertTriangle } from 'react-feather' import { Text } from 'rebass' import styled, { css } from 'styled-components/macro' -import { TooltipContainer } from 'legacy/components/Tooltip' import { ThemedText } from 'legacy/theme' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/legacy/constants/chains.ts b/apps/cowswap-frontend/src/legacy/constants/chains.ts deleted file mode 100644 index 7ae490cd42..0000000000 --- a/apps/cowswap-frontend/src/legacy/constants/chains.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { SupportedChainId } from '@cowprotocol/cow-sdk' - -/** - * Array of all the supported chain IDs - */ -export const ALL_SUPPORTED_CHAIN_IDS: SupportedChainId[] = Object.values(SupportedChainId).filter( - (id) => typeof id === 'number' -) as SupportedChainId[] diff --git a/apps/cowswap-frontend/src/legacy/constants/proposals/index.ts b/apps/cowswap-frontend/src/legacy/constants/proposals/index.ts deleted file mode 100644 index 337aa84f69..0000000000 --- a/apps/cowswap-frontend/src/legacy/constants/proposals/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const UNISWAP_GRANTS_START_BLOCK = 11473815 -export const BRAVO_START_BLOCK = 13059344 -export const ONE_BIP_START_BLOCK = 13551293 -export const POLYGON_START_BLOCK = 13786993 -export const MOONBEAN_START_BLOCK = 14732457 diff --git a/apps/cowswap-frontend/src/legacy/constants/proposals/polygon_proposal_title.ts b/apps/cowswap-frontend/src/legacy/constants/proposals/polygon_proposal_title.ts deleted file mode 100644 index 9e3897c792..0000000000 --- a/apps/cowswap-frontend/src/legacy/constants/proposals/polygon_proposal_title.ts +++ /dev/null @@ -1 +0,0 @@ -export const POLYGON_PROPOSAL_TITLE = 'Should Uniswap v3 be deployed to Polygon?' diff --git a/apps/cowswap-frontend/src/legacy/constants/proposals/uniswap_grants_proposal_description.ts b/apps/cowswap-frontend/src/legacy/constants/proposals/uniswap_grants_proposal_description.ts deleted file mode 100644 index 51347d38fd..0000000000 --- a/apps/cowswap-frontend/src/legacy/constants/proposals/uniswap_grants_proposal_description.ts +++ /dev/null @@ -1,106 +0,0 @@ -export const UNISWAP_GRANTS_PROPOSAL_DESCRIPTION = `# Uniswap Grants Program v0.1 - -*co-authored with [Ken Ng](https://twitter.com/nkennethk?lang=en)* - -## Summary: - -**This post outlines a framework for funding Uniswap ecosystem development with grants from the[ UNI Community Treasury](https://uniswap.org/blog/uni/).** The program starts small—sponsoring hackathons, [for example](https://gov.uniswap.org/c/proposal-discussion/5)—but could grow in significance over time (with renewals approved by governance) to fund core protocol development. Grants administration is a subjective process that cannot be easily automated, and thus we propose a nimble committee of 6 members —1 lead and 5 reviewers—to deliver an efficient, predictable process to applicants, such that funding can be administered without having to put each application to a vote. We propose the program start with an initial cap of $750K per quarter and a limit of 2 quarters before renewal—a sum that we feel is appropriate for an MVP relative to the size of the treasury that UNI token holders are entrusted with allocating. - -**Purpose:** - -**The mission of the UGP is to provide valuable resources to help grow the Uniswap ecosystem.** Through public discourse and inbound applications, the community will get first-hand exposure to identify and respond to the most pressing needs of the ecosystem, as well as the ability to support innovative projects expanding the capabilities of Uniswap. By rewarding talent early with developer incentives, bounties, and infrastructure support, UGP acts as a catalyst for growth and helps to maintain Uniswap as a nexus for DeFi on Ethereum. - -**Quarterly Budget:** - -* Max quarterly budget of up to $750k -* Budget and caps to be assessed every six months - -**Grant Allocation Committee:** - -* Of 6 committee members: 1 lead and 5 reviewers -* Each committee has a term of 2 quarters (6 months) after which the program needs to be renewed by UNI governance -* Committee functions as a 4 of 5 multi-sig - -**Committee Members** - -While the goals and priorities of the grant program will be thoroughly discussed and reviewed by the community through public discourse, **the decision to start UGP by operating as a small committee is to ensure that the application and decision process will be efficient and predictable, so applicants have clear objectives and timely decisions.** - -Starting with just six members enables the committee to efficiently fund projects with tight feedback loops and rapid iterations. The purpose of this committee would be to test the hypothesis that the Grants Program can successfully provide value for the UNI ecosystem before scaling the program. - -**We suggest the grants program is administered by a single lead. Here we propose Kenneth Ng, a co-author of this post**. Ken has helped grow the Ethereum Foundation Grants Program over the last two years in establishing high level priorities and adapting for the ecosystems needs. - -**The other 5 committee members should be thought of as “reviewers” — UNI community members who will keep the grants program functional by ensuring Ken is leading effectively and, of course, not absconding with funds.** Part of the reviewers job is to hold the program accountable for success (defined below) and/or return any excess funds to the UNI treasury. Reviewers are not compensated as part of this proposal as we expect their time commitment to be minimal. Compensation for the lead role is discussed below, as we expect this to be a labor intensive role. - -**Program Lead:** [Ken Ng](https://twitter.com/nkennethk?lang=en) (HL Creative Corp) -*Ecosystem Support Program at the Ethereum Foundation* - -1. Reviewer: [Jesse Walden](https://twitter.com/jessewldn) (o/b/o Unofficial LLC dba [Variant Fund](http://twitter.com/variantfund)) -*Founder and Investor at Variant Fund (holds UNI)* - -2. Reviewer: [Monet Supply](https://twitter.com/MonetSupply) -*Risk Analyst at MakerDAO* - -3. Reviewer: [Robert Leshner](https://twitter.com/rleshner) -*Founder and CEO of Compound Finance* - -4. Reviewer: [Kain Warwick](https://twitter.com/kaiynne) -*Founder of Synthetix* - -5. Reviewer: [Ashleigh Schap](https://twitter.com/ashleighschap) -*Growth Lead, Uniswap (Company)* - -## Methodology - -**1.1 Budget** - -This proposal recommends a max cap of $750K per quarter, with the ability to reevaluate biannually at each epoch (two fiscal quarters). While the UGP Grants Committee will be the decision makers around individual grants, respective budgets, roadmaps, and milestones, any top-level changes to UGP including epochs and max cap, will require full community quorum (4% approval). - -The UGP will be funded by the UNI treasury according to the[ release schedule](https://uniswap.org/blog/uni/) set out by the Uniswap team, whereby 43% of the UNI treasury is released over a four-year timeline. In Year 1 this will total to 172,000,000 UNI (~$344M as of writing). - -Taking into consideration the current landscape of ecosystem funding across Ethereum, the community would be hard-pressed to allocate even 5% of Year 1’s treasury. For context Gitcoin CLR Round 7 distributed $725k ($450k in matched) across 857 projects and YTD, Moloch has granted just under $200k but in contrast, the EF has committed to somewhere in the 8 figure range. - -**1.2 Committee Compensation** - -Operating a successful grants program takes considerable time and effort. Take, for instance, the EF Ecosystem Support Program, which has awarded grants since 2018, consists of an internal team at the Foundation as well as an ever increasing roster of community advisors in order to keep expanding and adapting to best serve the needs of the Ethereum ecosystem. While the structure of the allocation committee has six members, we propose that only the lead will be remunerated for their work in establishing the initial processes, vetting applications, and managing the program overall as this role is expected to be time consuming if the program is to be succesful. We propose that the other committee members be unpaid UNI ecosystem stakeholders who have an interest in seeing the protocol ecosystem continue to operate and grow. - -**We propose the lead be compensated 25 UNI/hr (approximately $100 USD at time of this writing) capped at 30 hours/week. This compensation, along with the quarterly budget, will be allocated to the UGP multisig from the UNI treasury**. In keeping with the committee’s commitment to the community, hours and duties will be logged publicly and transparently . - -**2.1 Priorities** - -Initially, the program aims to start narrow in scope, funding peripheral ecosystem initiatives, such as targeted bounties, hackathon sponsorships, and other low-stakes means of building out the Uniswap developer ecosystem. Over time, if the program proves effective, the grant allocations can grow in scope to include, for example, improved frontends, trading interfaces, and eventually, core protocol development. - -![|624x199](upload://vNP0APCOjiwQMurCmYI47cTLklc.png) - -With the initial priorities in mind, some effective measures for quick successes might look like: - -* Total number of projects funded -* Quarterly increase in applications -* Project engagement post-event/funding -* Overall community engagement/sentiment - -**2.2 Timeline** - -In keeping with the fast pace of the UNI ecosystem, we organize time in epochs, or two calendar quarters. Each epoch will see two funding rounds, one per quarter, after which the community can review and create proposals to improve or revamp the program as they deem fit. - -**![|624x245](upload://n56TSh5X3mt4TSqVVMFhbnZM0eM.png)** - -**Rolling Wave 1 & 2 Applications** - -* Starting in Q1 2021, UGP will start accepting applications for events looking for support in the form of bounties or prizes that in parallel can be proactively sourced. During these first two waves of funding projects, the allocation committee lead can begin laying out guardrails for continued funding - -* Considering the immediate feedback loops for the first epoch, we expect these allocation decisions to be discussed and reviewed by the larger community. Should this not be of value, the community can submit a formal governance proposal to change any piece of UGP that was not effective - -**Wave 3 & Beyond** - -* Beginning with Wave 3, there should have been enough time with impactful projects funded to be considered for follow-on funding, should it make sense. In the same vein, projects within scope will be expanded to also include those working on integrations and and other key components. - -* Beyond the second epoch, as the community helps to review and help adapt UGP to be most effective, the scope will continue to grow in order to accommodate the state of the ecosystem including that of core protocol improvements - -## Conclusion: - -**If this proposal is successfully approved, UGP will start accepting applications on a rolling basis beginning at the start of 2021.** With the phases and priorities laid out above, UGP will aim to make a significant impact by catalyzing growth and innovation in the UNI ecosystem. - -**This program is meant to be the simplest possible MVP of a Uniswap Ecosystem Grants initiative.** While the multi-sig committee comes with trust assumptions about the members, our hope is the community will approve this limited engagement to get the ball rolling in an efficient structure. **After the first epoch (2 fiscal quarters) the burden of proof will be on UGP to show empirical evidence that the program is worth continuing in its existing form and will submit to governance to renew treasury funding.** - -If this program proves successful, we hope it will inspire others to follow suit and create their own funding committees for allocating treasury capital—ideally with different specializations. -` diff --git a/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts b/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts index f158677721..27bf4f5aec 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts @@ -1,21 +1,22 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' +import { getChainInfo } from '@cowprotocol/common-const' +import { doesTokenMatchSymbolOrAddress } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, Token } from '@uniswap/sdk-core' -import { getChainInfo } from 'legacy/constants/chainInfo' import { useAllLists, useInactiveListUrls } from 'legacy/state/lists/hooks' -import { deserializeToken, useUserAddedTokens } from 'legacy/state/user/hooks' +import { deserializeToken, useFavouriteTokens, useUserAddedTokens } from 'legacy/state/user/hooks' import { TokensByAddress, tokensByAddressAtom } from 'modules/tokensList/state/tokensListAtom' -import { useWalletInfo } from 'modules/wallet' -import { useCurrencyFromMap, useTokenFromMapOrNetwork } from 'lib/hooks/useCurrency' import { getTokenFilter } from 'lib/hooks/useTokenList/filtering' -import { doesTokenMatchSymbolOrAddress } from 'utils/doesTokenMatchSymbolOrAddress' -import { TokenAddressMap, useUnsupportedTokenList } from './../state/lists/hooks' +import { useCurrencyFromMap, useTokenFromMapOrNetwork } from '../../lib/hooks/useCurrency' +import { TokenAmounts, useOnchainBalances } from '../../modules/tokens' +import { TokenAddressMap, useUnsupportedTokenList } from '../state/lists/hooks' // reduce token map into standard address <-> Token mapping, optionally include user added tokens export function useTokensFromMap(tokenMap: TokenAddressMap, includeUserAdded: boolean): { [address: string]: Token } { @@ -190,3 +191,31 @@ export function useCurrency(currencyId?: string | null): Currency | null | undef const tokens = useAllTokens() return useCurrencyFromMap(tokens, currencyId) } + +// mimics useAllBalances +export function useAllTokenBalances(): [TokenAmounts, boolean] { + const { account } = useWalletInfo() + const allTokens = useAllTokens() + // Mod, add favourite tokens to balances + const favTokens = useFavouriteTokens() + + const allTokensArray = useMemo(() => { + const favTokensObj = favTokens.reduce( + (acc, cur: Token) => { + acc[cur.address] = cur + return acc + }, + {} as { + [address: string]: Token + } + ) + + return Object.values({ ...favTokensObj, ...allTokens }) + }, [allTokens, favTokens]) + + const { isLoading, amounts } = useOnchainBalances({ + account: account ?? undefined, + tokens: allTokensArray, + }) + return [amounts ?? {}, isLoading] +} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useAccountRiskCheck.ts b/apps/cowswap-frontend/src/legacy/hooks/useAccountRiskCheck.ts deleted file mode 100644 index 29de90842e..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useAccountRiskCheck.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { useEffect } from 'react' - -import ms from 'ms.macro' - -import { ApplicationModal, setOpenModal } from 'legacy/state/application/reducer' -import { useAppDispatch } from 'legacy/state/hooks' - -import { sendEvent } from '../components/analytics/googleAnalytics' - -export default function useAccountRiskCheck(account: string | null | undefined) { - const dispatch = useAppDispatch() - - useEffect(() => { - if (account) { - const riskCheckLocalStorageKey = `risk-check-${account}` - const now = Date.now() - try { - const storedTime = localStorage.getItem(riskCheckLocalStorageKey) - const checkExpirationTime = storedTime ? parseInt(storedTime) : now - 1 - if (checkExpirationTime < Date.now()) { - const headers = new Headers({ 'Content-Type': 'application/json' }) - fetch('https://screening-worker.uniswap.workers.dev', { - method: 'POST', - headers, - body: JSON.stringify({ address: account }), - }) - .then((res) => res.json()) - .then((data) => { - if (data.block) { - dispatch(setOpenModal(ApplicationModal.BLOCKED_ACCOUNT)) - sendEvent({ - category: 'Address Screening', - action: 'blocked', - label: account, - }) - } - }) - .catch(() => dispatch(setOpenModal(null))) - } - } finally { - localStorage.setItem(riskCheckLocalStorageKey, (now + ms`7 days`).toString()) - } - } - }, [account, dispatch]) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useActiveLocale.ts b/apps/cowswap-frontend/src/legacy/hooks/useActiveLocale.ts index 92a9aa942b..65ecf2614f 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useActiveLocale.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useActiveLocale.ts @@ -1,11 +1,10 @@ import { useMemo } from 'react' -import { DEFAULT_LOCALE, SUPPORTED_LOCALES, SupportedLocale } from 'legacy/constants/locales' -import store from 'legacy/state' -import { useUserLocale } from 'legacy/state/user/hooks' +import { DEFAULT_LOCALE, SUPPORTED_LOCALES, SupportedLocale } from '@cowprotocol/common-const' +import { useParsedQueryString, parsedQueryString } from '@cowprotocol/common-hooks' -import useParsedQueryString from './useParsedQueryString' -import { parsedQueryString } from './useParsedQueryString' +import { cowSwapStore } from 'legacy/state' +import { useUserLocale } from 'legacy/state/user/hooks' /** * Given a locale string (e.g. from user agent), return the best match for corresponding SupportedLocale @@ -35,7 +34,7 @@ export function navigatorLocale(): SupportedLocale | undefined { } function storeLocale(): SupportedLocale | undefined { - return store.getState().user.userLocale ?? undefined + return cowSwapStore.getState().user.userLocale ?? undefined } export const initialLocale = diff --git a/apps/cowswap-frontend/src/legacy/hooks/useActivityDerivedState.ts b/apps/cowswap-frontend/src/legacy/hooks/useActivityDerivedState.ts index 02876405e1..1572f033de 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useActivityDerivedState.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useActivityDerivedState.ts @@ -1,17 +1,16 @@ import { useMemo } from 'react' +import { getEtherscanLink, getExplorerOrderLink } from '@cowprotocol/common-utils' +import { getSafeWebUrl } from '@cowprotocol/core' +import { useGnosisSafeInfo } from '@cowprotocol/wallet' import { SafeInfoResponse } from '@safe-global/api-kit' -import { ActivityDescriptors, ActivityStatus, ActivityType } from 'legacy/hooks/useRecentActivity' import { EnhancedTransactionDetails } from 'legacy/state/enhancedTransactions/reducer' import { Order, OrderStatus } from 'legacy/state/orders/actions' -import { getEtherscanLink } from 'legacy/utils' -import { getExplorerOrderLink } from 'legacy/utils/explorer' import { ActivityDerivedState } from 'modules/account/containers/Transaction' -import { useGnosisSafeInfo } from 'modules/wallet' -import { getSafeWebUrl } from 'api/gnosisSafe' +import { ActivityDescriptors, ActivityStatus, ActivityType } from './useRecentActivity' export function useActivityDerivedState({ chainId, diff --git a/apps/cowswap-frontend/src/legacy/hooks/useAllCurrencyCombinations.ts b/apps/cowswap-frontend/src/legacy/hooks/useAllCurrencyCombinations.ts deleted file mode 100644 index 412a82200f..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useAllCurrencyCombinations.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { useMemo } from 'react' - -import { Currency, Token } from '@uniswap/sdk-core' - -import { ADDITIONAL_BASES, BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES } from '../constants/routing' - -export function useAllCurrencyCombinations(currencyA?: Currency, currencyB?: Currency): [Token, Token][] { - const chainId = currencyA?.chainId - - const [tokenA, tokenB] = chainId ? [currencyA?.wrapped, currencyB?.wrapped] : [undefined, undefined] - - const bases: Token[] = useMemo(() => { - if (!chainId || chainId !== tokenB?.chainId) return [] - - const common = BASES_TO_CHECK_TRADES_AGAINST[chainId] ?? [] - const additionalA = tokenA ? ADDITIONAL_BASES[chainId]?.[tokenA.address] ?? [] : [] - const additionalB = tokenB ? ADDITIONAL_BASES[chainId]?.[tokenB.address] ?? [] : [] - - return [...common, ...additionalA, ...additionalB] - }, [chainId, tokenA, tokenB]) - - const basePairs: [Token, Token][] = useMemo( - () => - bases - .flatMap((base): [Token, Token][] => bases.map((otherBase) => [base, otherBase])) - // though redundant with the first filter below, that expression runs more often, so this is probably worthwhile - .filter(([t0, t1]) => !t0.equals(t1)), - [bases] - ) - - return useMemo( - () => - tokenA && tokenB - ? [ - // the direct pair - [tokenA, tokenB] as [Token, Token], - // token A against all bases - ...bases.map((base): [Token, Token] => [tokenA, base]), - // token B against all bases - ...bases.map((base): [Token, Token] => [tokenB, base]), - // each base against all bases - ...basePairs, - ] - // filter out invalid pairs comprised of the same asset (e.g. WETH<>WETH) - .filter(([t0, t1]) => !t0.equals(t1)) - // filter out duplicate pairs - .filter(([t0, t1], i, otherPairs) => { - // find the first index in the array at which there are the same 2 tokens as the current - const firstIndexInOtherPairs = otherPairs.findIndex(([t0Other, t1Other]) => { - return (t0.equals(t0Other) && t1.equals(t1Other)) || (t0.equals(t1Other) && t1.equals(t0Other)) - }) - // only accept the first occurrence of the same 2 tokens - return firstIndexInOtherPairs === i - }) - // optionally filter out some pairs for tokens with custom bases defined - .filter(([tokenA, tokenB]) => { - if (!chainId) return true - const customBases = CUSTOM_BASES[chainId] - - const customBasesA: Token[] | undefined = customBases?.[tokenA.address] - const customBasesB: Token[] | undefined = customBases?.[tokenB.address] - - if (!customBasesA && !customBasesB) return true - - if (customBasesA && !customBasesA.find((base) => tokenB.equals(base))) return false - if (customBasesB && !customBasesB.find((base) => tokenA.equals(base))) return false - - return true - }) - : [], - [tokenA, tokenB, bases, basePairs, chainId] - ) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useApeModeQueryParamReader.ts b/apps/cowswap-frontend/src/legacy/hooks/useApeModeQueryParamReader.ts deleted file mode 100644 index 8cd1cc6071..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useApeModeQueryParamReader.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useEffect } from 'react' - -import { useAppDispatch } from 'legacy/state/hooks' - -import useParsedQueryString from './useParsedQueryString' - -import { updateUserExpertMode } from '../state/user/reducer' - -export default function ApeModeQueryParamReader(): null { - useApeModeQueryParamReader() - return null -} - -function useApeModeQueryParamReader() { - const dispatch = useAppDispatch() - const { ape } = useParsedQueryString() - - useEffect(() => { - if (typeof ape !== 'string') return - if (ape === '' || ape.toLowerCase() === 'true') { - dispatch(updateUserExpertMode({ userExpertMode: true })) - } - }) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/index.ts b/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/index.ts index 406809c49f..0016fa3732 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/index.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/index.ts @@ -1,17 +1,15 @@ import { useMemo } from 'react' +import { V_COW_CONTRACT_ADDRESS } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' import { TransactionResponse } from '@ethersproject/providers' import { Currency, CurrencyAmount, MaxUint256 } from '@uniswap/sdk-core' -import { V_COW_CONTRACT_ADDRESS } from 'legacy/constants' -import { ClaimType } from 'legacy/state/claim/hooks' - -import { useWalletInfo } from 'modules/wallet' - -import { EnhancedUserClaimData } from 'pages/Claim/types' - import { ApprovalState, ApproveCallbackParams, useApproveCallback } from './useApproveCallbackMod' +import { ClaimType } from '../../state/claim/hooks/types' +import { EnhancedUserClaimData } from '../../state/claim/types' + export type OptionalApproveCallbackParams = { transactionSummary?: string modalMessage?: string diff --git a/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts b/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts index 525a5b4f12..24d3238d5e 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useApproveCallback/useApproveCallbackMod.ts @@ -1,19 +1,18 @@ import { useCallback, useMemo } from 'react' +import { useTokenContract, usePrevious } from '@cowprotocol/common-hooks' +import { calculateGasMargin } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { BigNumber } from '@ethersproject/bignumber' import { MaxUint256 } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' -import { useCurrency } from 'legacy/hooks/Tokens' -import { useTokenContract } from 'legacy/hooks/useContract' -import usePrevious from 'legacy/hooks/usePrevious' import { useTokenAllowance } from 'legacy/hooks/useTokenAllowance' import { useHasPendingApproval, useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' -import { calculateGasMargin } from 'legacy/utils/calculateGasMargin' -import { useWalletInfo } from 'modules/wallet' +import { ConfirmOperationType } from '../../state/types' +import { useCurrency } from '../Tokens' import { ApproveCallbackState, OptionalApproveCallbackParams } from './index' diff --git a/apps/cowswap-frontend/src/legacy/hooks/useArgentWalletContract.ts b/apps/cowswap-frontend/src/legacy/hooks/useArgentWalletContract.ts deleted file mode 100644 index 880bed8133..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useArgentWalletContract.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { ArgentWalletContract, ArgentWalletContractAbi } from '@cowswap/abis' - -import { useWalletInfo } from 'modules/wallet' - -import { useContract } from './useContract' -import useIsArgentWallet from './useIsArgentWallet' - -export function useArgentWalletContract(): ArgentWalletContract | null { - const { account } = useWalletInfo() - const isArgentWallet = useIsArgentWallet() - return useContract( - isArgentWallet ? account ?? undefined : undefined, - ArgentWalletContractAbi, - true - ) as ArgentWalletContract -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useColor/index.ts b/apps/cowswap-frontend/src/legacy/hooks/useColor/index.ts deleted file mode 100644 index 5f84aa9829..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useColor/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './useColorMod' diff --git a/apps/cowswap-frontend/src/legacy/hooks/useCombinedBalance.ts b/apps/cowswap-frontend/src/legacy/hooks/useCombinedBalance.ts new file mode 100644 index 0000000000..24ada8485b --- /dev/null +++ b/apps/cowswap-frontend/src/legacy/hooks/useCombinedBalance.ts @@ -0,0 +1,57 @@ +import { useMemo } from 'react' + +import { COW } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' +import { CurrencyAmount } from '@uniswap/sdk-core' + +import JSBI from 'jsbi' + +import { useVCowData } from 'legacy/state/cowToken/hooks' + +import { useTokenBalance } from 'modules/tokens/hooks/useCurrencyBalance' + +/** + * Hook that returns COW balance + */ +function useCowBalance() { + const { chainId, account } = useWalletInfo() + const cowToken = chainId ? COW[chainId] : undefined + return useTokenBalance(account || undefined, cowToken) +} + +/** + * Hook that returns combined vCOW + COW balance + vCow from locked GNO + */ +export function useCombinedBalance() { + const { chainId, account } = useWalletInfo() + const { total: vCowBalance } = useVCowData() + // const { allocated, claimed } = useCowFromLockedGnoBalances() + const cowBalance = useCowBalance() + + // const lockedGnoBalance = useMemo(() => { + // if (!allocated || !claimed) { + // return + // } + + // return JSBI.subtract(allocated.quotient, claimed.quotient) + // }, [allocated, claimed]) + + return useMemo(() => { + let tmpBalance = JSBI.BigInt(0) + + const isLoading = !!(account && (!vCowBalance /* || !lockedGnoBalance */ || !cowBalance)) + + const cow = COW[chainId] + + if (account) { + if (vCowBalance) tmpBalance = JSBI.add(tmpBalance, vCowBalance.quotient) + // if (lockedGnoBalance) tmpBalance = JSBI.add(tmpBalance, lockedGnoBalance) + if (cowBalance) tmpBalance = JSBI.add(tmpBalance, cowBalance.quotient) + } + + // TODO: check COW vs vCOW + const balance = CurrencyAmount.fromRawAmount(cow, tmpBalance) + + return { balance, isLoading } + }, [vCowBalance, /* lockedGnoBalance, */ cowBalance, chainId, account]) +} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useCowBalanceAndSubsidy.ts b/apps/cowswap-frontend/src/legacy/hooks/useCowBalanceAndSubsidy.ts index 566e0a6d1f..c6055b0d90 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useCowBalanceAndSubsidy.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useCowBalanceAndSubsidy.ts @@ -1,14 +1,14 @@ import { useMemo } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { BigNumber } from 'bignumber.js' import { COW_SUBSIDY_DATA } from 'legacy/components/CowSubsidyModal/constants' import { getDiscountFromBalance } from 'legacy/components/CowSubsidyModal/utils' -import { useCombinedBalance } from 'legacy/state/cowToken/hooks' -import { useWalletInfo } from 'modules/wallet' +import { useCombinedBalance } from './useCombinedBalance' const ZERO_BALANCE_SUBSIDY = { subsidy: { tier: 0, discount: COW_SUBSIDY_DATA[0][1] }, balance: undefined } diff --git a/apps/cowswap-frontend/src/legacy/hooks/useCurrentBlockTimestamp.ts b/apps/cowswap-frontend/src/legacy/hooks/useCurrentBlockTimestamp.ts index 0198ea62c8..701b902783 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useCurrentBlockTimestamp.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useCurrentBlockTimestamp.ts @@ -1,11 +1,10 @@ import { useMemo } from 'react' +import { useInterfaceMulticall } from '@cowprotocol/common-hooks' import { BigNumber } from '@ethersproject/bignumber' import { useSingleCallResult } from 'lib/hooks/multicall' -import { useInterfaceMulticall } from './useContract' - // gets the current timestamp from the blockchain export default function useCurrentBlockTimestamp(): BigNumber | undefined { const multicall = useInterfaceMulticall() diff --git a/apps/cowswap-frontend/src/legacy/hooks/useENSAddress.ts b/apps/cowswap-frontend/src/legacy/hooks/useENSAddress.ts deleted file mode 100644 index dacd96b5b5..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useENSAddress.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { useMemo } from 'react' - -import { safeNamehash } from 'legacy/utils/safeNamehash' - -import { useSingleCallResult } from 'lib/hooks/multicall' - -import { useENSRegistrarContract, useENSResolverContract } from './useContract' -import useDebounce from './useDebounce' - -import isZero from '../utils/isZero' - -/** - * Does a lookup for an ENS name to find its address. - */ -export default function useENSAddress(ensName?: string | null): { loading: boolean; address: string | null } { - const debouncedName = useDebounce(ensName, 200) - const ensNodeArgument = useMemo( - () => [debouncedName === null ? undefined : safeNamehash(debouncedName)], - [debouncedName] - ) - const registrarContract = useENSRegistrarContract(false) - const resolverAddress = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument) - const resolverAddressResult = resolverAddress.result?.[0] - const resolverContract = useENSResolverContract( - resolverAddressResult && !isZero(resolverAddressResult) ? resolverAddressResult : undefined, - false - ) - const addr = useSingleCallResult(resolverContract, 'addr', ensNodeArgument) - - const changed = debouncedName !== ensName - return useMemo( - () => ({ - address: changed ? null : addr.result?.[0] ?? null, - loading: changed || resolverAddress.loading || addr.loading, - }), - [addr.loading, addr.result, changed, resolverAddress.loading] - ) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useENSAvatar.ts b/apps/cowswap-frontend/src/legacy/hooks/useENSAvatar.ts deleted file mode 100644 index f53e194dd1..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useENSAvatar.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { useEffect, useMemo, useState } from 'react' - -import { BigNumber } from '@ethersproject/bignumber' -import { hexZeroPad } from '@ethersproject/bytes' -import { namehash } from '@ethersproject/hash' - -import { safeNamehash } from 'legacy/utils/safeNamehash' - -import { useWalletInfo } from 'modules/wallet' - -import { fetchWithBackoff } from 'common/utils/fetch' -import { useSingleCallResult } from 'lib/hooks/multicall' -import uriToHttp from 'lib/utils/uriToHttp' - -import { useENSRegistrarContract, useENSResolverContract, useERC1155Contract, useERC721Contract } from './useContract' -import useDebounce from './useDebounce' -import useENSName from './useENSName' - -import { isAddress } from '../utils' -import isZero from '../utils/isZero' - -/** - * Returns the ENS avatar URI, if available. - * Spec: https://gist.github.com/Arachnid/9db60bd75277969ee1689c8742b75182. - */ -export default function useENSAvatar( - address?: string, - enforceOwnership = true -): { avatar: string | null; loading: boolean } { - const debouncedAddress = useDebounce(address, 200) - const node = useMemo(() => { - if (!debouncedAddress || !isAddress(debouncedAddress)) return undefined - return namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`) - }, [debouncedAddress]) - - const addressAvatar = useAvatarFromNode(node) - const ENSName = useENSName(address).ENSName - const nameAvatar = useAvatarFromNode(ENSName === null ? undefined : safeNamehash(ENSName)) - let avatar = addressAvatar.avatar || nameAvatar.avatar - - const nftAvatar = useAvatarFromNFT(avatar, enforceOwnership) - avatar = nftAvatar.avatar || avatar - - const http = avatar && uriToHttp(avatar)[0] - - const changed = debouncedAddress !== address - return useMemo( - () => ({ - avatar: changed ? null : http ?? null, - loading: changed || addressAvatar.loading || nameAvatar.loading || nftAvatar.loading, - }), - [addressAvatar.loading, changed, http, nameAvatar.loading, nftAvatar.loading] - ) -} - -function useAvatarFromNode(node?: string): { avatar?: string; loading: boolean } { - const nodeArgument = useMemo(() => [node], [node]) - const textArgument = useMemo(() => [node, 'avatar'], [node]) - const registrarContract = useENSRegistrarContract(false) - const resolverAddress = useSingleCallResult(registrarContract, 'resolver', nodeArgument) - const resolverAddressResult = resolverAddress.result?.[0] - const resolverContract = useENSResolverContract( - resolverAddressResult && !isZero(resolverAddressResult) ? resolverAddressResult : undefined, - false - ) - const avatar = useSingleCallResult(resolverContract, 'text', textArgument) - - return useMemo( - () => ({ - avatar: avatar.result?.[0], - loading: resolverAddress.loading || avatar.loading, - }), - [avatar.loading, avatar.result, resolverAddress.loading] - ) -} - -function useAvatarFromNFT(nftUri = '', enforceOwnership: boolean): { avatar?: string; loading: boolean } { - const parts = nftUri.toLowerCase().split(':') - const protocol = parts[0] - // ignore the chain from eip155 - // TODO: when we are able, pull only from the specified chain - const [, erc] = parts[1]?.split('/') ?? [] - const [contractAddress, id] = parts[2]?.split('/') ?? [] - const isERC721 = protocol === 'eip155' && erc === 'erc721' - const isERC1155 = protocol === 'eip155' && erc === 'erc1155' - const erc721 = useERC721Uri(isERC721 ? contractAddress : undefined, id, enforceOwnership) - const erc1155 = useERC1155Uri(isERC1155 ? contractAddress : undefined, id, enforceOwnership) - const uri = erc721.uri || erc1155.uri - const http = uri && uriToHttp(uri)[0] - - const [loading, setLoading] = useState(false) - const [avatar, setAvatar] = useState(undefined) - useEffect(() => { - setAvatar(undefined) - if (http) { - setLoading(true) - fetchWithBackoff(http) - .then((res) => res.json()) - .then(({ image }) => { - setAvatar(image) - }) - .catch((e) => console.warn(e)) - .finally(() => { - setLoading(false) - }) - } - }, [http]) - - return useMemo( - () => ({ avatar, loading: erc721.loading || erc1155.loading || loading }), - [avatar, erc1155.loading, erc721.loading, loading] - ) -} - -function useERC721Uri( - contractAddress: string | undefined, - id: string | undefined, - enforceOwnership: boolean -): { uri?: string; loading: boolean } { - const idArgument = useMemo(() => [id], [id]) - const { account } = useWalletInfo() - const contract = useERC721Contract(contractAddress) - const owner = useSingleCallResult(contract, 'ownerOf', idArgument) - const uri = useSingleCallResult(contract, 'tokenURI', idArgument) - return useMemo( - () => ({ - uri: !enforceOwnership || account === owner.result?.[0] ? uri.result?.[0] : undefined, - loading: owner.loading || uri.loading, - }), - [account, enforceOwnership, owner.loading, owner.result, uri.loading, uri.result] - ) -} - -function useERC1155Uri( - contractAddress: string | undefined, - id: string | undefined, - enforceOwnership: boolean -): { uri?: string; loading: boolean } { - const { account } = useWalletInfo() - const idArgument = useMemo(() => [id], [id]) - const accountArgument = useMemo(() => [account || '', id], [account, id]) - const contract = useERC1155Contract(contractAddress) - const balance = useSingleCallResult(contract, 'balanceOf', accountArgument) - const uri = useSingleCallResult(contract, 'uri', idArgument) - // ERC-1155 allows a generic {id} in the URL, so prepare to replace if relevant, - // in lowercase hexadecimal (with no 0x prefix) and leading zero padded to 64 hex characters. - const idHex = getIdHex(id) - return useMemo( - () => ({ - uri: !enforceOwnership || balance.result?.[0] > 0 ? uri.result?.[0]?.replaceAll('{id}', idHex) : undefined, - loading: balance.loading || uri.loading, - }), - [balance.loading, balance.result, enforceOwnership, uri.loading, uri.result, idHex] - ) -} - -function getIdHex(id: string | undefined): string | undefined { - try { - return id ? hexZeroPad(BigNumber.from(id).toHexString(), 32).substring(2) : id - } catch (e) { - console.log(`Couldn't get id hex from id: ${id}`, e) - - return undefined - } -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useENSContentHash.ts b/apps/cowswap-frontend/src/legacy/hooks/useENSContentHash.ts deleted file mode 100644 index 9c07f471df..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useENSContentHash.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { useMemo } from 'react' - -import { safeNamehash } from 'legacy/utils/safeNamehash' - -import { useSingleCallResult } from 'lib/hooks/multicall' - -import { useENSRegistrarContract, useENSResolverContract } from './useContract' - -import isZero from '../utils/isZero' - -/** - * Does a lookup for an ENS name to find its contenthash. - */ -export default function useENSContentHash(ensName?: string | null): { loading: boolean; contenthash: string | null } { - const ensNodeArgument = useMemo(() => [ensName === null ? undefined : safeNamehash(ensName)], [ensName]) - const registrarContract = useENSRegistrarContract(false) - const resolverAddressResult = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument) - const resolverAddress = resolverAddressResult.result?.[0] - const resolverContract = useENSResolverContract( - resolverAddress && isZero(resolverAddress) ? undefined : resolverAddress, - false - ) - const contenthash = useSingleCallResult(resolverContract, 'contenthash', ensNodeArgument) - - return useMemo( - () => ({ - contenthash: contenthash.result?.[0] ?? null, - loading: resolverAddressResult.loading || contenthash.loading, - }), - [contenthash.loading, contenthash.result, resolverAddressResult.loading] - ) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useENSName.ts b/apps/cowswap-frontend/src/legacy/hooks/useENSName.ts deleted file mode 100644 index a745544073..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useENSName.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { useMemo } from 'react' - -import { namehash } from '@ethersproject/hash' - -import { useSingleCallResult } from 'lib/hooks/multicall' - -import { useENSRegistrarContract, useENSResolverContract } from './useContract' -import useDebounce from './useDebounce' -import useENSAddress from './useENSAddress' - -import { isAddress } from '../utils' -import isZero from '../utils/isZero' - -/** - * Does a reverse lookup for an address to find its ENS name. - * Note this is not the same as looking up an ENS name to find an address. - */ -export default function useENSName(address?: string): { ENSName: string | null; loading: boolean } { - const debouncedAddress = useDebounce(address, 200) - const ensNodeArgument = useMemo(() => { - if (!debouncedAddress || !isAddress(debouncedAddress)) return [undefined] - return [namehash(`${debouncedAddress.toLowerCase().substr(2)}.addr.reverse`)] - }, [debouncedAddress]) - const registrarContract = useENSRegistrarContract(false) - const resolverAddress = useSingleCallResult(registrarContract, 'resolver', ensNodeArgument) - const resolverAddressResult = resolverAddress.result?.[0] - const resolverContract = useENSResolverContract( - resolverAddressResult && !isZero(resolverAddressResult) ? resolverAddressResult : undefined, - false - ) - const nameCallRes = useSingleCallResult(resolverContract, 'name', ensNodeArgument) - const name = nameCallRes.result?.[0] - - /* ENS does not enforce that an address owns a .eth domain before setting it as a reverse proxy - and recommends that you perform a match on the forward resolution - see: https://docs.ens.domains/dapp-developer-guide/resolving-names#reverse-resolution - */ - const fwdAddr = useENSAddress(name) - const checkedName = address === fwdAddr?.address ? name : null - - const changed = debouncedAddress !== address - return useMemo( - () => ({ - ENSName: changed ? null : checkedName, - loading: changed || resolverAddress.loading || nameCallRes.loading, - }), - [changed, nameCallRes.loading, checkedName, resolverAddress.loading] - ) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useErrorMessageAndModal.tsx b/apps/cowswap-frontend/src/legacy/hooks/useErrorMessageAndModal.tsx index 70633e00d8..b7a659aa9c 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useErrorMessageAndModal.tsx +++ b/apps/cowswap-frontend/src/legacy/hooks/useErrorMessageAndModal.tsx @@ -1,36 +1,7 @@ import { useMemo, useState } from 'react' -import { ErrorMessageProps, SwapCallbackError } from 'legacy/components/swap/styleds' - import useTransactionErrorModal from './useTransactionErrorModal' -/** - * @description hook for getting CoW Swap error and handling them visually - * @description ErrorMessage component accepts an error message to override exported error state, and a close option - * @returns returns object: { error, setError, ErrorMessage } => error message, error message setter, and our ErrorMessage component - */ -export function useErrorMessage() { - const [internalError, setError] = useState() - - return useMemo(() => { - const handleCloseError = () => setError(undefined) - - return { - error: internalError, - handleSetError: setError, - ErrorMessage: function ErrorMessage({ - error = internalError, - showClose = false, - ...rest - }: Pick) { - return error ? ( - - ) : null - }, - } - }, [internalError]) -} - export function useErrorModal() { const [internalError, setInternalError] = useState() const { openModal, closeModal, TransactionErrorModal } = useTransactionErrorModal() diff --git a/apps/cowswap-frontend/src/legacy/hooks/useFavouriteOrCommonTokens.tsx b/apps/cowswap-frontend/src/legacy/hooks/useFavouriteOrCommonTokens.tsx index 8b0aa5d85b..ed8f8f8f4d 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useFavouriteOrCommonTokens.tsx +++ b/apps/cowswap-frontend/src/legacy/hooks/useFavouriteOrCommonTokens.tsx @@ -1,9 +1,9 @@ import { useMemo } from 'react' -import { COMMON_BASES } from 'legacy/constants/routing' -import { useFavouriteTokens } from 'legacy/state/user/hooks' +import { COMMON_BASES } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' -import { useWalletInfo } from 'modules/wallet' +import { useFavouriteTokens } from 'legacy/state/user/hooks' export function useFavouriteOrCommonTokens() { const { chainId } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts b/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts index 00f7e0fc7e..dfc39abab8 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts @@ -1,17 +1,16 @@ import { useCallback } from 'react' +import { MAINNET_PROVIDER } from '@cowprotocol/common-const' +import { resolveENSContentHash } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { TokenList } from '@uniswap/token-lists' import { nanoid } from '@reduxjs/toolkit' -import { MAINNET_PROVIDER } from 'legacy/constants/networks' import { useAppDispatch } from 'legacy/state/hooks' import { fetchTokenList } from 'legacy/state/lists/actions' -import { useWalletInfo } from 'modules/wallet' - import getTokenList from 'lib/hooks/useTokenList/fetchTokenList' -import resolveENSContentHash from 'lib/utils/resolveENSContentHash' export function useFetchListCallback(): (listUrl: string, sendDispatch?: boolean) => Promise { const dispatch = useAppDispatch() diff --git a/apps/cowswap-frontend/src/legacy/hooks/useGasPrice.ts b/apps/cowswap-frontend/src/legacy/hooks/useGasPrice.ts index ebfcfbdf56..327f0fa5b2 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useGasPrice.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useGasPrice.ts @@ -1,12 +1,12 @@ import { useMemo } from 'react' +import { useContract } from '@cowprotocol/common-hooks' +import { useENSAddress } from '@cowprotocol/ens' + import JSBI from 'jsbi' import { useSingleCallResult } from 'lib/hooks/multicall' -import { useContract } from './useContract' -import useENSAddress from './useENSAddress' - const CHAIN_DATA_ABI = [ { inputs: [], diff --git a/apps/cowswap-frontend/src/legacy/hooks/useGetSafeInfo.ts b/apps/cowswap-frontend/src/legacy/hooks/useGetSafeInfo.ts index 9ab23ace1b..3f8fdedf1b 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useGetSafeInfo.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useGetSafeInfo.ts @@ -1,16 +1,13 @@ import { useCallback } from 'react' +import { retry, RetryOptions } from '@cowprotocol/common-utils' +import { getSafeTransaction } from '@cowprotocol/core' +import { useWalletInfo } from '@cowprotocol/wallet' import { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types' import { useWeb3React } from '@web3-react/core' import { RetryResult } from 'types' -import { retry, RetryOptions } from 'legacy/utils/retry' - -import { useWalletInfo } from 'modules/wallet' - -import { getSafeTransaction } from 'api/gnosisSafe' - const DEFAULT_RETRY_OPTIONS: RetryOptions = { n: 3, minWait: 1000, maxWait: 3000 } export type GetSafeInfo = (hash: string) => RetryResult diff --git a/apps/cowswap-frontend/src/legacy/hooks/useHttpLocations.ts b/apps/cowswap-frontend/src/legacy/hooks/useHttpLocations.ts index 688e25aba1..20f04ebe38 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useHttpLocations.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useHttpLocations.ts @@ -1,10 +1,7 @@ import { useMemo } from 'react' -import contenthashToUri from 'lib/utils/contenthashToUri' -import parseENSAddress from 'lib/utils/parseENSAddress' -import uriToHttp from 'lib/utils/uriToHttp' - -import useENSContentHash from './useENSContentHash' +import { contenthashToUri, parseENSAddress, uriToHttp } from '@cowprotocol/common-utils' +import { useENSContentHash } from '@cowprotocol/ens' export default function useHttpLocations(uri: string | undefined): string[] { const ens = useMemo(() => (uri ? parseENSAddress(uri) : undefined), [uri]) diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsActiveWallet.ts b/apps/cowswap-frontend/src/legacy/hooks/useIsActiveWallet.ts index b4cad5ac9d..5034ca64f9 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useIsActiveWallet.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useIsActiveWallet.ts @@ -1,9 +1,8 @@ +import { Web3ReactConnection } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { useSelectedWallet } from 'legacy/state/user/hooks' -import { Web3ReactConnection } from 'modules/wallet/web3-react/types' - export const useIsActiveWallet = (connection: Web3ReactConnection) => { const { account } = useWeb3React() diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsAmbireWallet.ts b/apps/cowswap-frontend/src/legacy/hooks/useIsAmbireWallet.ts deleted file mode 100644 index c817985c2f..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useIsAmbireWallet.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { useWalletMetaData } from 'modules/wallet' -import { getIsAmbireWallet } from 'modules/wallet/api/utils/connection' - -export default function useIsAmbireWallet(): boolean { - const { walletName } = useWalletMetaData() - - return getIsAmbireWallet(walletName) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsArgentWallet.ts b/apps/cowswap-frontend/src/legacy/hooks/useIsArgentWallet.ts deleted file mode 100644 index 8e10102a9a..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useIsArgentWallet.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { useMemo } from 'react' - -import { useWalletInfo } from 'modules/wallet' - -import { NEVER_RELOAD, useSingleCallResult } from 'lib/hooks/multicall' - -import { useArgentWalletDetectorContract } from './useContract' - -export default function useIsArgentWallet(): boolean { - const { account } = useWalletInfo() - const argentWalletDetector = useArgentWalletDetectorContract() - const inputs = useMemo(() => [account ?? undefined], [account]) - const call = useSingleCallResult(argentWalletDetector, 'isArgentWallet', inputs, NEVER_RELOAD) - return Boolean(call?.result?.[0]) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts b/apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts index fac7bceb86..607de3afcb 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts @@ -2,7 +2,7 @@ import { useMemo } from 'react' import { Currency } from '@uniswap/sdk-core' -import { useUnsupportedTokens } from 'legacy/hooks/Tokens' +import { useUnsupportedTokens } from './Tokens' /** * Returns true if the input currency or output currency cannot be traded in the interface diff --git a/apps/cowswap-frontend/src/legacy/hooks/useLocationLinkProps.ts b/apps/cowswap-frontend/src/legacy/hooks/useLocationLinkProps.ts deleted file mode 100644 index d812001598..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useLocationLinkProps.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { useMemo } from 'react' - -import { LocationDescriptor } from 'history' -import { stringify } from 'qs' -import { useLocation } from 'react-router-dom' - -import { SupportedLocale } from 'legacy/constants/locales' -import useParsedQueryString from 'legacy/hooks/useParsedQueryString' - -import { useActiveLocale } from './useActiveLocale' - -import { sendEvent } from '../components/analytics/googleAnalytics' - -export function useLocationLinkProps(locale: SupportedLocale | null): { - to?: LocationDescriptor - onClick?: () => void -} { - const location = useLocation() - const qs = useParsedQueryString() - const activeLocale = useActiveLocale() - - return useMemo( - () => - !locale - ? {} - : { - to: { - ...location, - search: stringify({ ...qs, lng: locale }), - }, - onClick: () => { - sendEvent({ - category: 'Localization', - action: 'Switch Locale', - label: `${activeLocale} -> ${locale}`, - }) - }, - }, - [location, qs, activeLocale, locale] - ) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useNetworkName.ts b/apps/cowswap-frontend/src/legacy/hooks/useNetworkName.ts deleted file mode 100644 index a25b5b1adf..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useNetworkName.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useMemo } from 'react' - -import { CHAIN_INFO } from 'legacy/constants/chainInfo' - -import { useWalletInfo } from 'modules/wallet' - -export default function useNetworkName(): string | undefined { - const { chainId } = useWalletInfo() - - return useMemo(() => { - return CHAIN_INFO[chainId].label || '' - }, [chainId]) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/usePriceImpact/useFiatValuePriceImpact.ts b/apps/cowswap-frontend/src/legacy/hooks/usePriceImpact/useFiatValuePriceImpact.ts index e0561dcd3a..519cc9db61 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/usePriceImpact/useFiatValuePriceImpact.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/usePriceImpact/useFiatValuePriceImpact.ts @@ -1,11 +1,10 @@ +import { ONE_HUNDRED_PERCENT } from '@cowprotocol/common-const' +import { useDebounce } from '@cowprotocol/common-hooks' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import JSBI from 'jsbi' import ms from 'ms.macro' -import { ONE_HUNDRED_PERCENT } from 'legacy/constants/misc' -import useDebounce from 'legacy/hooks/useDebounce' - import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' import { useTradeUsdAmounts } from 'modules/usdAmount' diff --git a/apps/cowswap-frontend/src/legacy/hooks/useRecentActivity.ts b/apps/cowswap-frontend/src/legacy/hooks/useRecentActivity.ts index 435fcfb60f..1f653b49e0 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useRecentActivity.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useRecentActivity.ts @@ -1,17 +1,15 @@ import { useMemo } from 'react' +import { MAXIMUM_ORDERS_TO_DISPLAY } from '@cowprotocol/common-const' +import { getDateTimestamp } from '@cowprotocol/common-utils' import { OrderClass, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' -import { MAXIMUM_ORDERS_TO_DISPLAY } from 'legacy/constants' import { isTransactionRecent, useAllTransactions, useTransactionsByHash } from 'legacy/state/enhancedTransactions/hooks' import { EnhancedTransactionDetails } from 'legacy/state/enhancedTransactions/reducer' import { Order, OrderStatus } from 'legacy/state/orders/actions' import { useCombinedPendingOrders, useOrder, useOrders, useOrdersById } from 'legacy/state/orders/hooks' -import { useWalletInfo } from 'modules/wallet' - -import { getDateTimestamp } from 'utils/time' - export interface AddedOrder extends Order { addedTime: number } diff --git a/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx b/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx index 26ddeca6c9..95ff6ea1f0 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx +++ b/apps/cowswap-frontend/src/legacy/hooks/useRefetchPriceCallback.tsx @@ -1,9 +1,18 @@ import { useCallback } from 'react' +import { isOnline } from '@cowprotocol/common-hooks' +import { + CancelableResult, + onlyResolvesLast, + getPromiseFulfilledValue, + isPromiseFulfilled, + registerOnWindow, + calculateValidTo, + getQuoteUnsupportedToken, +} from '@cowprotocol/common-utils' import { PriceQuality } from '@cowprotocol/cow-sdk' import { useGetGpPriceStrategy } from 'legacy/hooks/useGetGpPriceStrategy' -import { isOnline } from 'legacy/hooks/useIsOnline' import { AddGpUnsupportedTokenParams } from 'legacy/state/lists/actions' import { useAddGpUnsupportedToken, @@ -13,9 +22,8 @@ import { import { QuoteError } from 'legacy/state/price/actions' import { useQuoteDispatchers } from 'legacy/state/price/hooks' import { QuoteInformationObject } from 'legacy/state/price/reducer' +import { LegacyFeeQuoteParams, LegacyQuoteParams } from 'legacy/state/price/types' import { useUserTransactionTTL } from 'legacy/state/user/hooks' -import { CancelableResult, onlyResolvesLast } from 'legacy/utils/async' -import { getPromiseFulfilledValue, isPromiseFulfilled, registerOnWindow } from 'legacy/utils/misc' import { getBestQuote, getFastQuote, QuoteResult } from 'legacy/utils/price' import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow' @@ -26,9 +34,6 @@ import GpQuoteError, { GpQuoteErrorDetails, isValidQuoteError, } from 'api/gnosisProtocol/errors/QuoteError' -import { LegacyFeeQuoteParams, LegacyQuoteParams } from 'api/gnosisProtocol/legacy/types' -import { getQuoteUnsupportedToken } from 'utils/getQuoteUnsupportedToken' -import { calculateValidTo } from 'utils/time' interface HandleQuoteErrorParams { quoteData: QuoteInformationObject | LegacyFeeQuoteParams diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTheme.ts b/apps/cowswap-frontend/src/legacy/hooks/useTheme.ts deleted file mode 100644 index eca5cc2471..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useTheme.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useContext } from 'react' - -import { ThemeContext } from 'styled-components/macro' - -export default function useTheme() { - return useContext(ThemeContext) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTokenAllowance.ts b/apps/cowswap-frontend/src/legacy/hooks/useTokenAllowance.ts index 673d35f939..0de703a8f2 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useTokenAllowance.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useTokenAllowance.ts @@ -1,13 +1,12 @@ import { useMemo } from 'react' +import { useTokenContract } from '@cowprotocol/common-hooks' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { Nullish } from 'types' import { useSingleCallResult } from 'lib/hooks/multicall' -import { useTokenContract } from './useContract' - export function useTokenAllowance( token: Nullish, owner?: string, diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTokenInfoFromActiveList.ts b/apps/cowswap-frontend/src/legacy/hooks/useTokenInfoFromActiveList.ts deleted file mode 100644 index 788cd14f2c..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useTokenInfoFromActiveList.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useMemo } from 'react' - -import { Currency } from '@uniswap/sdk-core' - -import { useCombinedActiveList } from 'legacy/state/lists/hooks' - -import { useWalletInfo } from 'modules/wallet' - -/** - * Returns a WrappedTokenInfo from the active token lists when possible, - * or the passed token otherwise. */ -export function useTokenInfoFromActiveList(currency: Currency) { - const { chainId } = useWalletInfo() - const activeList = useCombinedActiveList() - - return useMemo(() => { - if (!chainId) return - if (currency.isNative) return currency - - try { - return activeList[chainId][currency.wrapped.address].token - } catch (e: any) { - return currency - } - }, [activeList, chainId, currency]) -} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts b/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts index 4a1acbf487..a1978de686 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useTokenLazy.ts @@ -1,16 +1,15 @@ import { useCallback } from 'react' -import { Erc20 } from '@cowswap/abis' +import { Erc20 } from '@cowprotocol/abis' +import { getBytes32TokenContract, getTokenContract } from '@cowprotocol/common-hooks' +import { retry } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { Contract } from '@ethersproject/contracts' import { JsonRpcProvider } from '@ethersproject/providers' import { Token } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' -import { getBytes32TokenContract, getTokenContract } from 'legacy/hooks/useContract' import { useAddUserToken } from 'legacy/state/user/hooks' -import { retry } from 'legacy/utils/retry' - -import { useWalletInfo } from 'modules/wallet' import { parseStringOrBytes32 } from 'lib/hooks/useCurrency' diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTotalSupply.ts b/apps/cowswap-frontend/src/legacy/hooks/useTotalSupply.ts index 070dfc2571..87b1b9db60 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useTotalSupply.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useTotalSupply.ts @@ -1,11 +1,10 @@ import { useMemo } from 'react' +import { useTokenContract } from '@cowprotocol/common-hooks' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { useSingleCallResult } from 'lib/hooks/multicall' -import { useTokenContract } from './useContract' - // returns undefined if input token is undefined, or fails to get token contract, // or contract total supply cannot be fetched export function useTotalSupply(token?: Currency): CurrencyAmount | undefined { diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTransactionConfirmationModal.tsx b/apps/cowswap-frontend/src/legacy/hooks/useTransactionConfirmationModal.tsx index 574eac9894..157b2f0c1a 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useTransactionConfirmationModal.tsx +++ b/apps/cowswap-frontend/src/legacy/hooks/useTransactionConfirmationModal.tsx @@ -1,9 +1,11 @@ import { useState, useCallback } from 'react' -import { TransactionConfirmationModal, ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' +import { TransactionConfirmationModal } from 'legacy/components/TransactionConfirmationModal' import { useOpenModal, useCloseModals, useModalIsOpen } from 'legacy/state/application/hooks' import { ApplicationModal } from 'legacy/state/application/reducer' +import { ConfirmOperationType } from '../state/types' + export default function useTransactionConfirmationModal( defaultOperationType: ConfirmOperationType = ConfirmOperationType.WRAP_ETHER ) { diff --git a/apps/cowswap-frontend/src/legacy/hooks/useWrapCallback.ts b/apps/cowswap-frontend/src/legacy/hooks/useWrapCallback.ts index 363b5ce6af..7dc8c777ae 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useWrapCallback.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useWrapCallback.ts @@ -1,22 +1,19 @@ +import { wrapAnalytics } from '@cowprotocol/analytics' +import { RADIX_HEX } from '@cowprotocol/common-const' +import { getChainCurrencySymbols } from '@cowprotocol/common-const' +import { calculateGasMargin, formatTokenAmount, isRejectRequestProviderError } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { BigNumber } from '@ethersproject/bignumber' import { Contract } from '@ethersproject/contracts' import { TransactionResponse } from '@ethersproject/providers' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { wrapAnalytics } from 'legacy/components/analytics' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' -import { getOperationMessage } from 'legacy/components/TransactionConfirmationModal/LegacyConfirmationPendingContent' -import { RADIX_HEX } from 'legacy/constants' import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' -import { calculateGasMargin } from 'legacy/utils/calculateGasMargin' -import { getChainCurrencySymbols } from 'legacy/utils/gnosis_chain/hack' import { ExtendedTradeRawState, TradeRawState } from 'modules/trade/types/TradeRawState' -import { formatTokenAmount } from 'utils/amountFormat' - -import { isRejectRequestProviderError } from '../utils/misc' +import { getOperationMessage } from '../components/TransactionConfirmationModal/LegacyConfirmationPendingContent' +import { ConfirmOperationType } from '../state/types' // Use a 180K gas as a fallback if there's issue calculating the gas estimation (fixes some issues with some nodes failing to calculate gas costs for SC wallets) const WRAP_UNWRAP_GAS_LIMIT_DEFAULT = BigNumber.from('180000') diff --git a/apps/cowswap-frontend/src/legacy/state/application/hooks.ts b/apps/cowswap-frontend/src/legacy/state/application/hooks.ts index cb8eb4da2b..73990bfb27 100644 --- a/apps/cowswap-frontend/src/legacy/state/application/hooks.ts +++ b/apps/cowswap-frontend/src/legacy/state/application/hooks.ts @@ -1,11 +1,13 @@ import { useCallback, useMemo } from 'react' +import { DEFAULT_TXN_DISMISS_MS } from '@cowprotocol/common-const' + import { createAction } from '@reduxjs/toolkit' -import { DEFAULT_TXN_DISMISS_MS } from 'legacy/constants/misc' -import { AppState } from 'legacy/state' -import { addPopup, ApplicationModal, PopupContent, removePopup } from 'legacy/state/application/reducer' -import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' +import { addPopup, ApplicationModal, PopupContent, removePopup } from './reducer' + +import { useAppDispatch, useAppSelector } from '../hooks' +import { AppState } from '../index' export const setOpenModal = createAction('application/setOpenModal') @@ -66,7 +68,7 @@ export function useTogglePrivacyPolicy(): () => void { } /** - * @deprecated use @cowswap/snackbars instead + * @deprecated use @cowprotocol/snackbars instead */ export function useRemovePopup(): (key: string) => void { const dispatch = useAppDispatch() @@ -79,7 +81,7 @@ export function useRemovePopup(): (key: string) => void { } /** - * @deprecated use @cowswap/snackbars instead + * @deprecated use @cowprotocol/snackbars instead */ export function useActivePopups(): AppState['application']['popupList'] { const list = useAppSelector((state: AppState) => state.application.popupList) @@ -102,7 +104,7 @@ export function useCloseModals(): () => void { } /** - * @deprecated use @cowswap/snackbars instead + * @deprecated use @cowprotocol/snackbars instead */ export function useAddPopup(): (content: PopupContent, key?: string, removeAfterMs?: number | null) => void { const dispatch = useAppDispatch() diff --git a/apps/cowswap-frontend/src/legacy/state/application/initialState.ts b/apps/cowswap-frontend/src/legacy/state/application/initialState.ts index 506ed1ca9d..e3f262d3a6 100644 --- a/apps/cowswap-frontend/src/legacy/state/application/initialState.ts +++ b/apps/cowswap-frontend/src/legacy/state/application/initialState.ts @@ -1,5 +1,5 @@ -import { localWarning } from 'legacy/state/application/localWarning' -import { ApplicationState } from 'legacy/state/application/reducer' +import { localWarning } from './localWarning' +import { ApplicationState } from './reducer' const popupList: ApplicationState['popupList'] = [] diff --git a/apps/cowswap-frontend/src/legacy/state/application/localWarning.ts b/apps/cowswap-frontend/src/legacy/state/application/localWarning.ts index 6f8039615f..f89b5293c9 100644 --- a/apps/cowswap-frontend/src/legacy/state/application/localWarning.ts +++ b/apps/cowswap-frontend/src/legacy/state/application/localWarning.ts @@ -1,5 +1,5 @@ -import { PINATA_API_KEY, PINATA_SECRET_API_KEY } from 'legacy/constants/ipfs' -import { isLocal } from 'legacy/utils/environments' +import { PINATA_API_KEY, PINATA_SECRET_API_KEY } from '@cowprotocol/common-const' +import { isLocal } from '@cowprotocol/common-utils' let warningMsg diff --git a/apps/cowswap-frontend/src/legacy/state/application/reducer.ts b/apps/cowswap-frontend/src/legacy/state/application/reducer.ts index 4add005de0..3b1d4f3c94 100644 --- a/apps/cowswap-frontend/src/legacy/state/application/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/application/reducer.ts @@ -1,12 +1,12 @@ +import { DEFAULT_TXN_DISMISS_MS } from '@cowprotocol/common-const' +import { BlockExplorerLinkType } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { createSlice, nanoid } from '@reduxjs/toolkit' import { FlattenInterpolation, ThemeProps, DefaultTheme } from 'styled-components/macro' import { Nullish } from 'types' -import { DEFAULT_TXN_DISMISS_MS } from 'legacy/constants/misc' -import { initialState } from 'legacy/state/application/initialState' -import { BlockExplorerLinkType } from 'legacy/utils' +import { initialState } from './initialState' type BasePopupContent = { failedSwitchNetwork: SupportedChainId diff --git a/apps/cowswap-frontend/src/legacy/state/claim/actions.ts b/apps/cowswap-frontend/src/legacy/state/claim/actions.ts index 36a2668ddc..358368d100 100644 --- a/apps/cowswap-frontend/src/legacy/state/claim/actions.ts +++ b/apps/cowswap-frontend/src/legacy/state/claim/actions.ts @@ -2,7 +2,7 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' import { createAction } from '@reduxjs/toolkit' -import { ClaimInfo } from 'legacy/state/claim/reducer' +import { ClaimInfo } from './reducer' export enum ClaimStatus { DEFAULT = 'DEFAULT', @@ -12,33 +12,6 @@ export enum ClaimStatus { FAILED = 'FAILED', } -export type ClaimActions = { - // account - setInputAddress: (payload: string) => void - setActiveClaimAccount: (payload: string) => void - setActiveClaimAccountENS: (payload: string) => void - - // search - setIsSearchUsed: (payload: boolean) => void - - // claiming - setClaimStatus: (payload: ClaimStatus) => void - setClaimedAmount: (payload: string) => void - setEstimatedGas: (payload: string) => void - - // investing - setIsInvestFlowActive: (payload: boolean) => void - setInvestFlowStep: (payload: number) => void - initInvestFlowData: () => void - updateInvestAmount: (payload: { index: number; amount: string }) => void - updateInvestError: (payload: { index: number; error: string | undefined }) => void - setIsTouched: (payload: { index: number; isTouched: boolean }) => void - - // claim row selection - setSelected: (payload: number[]) => void - setSelectedAll: (payload: boolean) => void -} - // accounts export const setInputAddress = createAction('claim/setInputAddress') export const setActiveClaimAccount = createAction('claim/setActiveClaimAccount') diff --git a/apps/cowswap-frontend/src/legacy/state/claim/hooks/const.ts b/apps/cowswap-frontend/src/legacy/state/claim/hooks/const.ts new file mode 100644 index 0000000000..c684a50073 --- /dev/null +++ b/apps/cowswap-frontend/src/legacy/state/claim/hooks/const.ts @@ -0,0 +1,7 @@ +import { ClaimType } from './types' + +const CLAIMS_REPO_BRANCH = 'main' + +export const CLAIMS_REPO = `https://raw.githubusercontent.com/cowprotocol/cow-merkle-drop/${CLAIMS_REPO_BRANCH}/` +export const FREE_CLAIM_TYPES: ClaimType[] = [ClaimType.Airdrop, ClaimType.Team, ClaimType.Advisor] +export const PAID_CLAIM_TYPES: ClaimType[] = [ClaimType.GnoOption, ClaimType.UserOption, ClaimType.Investor] diff --git a/apps/cowswap-frontend/src/legacy/state/claim/hooks/index.ts b/apps/cowswap-frontend/src/legacy/state/claim/hooks/index.ts index a5aaba7fe6..ccedc9e2b8 100644 --- a/apps/cowswap-frontend/src/legacy/state/claim/hooks/index.ts +++ b/apps/cowswap-frontend/src/legacy/state/claim/hooks/index.ts @@ -1,8 +1,11 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { VCow } from '@cowswap/abis' +import { VCow } from '@cowprotocol/abis' +import { GpEther, V_COW } from '@cowprotocol/common-const' +import { useIsMounted, useVCowContract } from '@cowprotocol/common-hooks' +import { calculateGasMargin, formatTokenAmount, isAddress } from '@cowprotocol/common-utils' +import { SupportedChainId as ChainId, SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { BigNumber } from '@ethersproject/bignumber' import { TransactionResponse } from '@ethersproject/providers' import { parseUnits } from '@ethersproject/units' @@ -11,55 +14,44 @@ import { CurrencyAmount, Price, Token } from '@uniswap/sdk-core' import JSBI from 'jsbi' import ms from 'ms.macro' -import { useSelector, useDispatch } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' -import { GpEther, V_COW } from 'legacy/constants/tokens' -import { useVCowContract } from 'legacy/hooks/useContract' -import useIsMounted from 'legacy/hooks/useIsMounted' -import { AppDispatch } from 'legacy/state' -import { AppState } from 'legacy/state' +import { useSingleContractMultipleData } from 'lib/hooks/multicall' + +import { PAID_CLAIM_TYPES } from './const' +import { ClaimInput, ClaimType, RepoClaims, UserClaims, VCowPrices } from './types' import { + claimTypeToTokenAmount, getClaimKey, getClaimsRepoPath, isFreeClaim, - claimTypeToTokenAmount, transformRepoClaimsToUserClaims, -} from 'legacy/state/claim/hooks/utils' -import { ClaimInfo } from 'legacy/state/claim/reducer' -import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' -import { useAllClaimingTransactionIndices } from 'legacy/state/enhancedTransactions/hooks' -import { isAddress } from 'legacy/utils' -import { calculateGasMargin } from 'legacy/utils/calculateGasMargin' - -import { useWalletInfo } from 'modules/wallet' - -import { useSingleContractMultipleData } from 'lib/hooks/multicall' -import { EnhancedUserClaimData } from 'pages/Claim/types' -import { formatTokenAmount } from 'utils/amountFormat' +} from './utils' +import { useAllClaimingTransactionIndices, useTransactionAdder } from '../../enhancedTransactions/hooks' +import { AppDispatch, AppState } from '../../index' import { - setInputAddress, + ClaimStatus, + initInvestFlowData, + resetClaimUi, setActiveClaimAccount, setActiveClaimAccountENS, - setIsSearchUsed, - setClaimStatus, setClaimedAmount, - setIsInvestFlowActive, + setClaimsCount, + setClaimStatus, + setEstimatedGas, + setInputAddress, setInvestFlowStep, - initInvestFlowData, - updateInvestAmount, + setIsInvestFlowActive, + setIsSearchUsed, + setIsTouched, setSelected, setSelectedAll, - ClaimStatus, - resetClaimUi, + updateInvestAmount, updateInvestError, - setEstimatedGas, - setIsTouched, - setClaimsCount, } from '../actions' - -const CLAIMS_REPO_BRANCH = 'main' -export const CLAIMS_REPO = `https://raw.githubusercontent.com/cowprotocol/cow-merkle-drop/${CLAIMS_REPO_BRANCH}/` +import { ClaimInfo } from '../reducer' +import { EnhancedUserClaimData } from '../types' // Base amount = 1 VCOW const ONE_VCOW = CurrencyAmount.fromRawAmount( @@ -74,20 +66,8 @@ const AIRDROP_TIME = ms`6 weeks` // For native token price calculation const DENOMINATOR = JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(18)) -export enum ClaimType { - Airdrop, // free, no vesting, can be available on both mainnet and gchain - GnoOption, // paid, with vesting, must use GNO, can be available on both mainnet and gchain - UserOption, // paid, with vesting, must use Native currency, can be available on both mainnet and gchain - Investor, // paid, with vesting, must use USDC, only on mainnet - Team, // free, with vesting, only on mainnet - Advisor, // free, with vesting, only on mainnet -} - type RepoClaimType = keyof typeof ClaimType -export const FREE_CLAIM_TYPES: ClaimType[] = [ClaimType.Airdrop, ClaimType.Team, ClaimType.Advisor] -export const PAID_CLAIM_TYPES: ClaimType[] = [ClaimType.GnoOption, ClaimType.UserOption, ClaimType.Investor] - export interface UserClaimData { index: number amount: string @@ -99,23 +79,8 @@ export type RepoClaimData = Omit & { type: RepoClaimType } -export interface ClaimInput { - /** - * The index of the claim - */ - index: number - /** - * The amount of the claim. Optional - * If not present, will claim the full amount - */ - amount?: string -} - type Account = string | null | undefined -export type UserClaims = UserClaimData[] -export type RepoClaims = RepoClaimData[] - export type ClassifiedUserClaims = { available: UserClaims expired: UserClaims @@ -402,12 +367,6 @@ function _useVCowPriceForToken(priceFnName: VCowPriceFnNames): string | null { return price } -export type VCowPrices = { - native: string | null - gno: string | null - usdc: string | null -} - export function useVCowPrices(): VCowPrices { const native = useNativeTokenPrice() const gno = useGnoPrice() diff --git a/apps/cowswap-frontend/src/legacy/state/claim/hooks/types.ts b/apps/cowswap-frontend/src/legacy/state/claim/hooks/types.ts new file mode 100644 index 0000000000..dd593fd8b3 --- /dev/null +++ b/apps/cowswap-frontend/src/legacy/state/claim/hooks/types.ts @@ -0,0 +1,30 @@ +import { RepoClaimData, UserClaimData } from './index' + +export enum ClaimType { + Airdrop, // free, no vesting, can be available on both mainnet and gchain + GnoOption, // paid, with vesting, must use GNO, can be available on both mainnet and gchain + UserOption, // paid, with vesting, must use Native currency, can be available on both mainnet and gchain + Investor, // paid, with vesting, must use USDC, only on mainnet + Team, // free, with vesting, only on mainnet + Advisor, // free, with vesting, only on mainnet +} + +export interface ClaimInput { + /** + * The index of the claim + */ + index: number + /** + * The amount of the claim. Optional + * If not present, will claim the full amount + */ + amount?: string +} + +export type UserClaims = UserClaimData[] +export type RepoClaims = RepoClaimData[] +export type VCowPrices = { + native: string | null + gno: string | null + usdc: string | null +} diff --git a/apps/cowswap-frontend/src/legacy/state/claim/hooks/utils.ts b/apps/cowswap-frontend/src/legacy/state/claim/hooks/utils.ts index e936f0e6f5..d6cca292b8 100644 --- a/apps/cowswap-frontend/src/legacy/state/claim/hooks/utils.ts +++ b/apps/cowswap-frontend/src/legacy/state/claim/hooks/utils.ts @@ -1,21 +1,12 @@ +import { GpEther, USDC, GNO, ZERO_PERCENT, ONE_HUNDRED_PERCENT } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core' -import { ONE_HUNDRED_PERCENT, ZERO_PERCENT } from 'legacy/constants/misc' -import { GNO, GpEther, USDC } from 'legacy/constants/tokens' -import { - CLAIMS_REPO, - ClaimType, - FREE_CLAIM_TYPES, - PAID_CLAIM_TYPES, - RepoClaims, - UserClaims, - VCowPrices, -} from 'legacy/state/claim/hooks/index' -import { ClaimInput } from 'legacy/state/claim/hooks/index' -import { InvestClaim } from 'legacy/state/claim/reducer' - -import { EnhancedUserClaimData, InvestmentAmounts } from 'pages/Claim/types' +import { CLAIMS_REPO, FREE_CLAIM_TYPES, PAID_CLAIM_TYPES } from './const' +import { ClaimInput, ClaimType, RepoClaims, UserClaims, VCowPrices } from './types' + +import { InvestClaim } from '../reducer' +import { EnhancedUserClaimData, InvestmentAmounts } from '../types' /** * Helper function to check whether any claim is an investment option diff --git a/apps/cowswap-frontend/src/pages/Claim/types.ts b/apps/cowswap-frontend/src/legacy/state/claim/types.ts similarity index 89% rename from apps/cowswap-frontend/src/pages/Claim/types.ts rename to apps/cowswap-frontend/src/legacy/state/claim/types.ts index 436889852d..bba01d01c3 100644 --- a/apps/cowswap-frontend/src/pages/Claim/types.ts +++ b/apps/cowswap-frontend/src/legacy/state/claim/types.ts @@ -1,9 +1,9 @@ import { SyntheticEvent } from 'react' +import { GpEther } from '@cowprotocol/common-const' import { Currency, CurrencyAmount, Price, Token } from '@uniswap/sdk-core' -import { GpEther } from 'legacy/constants/tokens' -import { UserClaimData } from 'legacy/state/claim/hooks' +import { UserClaimData } from './hooks' export type ClaimCommonTypes = { account: string | null | undefined diff --git a/apps/cowswap-frontend/src/legacy/state/claim/updater.tsx b/apps/cowswap-frontend/src/legacy/state/claim/updater.tsx index 23e17bc005..3388fd2753 100644 --- a/apps/cowswap-frontend/src/legacy/state/claim/updater.tsx +++ b/apps/cowswap-frontend/src/legacy/state/claim/updater.tsx @@ -1,16 +1,10 @@ import { useEffect, useMemo } from 'react' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' -import { - ClassifiedUserClaims, - useClaimDispatchers, - useClaimState, - useClassifiedUserClaims, -} from 'legacy/state/claim/hooks' -import { ClaimInfo } from 'legacy/state/claim/reducer' - -import { useWalletInfo } from 'modules/wallet' +import { ClassifiedUserClaims, useClaimDispatchers, useClaimState, useClassifiedUserClaims } from './hooks' +import { ClaimInfo } from './reducer' export default function Updater() { const { chainId } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/legacy/state/connection/hooks.ts b/apps/cowswap-frontend/src/legacy/state/connection/hooks.ts deleted file mode 100644 index d75ecd87e5..0000000000 --- a/apps/cowswap-frontend/src/legacy/state/connection/hooks.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { useMemo } from 'react' - -import { Token } from '@uniswap/sdk-core' - -import { useAllTokens } from 'legacy/hooks/Tokens' -import { useFavouriteTokens } from 'legacy/state/user/hooks' - -import { useOnchainBalances } from 'modules/tokens' -import { TokenAmounts } from 'modules/tokens' -import { useWalletInfo } from 'modules/wallet' - -// mimics useAllBalances -export function useAllTokenBalances(): [TokenAmounts, boolean] { - const { account } = useWalletInfo() - const allTokens = useAllTokens() - // Mod, add favourite tokens to balances - const favTokens = useFavouriteTokens() - - const allTokensArray = useMemo(() => { - const favTokensObj = favTokens.reduce( - (acc, cur: Token) => { - acc[cur.address] = cur - return acc - }, - {} as { - [address: string]: Token - } - ) - - return Object.values({ ...favTokensObj, ...allTokens }) - }, [allTokens, favTokens]) - - const { isLoading, amounts } = useOnchainBalances({ - account: account ?? undefined, - tokens: allTokensArray, - }) - return [amounts ?? {}, isLoading] -} diff --git a/apps/cowswap-frontend/src/legacy/state/connection/reducer.ts b/apps/cowswap-frontend/src/legacy/state/connection/reducer.ts index 14ae1b7651..c5c8f5ce32 100644 --- a/apps/cowswap-frontend/src/legacy/state/connection/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/connection/reducer.ts @@ -1,6 +1,6 @@ -import { createSlice } from '@reduxjs/toolkit' +import { ConnectionType } from '@cowprotocol/wallet' -import { ConnectionType } from 'modules/wallet' +import { createSlice } from '@reduxjs/toolkit' export interface ConnectionState { errorByConnectionType: Record @@ -14,7 +14,7 @@ export const initialState: ConnectionState = { } const connectionSlice = createSlice({ - name: 'modules/wallet/web3-react/utils/connection', + name: 'wallet-connection', initialState, reducers: { updateConnectionError( diff --git a/apps/cowswap-frontend/src/legacy/state/cowToken/hooks.ts b/apps/cowswap-frontend/src/legacy/state/cowToken/hooks.ts index 5770448a2a..6558986cbc 100644 --- a/apps/cowswap-frontend/src/legacy/state/cowToken/hooks.ts +++ b/apps/cowswap-frontend/src/legacy/state/cowToken/hooks.ts @@ -1,25 +1,21 @@ import { useCallback, useMemo } from 'react' +import { V_COW } from '@cowprotocol/common-const' +import { useVCowContract } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' import { TransactionResponse } from '@ethersproject/providers' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import JSBI from 'jsbi' - -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' -import { V_COW, COW } from 'legacy/constants/tokens' -import { APPROVE_GAS_LIMIT_DEFAULT } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' -import { useVCowContract } from 'legacy/hooks/useContract' -import { AppState } from 'legacy/state' -import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' -import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' - -import { useTokenBalance } from 'modules/tokens/hooks/useCurrencyBalance' -import { useWalletInfo } from 'modules/wallet' - -import { useSingleCallResult, CallStateResult as Result } from 'lib/hooks/multicall' +import { CallStateResult as Result, useSingleCallResult } from 'lib/hooks/multicall' import { setSwapVCowStatus, SwapVCowStatus } from './actions' +import { APPROVE_GAS_LIMIT_DEFAULT } from '../../hooks/useApproveCallback/useApproveCallbackMod' +import { useTransactionAdder } from '../enhancedTransactions/hooks' +import { useAppDispatch, useAppSelector } from '../hooks' +import { AppState } from '../index' +import { ConfirmOperationType } from '../types' + export type SetSwapVCowStatusCallback = (payload: SwapVCowStatus) => void type VCowData = { @@ -156,49 +152,3 @@ export function useSetSwapVCowStatus(): SetSwapVCowStatusCallback { export function useSwapVCowStatus() { return useAppSelector((state: AppState) => state.cowToken.swapVCowStatus) } - -/** - * Hook that returns COW balance - */ -export function useCowBalance() { - const { chainId, account } = useWalletInfo() - const cowToken = chainId ? COW[chainId] : undefined - return useTokenBalance(account || undefined, cowToken) -} - -/** - * Hook that returns combined vCOW + COW balance + vCow from locked GNO - */ -export function useCombinedBalance() { - const { chainId, account } = useWalletInfo() - const { total: vCowBalance } = useVCowData() - // const { allocated, claimed } = useCowFromLockedGnoBalances() - const cowBalance = useCowBalance() - - // const lockedGnoBalance = useMemo(() => { - // if (!allocated || !claimed) { - // return - // } - - // return JSBI.subtract(allocated.quotient, claimed.quotient) - // }, [allocated, claimed]) - - return useMemo(() => { - let tmpBalance = JSBI.BigInt(0) - - const isLoading = !!(account && (!vCowBalance /* || !lockedGnoBalance */ || !cowBalance)) - - const cow = COW[chainId] - - if (account) { - if (vCowBalance) tmpBalance = JSBI.add(tmpBalance, vCowBalance.quotient) - // if (lockedGnoBalance) tmpBalance = JSBI.add(tmpBalance, lockedGnoBalance) - if (cowBalance) tmpBalance = JSBI.add(tmpBalance, cowBalance.quotient) - } - - // TODO: check COW vs vCOW - const balance = CurrencyAmount.fromRawAmount(cow, tmpBalance) - - return { balance, isLoading } - }, [vCowBalance, /* lockedGnoBalance, */ cowBalance, chainId, account]) -} diff --git a/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts b/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts index 46670f65de..89852f3350 100644 --- a/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts +++ b/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts @@ -1,11 +1,11 @@ -import { isAnyOf, Middleware } from '@reduxjs/toolkit' +import { getCowSoundError, getCowSoundSuccess } from '@cowprotocol/common-utils' -import { AppState } from 'legacy/state' -import { getCowSoundSuccess, getCowSoundError } from 'legacy/utils/sound' +import { isAnyOf, Middleware } from '@reduxjs/toolkit' import { setSwapVCowStatus, SwapVCowStatus } from './actions' import { finalizeTransaction } from '../enhancedTransactions/actions' +import { AppState } from '../index' const isFinalizeTransaction = isAnyOf(finalizeTransaction) diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/TransactionHooksMod.tsx b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/TransactionHooksMod.tsx index 08efffa04b..16bbf7479f 100644 --- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/TransactionHooksMod.tsx +++ b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/TransactionHooksMod.tsx @@ -1,9 +1,8 @@ import { useMemo } from 'react' -import { useAppSelector } from 'legacy/state/hooks' - -import { useWalletInfo } from 'modules/wallet' +import { useWalletInfo } from '@cowprotocol/wallet' +import { useAppSelector } from '../../hooks' import { EnhancedTransactionDetails } from '../reducer' // returns all the transactions for the current chain diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/index.ts b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/index.ts index d90451ad02..cb9a814b0f 100644 --- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/index.ts +++ b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/hooks/index.ts @@ -1,10 +1,10 @@ import { useCallback, useMemo } from 'react' -import { useAllTransactions } from 'legacy/state/enhancedTransactions/hooks/index' -import { useAppDispatch } from 'legacy/state/hooks' +import { useWalletInfo, useIsSafeWallet } from '@cowprotocol/wallet' -import { useWalletInfo, useIsSafeWallet } from 'modules/wallet' +import { useAllTransactions } from './TransactionHooksMod' +import { useAppDispatch } from '../../hooks' import { addTransaction, AddTransactionParams } from '../actions' import { EnhancedTransactionDetails, HashType } from '../reducer' diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts index 797e31daf7..5b491a5ad0 100644 --- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts @@ -12,7 +12,7 @@ import { updateSafeTransaction, ReplacementType, SerializableTransactionReceipt, -} from 'legacy/state/enhancedTransactions/actions' +} from './actions' export enum HashType { ETHEREUM_TX = 'ETHEREUM_TX', diff --git a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/index.tsx b/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/index.tsx deleted file mode 100644 index 44786f61ae..0000000000 --- a/apps/cowswap-frontend/src/legacy/state/enhancedTransactions/updater/index.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react' - -import CancelReplaceTxUpdater from './CancelReplaceTxUpdater' -import FinalizeTxUpdater from './FinalizeTxUpdater' - -export default function Updater() { - return ( - <> - - - - ) -} diff --git a/apps/cowswap-frontend/src/legacy/state/gas/actions.ts b/apps/cowswap-frontend/src/legacy/state/gas/actions.ts index 4af7a31ade..e89e042717 100644 --- a/apps/cowswap-frontend/src/legacy/state/gas/actions.ts +++ b/apps/cowswap-frontend/src/legacy/state/gas/actions.ts @@ -1,9 +1,9 @@ import { createAction } from '@reduxjs/toolkit' -import { WithChainId } from 'legacy/state/lists/actions' - import { GasFeeEndpointResponse } from 'api/gasPrices' +import { WithChainId } from '../lists/actions' + export type UpdateGasPrices = GasFeeEndpointResponse & WithChainId export const updateGasPrices = createAction('gas/updateGasPrices') diff --git a/apps/cowswap-frontend/src/legacy/state/gas/atoms.ts b/apps/cowswap-frontend/src/legacy/state/gas/atoms.ts index 6c4b231ac5..53cb47e594 100644 --- a/apps/cowswap-frontend/src/legacy/state/gas/atoms.ts +++ b/apps/cowswap-frontend/src/legacy/state/gas/atoms.ts @@ -1,6 +1,6 @@ import { atom } from 'jotai' -import { DEFAULT_GP_PRICE_STRATEGY } from 'legacy/constants' +import { DEFAULT_GP_PRICE_STRATEGY } from '@cowprotocol/common-const' export type GpPriceStrategy = 'COWSWAP' | 'LEGACY' diff --git a/apps/cowswap-frontend/src/legacy/state/gas/gas-price-strategy-updater.tsx b/apps/cowswap-frontend/src/legacy/state/gas/gas-price-strategy-updater.tsx index fa2e021437..d1bb63d8c8 100644 --- a/apps/cowswap-frontend/src/legacy/state/gas/gas-price-strategy-updater.tsx +++ b/apps/cowswap-frontend/src/legacy/state/gas/gas-price-strategy-updater.tsx @@ -1,15 +1,15 @@ import { useSetAtom } from 'jotai' import { useEffect } from 'react' -import ms from 'ms.macro' - -import { DEFAULT_GP_PRICE_STRATEGY } from 'legacy/constants' -import { gasPriceStrategyAtom } from 'legacy/state/gas/atoms' +import { DEFAULT_GP_PRICE_STRATEGY } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' -import { useWalletInfo } from 'modules/wallet' +import ms from 'ms.macro' import { getPriceStrategy } from 'api/gnosisProtocol/priceApi' +import { gasPriceStrategyAtom } from './atoms' + const GP_PRICE_STRATEGY_INTERVAL_TIME = ms`30 minutes` export function GasPriceStrategyUpdater(): null { diff --git a/apps/cowswap-frontend/src/legacy/state/gas/hooks.ts b/apps/cowswap-frontend/src/legacy/state/gas/hooks.ts index 753bedece7..df58a68901 100644 --- a/apps/cowswap-frontend/src/legacy/state/gas/hooks.ts +++ b/apps/cowswap-frontend/src/legacy/state/gas/hooks.ts @@ -1,33 +1,13 @@ -import { useSetAtom } from 'jotai' -import { useCallback } from 'react' - import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' -import { useSelector, useDispatch } from 'react-redux' - -import { AppDispatch } from 'legacy/state' -import { AppState } from 'legacy/state' +import { useSelector } from 'react-redux' -import { gasPriceAtom } from 'modules/gasPirce' - -import { updateGasPrices, UpdateGasPrices } from './actions' import { GasState } from './reducer' +import { AppState } from '../index' + export function useGasPrices(chainId?: ChainId) { return useSelector((state) => { return chainId ? state.gas[chainId] : null }) } - -export function useUpdateGasPrices() { - const dispatch = useDispatch() - const setGasPrice = useSetAtom(gasPriceAtom) - - return useCallback( - (gasParams: UpdateGasPrices) => { - dispatch(updateGasPrices(gasParams)) - setGasPrice(gasParams) - }, - [dispatch, setGasPrice] - ) -} diff --git a/apps/cowswap-frontend/src/legacy/state/global/actions.ts b/apps/cowswap-frontend/src/legacy/state/global/actions.ts index d4cfa1d5e4..4094748f77 100644 --- a/apps/cowswap-frontend/src/legacy/state/global/actions.ts +++ b/apps/cowswap-frontend/src/legacy/state/global/actions.ts @@ -1,6 +1,6 @@ import { createAction } from '@reduxjs/toolkit' -import { WithChainId } from 'legacy/state/lists/actions' +import { WithChainId } from '../lists/actions' // fired once when the app reloads but before the app renders // allows any updates to be applied to store data loaded from localStorage diff --git a/apps/cowswap-frontend/src/legacy/state/hooks/index.ts b/apps/cowswap-frontend/src/legacy/state/hooks/index.ts index 0b2089a33e..1412b2aef9 100644 --- a/apps/cowswap-frontend/src/legacy/state/hooks/index.ts +++ b/apps/cowswap-frontend/src/legacy/state/hooks/index.ts @@ -1,6 +1,6 @@ import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' -import { AppDispatch, AppState } from 'legacy/state' +import { AppDispatch, AppState } from '../index' export const useAppDispatch = () => useDispatch() export const useAppSelector: TypedUseSelectorHook = useSelector diff --git a/apps/cowswap-frontend/src/legacy/state/index.ts b/apps/cowswap-frontend/src/legacy/state/index.ts index 86b5acadd5..d76c9a9fab 100644 --- a/apps/cowswap-frontend/src/legacy/state/index.ts +++ b/apps/cowswap-frontend/src/legacy/state/index.ts @@ -1,39 +1,36 @@ +import { DEFAULT_NETWORK_FOR_LISTS } from '@cowprotocol/common-const' + import { configureStore, StateFromReducersMapObject } from '@reduxjs/toolkit' import { load, save } from 'redux-localstorage-simple' -import { DEFAULT_NETWORK_FOR_LISTS } from 'legacy/constants/lists' -import application from 'legacy/state/application/reducer' -import claim from 'legacy/state/claim/reducer' -import connection from 'legacy/state/connection/reducer' -import { cowTokenMiddleware } from 'legacy/state/cowToken/middleware' -import cowToken from 'legacy/state/cowToken/reducer' -import enhancedTransactions from 'legacy/state/enhancedTransactions/reducer' -import gas from 'legacy/state/gas/reducer' -import { updateVersion } from 'legacy/state/global/actions' -import lists from 'legacy/state/lists/reducer' -import logs from 'legacy/state/logs/slice' -import orders from 'legacy/state/orders/reducer' -import { priceMiddleware } from 'legacy/state/price/middleware' -import price from 'legacy/state/price/reducer' -import profile from 'legacy/state/profile/reducer' -import swap from 'legacy/state/swap/reducer' -import user from 'legacy/state/user/reducer' - -import multicall from 'lib/state/multicall' +// import { composableOrdersPopupMiddleware } from 'modules/twap/state/composableOrdersPopupMiddleware' -import { appziMiddleware, popupMiddleware, soundMiddleware, composableOrdersPopupMiddleware } from './orders/middleware' +import application from './application/reducer' +import claim from './claim/reducer' +import connection from './connection/reducer' +import { cowTokenMiddleware } from './cowToken/middleware' +import cowToken from './cowToken/reducer' +import enhancedTransactions from './enhancedTransactions/reducer' +import gas from './gas/reducer' +import { updateVersion } from './global/actions' +import lists from './lists/reducer' +import logs from './logs/slice' +import { multicall } from './multicall' +import { appziMiddleware, popupMiddleware, soundMiddleware } from './orders/middleware' +import orders from './orders/reducer' +import { priceMiddleware } from './price/middleware' +import price from './price/reducer' +import profile from './profile/reducer' +import swap from './swap/reducer' +import user from './user/reducer' -const UNISWAP_REDUCERS = { +const reducers = { application, user, connection, swap, multicall: multicall.reducer, logs, -} - -const reducers = { - ...UNISWAP_REDUCERS, transactions: enhancedTransactions, // replace transactions state by "enhancedTransactions" lists, orders, @@ -46,13 +43,14 @@ const reducers = { const PERSISTED_KEYS: string[] = ['user', 'transactions', 'orders', 'lists', 'gas', 'affiliate', 'profile', 'swap'] -const store = configureStore({ +export const cowSwapStore = configureStore({ reducer: reducers, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ thunk: true, serializableCheck: false }) .concat(save({ states: PERSISTED_KEYS, debounce: 1000 })) .concat(popupMiddleware) - .concat(composableOrdersPopupMiddleware) + // TODO: fix it + // .concat(composableOrdersPopupMiddleware) .concat(cowTokenMiddleware) .concat(soundMiddleware) .concat(appziMiddleware) @@ -61,12 +59,10 @@ const store = configureStore({ }) // this instantiates the app / reducers in several places using the default chainId -store.dispatch(updateVersion({ chainId: DEFAULT_NETWORK_FOR_LISTS })) +cowSwapStore.dispatch(updateVersion({ chainId: DEFAULT_NETWORK_FOR_LISTS })) // TODO: this is new, should we enable it? // setupListeners(store.dispatch) -export default store - export type AppState = StateFromReducersMapObject -export type AppDispatch = typeof store.dispatch +export type AppDispatch = typeof cowSwapStore.dispatch diff --git a/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts b/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts index 428ddc176b..6a5a1d0565 100644 --- a/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts +++ b/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts @@ -1,6 +1,9 @@ import { useCallback, useMemo } from 'react' +import { UNSUPPORTED_LIST_URLS } from '@cowprotocol/common-const' +import { sortByListPriority } from '@cowprotocol/common-utils' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import DEFAULT_TOKEN_LIST from '@uniswap/default-token-list' import { Currency } from '@uniswap/sdk-core' import { TokenInfo } from '@uniswap/token-lists' @@ -8,23 +11,18 @@ import { TokenInfo } from '@uniswap/token-lists' import { shallowEqual } from 'react-redux' import { Nullish } from 'types' -import { UNSUPPORTED_LIST_URLS } from 'legacy/constants/lists' -import BROKEN_LIST from 'legacy/constants/tokenLists/broken.tokenlist.json' -import UNSUPPORTED_TOKEN_LIST from 'legacy/constants/tokenLists/unsupported.tokenlist.json' -import { AppState } from 'legacy/state' -import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' +import { UnsupportedToken } from 'api/gnosisProtocol' +import { ChainTokenMap, tokensToChainTokenMap } from 'lib/hooks/useTokenList/utils' + import { addGpUnsupportedToken, AddGpUnsupportedTokenParams, removeGpUnsupportedToken, RemoveGpUnsupportedTokenParams, -} from 'legacy/state/lists/actions' -import sortByListPriority from 'legacy/utils/listSort' +} from './actions' -import { useWalletInfo } from 'modules/wallet' - -import { UnsupportedToken } from 'api/gnosisProtocol' -import { ChainTokenMap, tokensToChainTokenMap } from 'lib/hooks/useTokenList/utils' +import { useAppDispatch, useAppSelector } from '../hooks' +import { AppState } from '../index' export type TokenAddressMap = ChainTokenMap @@ -34,11 +32,8 @@ type Mutable = { export function useActiveListUrls(): string[] | undefined { const { chainId } = useWalletInfo() - const activeListUrls = useAppSelector((state) => state.lists[chainId]?.activeListUrls, shallowEqual) - return useMemo(() => { - return activeListUrls?.filter((url) => !UNSUPPORTED_LIST_URLS[chainId]?.includes(url)) - }, [chainId, activeListUrls]) + return useAppSelector((state) => state.lists[chainId]?.activeListUrls, shallowEqual) } export function useAllLists(): AppState['lists'][ChainId]['byUrl'] { @@ -105,20 +100,7 @@ export function useCombinedActiveList(): TokenAddressMap { // list of tokens not supported on interface for various reasons, used to show warnings and prevent swaps and adds export function useUnsupportedTokenList(): TokenAddressMap { - // get hard-coded broken tokens - const brokenListMap = useMemo(() => tokensToChainTokenMap(BROKEN_LIST), []) - - // get hard-coded list of unsupported tokens - const localUnsupportedListMap = useMemo(() => tokensToChainTokenMap(UNSUPPORTED_TOKEN_LIST), []) - - // get dynamic list of unsupported tokens - const loadedUnsupportedListMap = useCombinedTokenMapFromUrls(UNSUPPORTED_LIST_URLS[1]) - - // format into one token address map - return useMemo( - () => combineMaps(brokenListMap, combineMaps(localUnsupportedListMap, loadedUnsupportedListMap)), - [brokenListMap, localUnsupportedListMap, loadedUnsupportedListMap] - ) + return useCombinedTokenMapFromUrls(UNSUPPORTED_LIST_URLS[1]) } export function useTokensListFromUrls(urls: string[] | undefined): TokenInfo[] { diff --git a/apps/cowswap-frontend/src/legacy/state/lists/reducer.test.ts b/apps/cowswap-frontend/src/legacy/state/lists/reducer.test.ts index 8fe6778621..ce5824454c 100644 --- a/apps/cowswap-frontend/src/legacy/state/lists/reducer.test.ts +++ b/apps/cowswap-frontend/src/legacy/state/lists/reducer.test.ts @@ -1,11 +1,12 @@ +import { DEFAULT_ACTIVE_LIST_URLS_BY_NETWORK, DEFAULT_LIST_OF_LISTS_BY_NETWORK } from '@cowprotocol/common-const' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { createStore, Store } from 'redux' -import { DEFAULT_ACTIVE_LIST_URLS_BY_NETWORK, DEFAULT_LIST_OF_LISTS_BY_NETWORK } from 'legacy/constants/lists' -import { updateVersion } from 'legacy/state/global/actions' -import { fetchTokenList, acceptListUpdate, addList, removeList, enableList } from 'legacy/state/lists/actions' -import reducer, { ListsStateByNetwork } from 'legacy/state/lists/reducer' +import { fetchTokenList, acceptListUpdate, addList, removeList, enableList } from './actions' +import reducer, { ListsStateByNetwork } from './reducer' + +import { updateVersion } from '../global/actions' const DEFAULT_LIST_OF_LISTS = DEFAULT_LIST_OF_LISTS_BY_NETWORK[ChainId.MAINNET] diff --git a/apps/cowswap-frontend/src/legacy/state/lists/reducer.ts b/apps/cowswap-frontend/src/legacy/state/lists/reducer.ts index 26194307d5..e1a59f405c 100644 --- a/apps/cowswap-frontend/src/legacy/state/lists/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/lists/reducer.ts @@ -1,16 +1,14 @@ -import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' -import { getVersionUpgrade, TokenList, VersionUpgrade } from '@uniswap/token-lists' - -import { createReducer } from '@reduxjs/toolkit' - import { DEFAULT_ACTIVE_LIST_URLS_BY_NETWORK, DEFAULT_LIST_OF_LISTS_BY_NETWORK, DEFAULT_NETWORK_FOR_LISTS, UNSUPPORTED_LIST_URLS, -} from 'legacy/constants/lists' -import { updateVersion } from 'legacy/state/global/actions' -import { getChainIdValues } from 'legacy/utils/misc' +} from '@cowprotocol/common-const' +import { getChainIdValues } from '@cowprotocol/common-utils' +import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { getVersionUpgrade, TokenList, VersionUpgrade } from '@uniswap/token-lists' + +import { createReducer } from '@reduxjs/toolkit' import { UnsupportedToken } from 'api/gnosisProtocol' @@ -25,6 +23,8 @@ import { removeList, } from './actions' +import { updateVersion } from '../global/actions' + export interface ListsState { readonly byUrl: { readonly [url: string]: { diff --git a/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts b/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts index 069fb3cee5..3e446c5866 100644 --- a/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts +++ b/apps/cowswap-frontend/src/legacy/state/lists/wrappedTokenInfo.ts @@ -1,8 +1,7 @@ +import { isAddress } from '@cowprotocol/common-utils' import { Currency, Token } from '@uniswap/sdk-core' import { Tags, TokenInfo, TokenList } from '@uniswap/token-lists' -import { isAddress } from '../../utils' - type TagDetails = Tags[keyof Tags] export interface TagInfo extends TagDetails { id: string diff --git a/apps/cowswap-frontend/src/legacy/state/logs/hooks.ts b/apps/cowswap-frontend/src/legacy/state/logs/hooks.ts index f73ebd1b6b..1719211d3b 100644 --- a/apps/cowswap-frontend/src/legacy/state/logs/hooks.ts +++ b/apps/cowswap-frontend/src/legacy/state/logs/hooks.ts @@ -1,11 +1,9 @@ import { useEffect, useMemo } from 'react' +import { useBlockNumber } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' import { Filter } from '@ethersproject/providers' -import { useWalletInfo } from 'modules/wallet' - -import useBlockNumber from 'lib/hooks/useBlockNumber' - import { addListener, removeListener } from './slice' import { filterToKey, isHistoricalLog, Log } from './utils' diff --git a/apps/cowswap-frontend/src/legacy/state/multicall.tsx b/apps/cowswap-frontend/src/legacy/state/multicall.tsx new file mode 100644 index 0000000000..b4cb8342c2 --- /dev/null +++ b/apps/cowswap-frontend/src/legacy/state/multicall.tsx @@ -0,0 +1,13 @@ +import { useInterfaceMulticall, useBlockNumber } from '@cowprotocol/common-hooks' +import { createMulticall } from '@uniswap/redux-multicall' +import { useWeb3React } from '@web3-react/core' + +export const multicall = createMulticall() + +export function MulticallUpdater() { + const { chainId } = useWeb3React() + const latestBlockNumber = useBlockNumber() + const contract = useInterfaceMulticall() + + return +} diff --git a/apps/cowswap-frontend/src/legacy/state/orders/actions.ts b/apps/cowswap-frontend/src/legacy/state/orders/actions.ts index c9696db9b8..a08dd6ecd6 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/actions.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/actions.ts @@ -5,10 +5,10 @@ import { Token } from '@uniswap/sdk-core' import { createAction } from '@reduxjs/toolkit' -import { SerializedToken } from 'legacy/state/user/types' - import { ComposableCowInfo } from 'common/types' +import { SerializedToken } from '../user/types' + export enum OrderStatus { PENDING = 'pending', PRESIGNATURE_PENDING = 'presignaturePending', diff --git a/apps/cowswap-frontend/src/legacy/state/orders/buildCancellationPopupSummary.tsx b/apps/cowswap-frontend/src/legacy/state/orders/buildCancellationPopupSummary.tsx index da99578d51..98ac575f44 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/buildCancellationPopupSummary.tsx +++ b/apps/cowswap-frontend/src/legacy/state/orders/buildCancellationPopupSummary.tsx @@ -1,9 +1,13 @@ -import styled from 'styled-components/macro' - -import { CancellationSummary } from 'modules/account/containers/Transaction/styled' +import { shortenOrderId } from '@cowprotocol/common-utils' -import { shortenOrderId } from '../../utils' +import styled from 'styled-components/macro' +const CancellationSummary = styled.span` + padding: 12px; + margin: 0; + border-radius: 6px; + background: ${({ theme }) => theme.bg1}; +` // Moved this function to separate file to avoid curcular deps const Wrapper = styled.div` diff --git a/apps/cowswap-frontend/src/modules/orders/utils/flatOrdersStateNetwork.ts b/apps/cowswap-frontend/src/legacy/state/orders/flatOrdersStateNetwork.ts similarity index 78% rename from apps/cowswap-frontend/src/modules/orders/utils/flatOrdersStateNetwork.ts rename to apps/cowswap-frontend/src/legacy/state/orders/flatOrdersStateNetwork.ts index 32de96257a..04cb870963 100644 --- a/apps/cowswap-frontend/src/modules/orders/utils/flatOrdersStateNetwork.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/flatOrdersStateNetwork.ts @@ -1,4 +1,4 @@ -import { OrdersStateNetwork, PartialOrdersMap } from 'legacy/state/orders/reducer' +import { OrdersStateNetwork, PartialOrdersMap } from './reducer' export function flatOrdersStateNetwork(state: OrdersStateNetwork): PartialOrdersMap { return { diff --git a/apps/cowswap-frontend/src/legacy/state/orders/helpers.tsx b/apps/cowswap-frontend/src/legacy/state/orders/helpers.tsx index 56e2a876f5..589541102e 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/helpers.tsx +++ b/apps/cowswap-frontend/src/legacy/state/orders/helpers.tsx @@ -1,4 +1,4 @@ -import { BlockExplorerLinkType, formatOrderId } from 'legacy/utils' +import { BlockExplorerLinkType, formatOrderId } from '@cowprotocol/common-utils' import { OrderStatus } from './actions' import { OrderObject, OrdersStateNetwork } from './reducer' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts b/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts index 93fa1f58fc..e31c65b69d 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/hooks.ts @@ -1,16 +1,10 @@ import { useCallback, useMemo } from 'react' +import { isTruthy } from '@cowprotocol/common-utils' import { OrderClass, SupportedChainId } from '@cowprotocol/cow-sdk' import { useDispatch, useSelector } from 'react-redux' -import { AppDispatch, AppState } from 'legacy/state' -import { isOrderExpired, partialOrderUpdate } from 'legacy/state/orders/utils' -import { deserializeToken, serializeToken } from 'legacy/state/user/hooks' -import { isTruthy } from 'legacy/utils/misc' - -import { flatOrdersStateNetwork } from 'modules/orders/utils/flatOrdersStateNetwork' - import { OrderID } from 'api/gnosisProtocol' import { @@ -35,6 +29,7 @@ import { UpdatePresignGnosisSafeTxParams, clearOrdersStorage, } from './actions' +import { flatOrdersStateNetwork } from './flatOrdersStateNetwork' import { getDefaultNetworkState, ORDER_LIST_KEYS, @@ -46,6 +41,10 @@ import { PartialOrdersMap, V2OrderObject, } from './reducer' +import { isOrderExpired, partialOrderUpdate } from './utils' + +import { AppDispatch, AppState } from '../index' +import { deserializeToken, serializeToken } from '../user/hooks' export interface AddOrUpdateUnserialisedOrdersParams extends Omit { orders: Order[] diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.test.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.test.ts index 8e9c366034..d47f88132f 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.test.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.test.ts @@ -1,16 +1,15 @@ +import { isOrderInPendingTooLong, openNpsAppziSometimes } from '@cowprotocol/common-utils' import { OrderClass } from '@cowprotocol/cow-sdk' import { AnyAction, Dispatch, MiddlewareAPI } from 'redux' import { instance, mock, resetCalls, when } from 'ts-mockito' -import { isOrderInPendingTooLong, openNpsAppziSometimes } from 'legacy/utils/appzi' - import { appziMiddleware } from './appziMiddleware' import { AppState } from '../../index' import { getOrderByIdFromState } from '../helpers' -jest.mock('legacy/utils/appzi') +jest.mock('@cowprotocol/common-utils') jest.mock('../helpers', () => { return { ...jest.requireActual('../helpers'), diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.ts index a073cd9e64..69a95df740 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/appziMiddleware.ts @@ -1,11 +1,14 @@ +import { + getExplorerOrderLink, + isOrderInPendingTooLong, + openNpsAppziSometimes, + timeSinceInSeconds, +} from '@cowprotocol/common-utils' import { OrderClass, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { isAnyOf } from '@reduxjs/toolkit' import { AnyAction, Dispatch, Middleware, MiddlewareAPI } from 'redux' -import { timeSinceInSeconds } from '../../../../utils/time' -import { isOrderInPendingTooLong, openNpsAppziSometimes } from '../../../utils/appzi' -import { getExplorerOrderLink } from '../../../utils/explorer' import { AppState } from '../../index' import * as OrderActions from '../actions' import { getOrderByIdFromState } from '../helpers' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchCancelOrdersPopup.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchCancelOrdersPopup.ts index 9686978e14..44f701cbec 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchCancelOrdersPopup.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchCancelOrdersPopup.ts @@ -1,6 +1,7 @@ +import { orderAnalytics } from '@cowprotocol/analytics' + import { Dispatch, MiddlewareAPI } from 'redux' -import { orderAnalytics } from '../../../components/analytics' import { addPopup, AddPopupPayload } from '../../application/reducer' import { AppState } from '../../index' import { BaseOrder } from '../actions' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchExpireOrdersPopup.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchExpireOrdersPopup.ts index 55ed23ab6c..ca49e806de 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchExpireOrdersPopup.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchExpireOrdersPopup.ts @@ -1,6 +1,7 @@ +import { orderAnalytics } from '@cowprotocol/analytics' + import { Dispatch, MiddlewareAPI } from 'redux' -import { orderAnalytics } from '../../../components/analytics' import { addPopup } from '../../application/reducer' import { AppState } from '../../index' import { ExpireOrdersBatchParams } from '../actions' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchFulfillOrderPopup.tsx b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchFulfillOrderPopup.tsx index c9192cb58c..d57af681b8 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchFulfillOrderPopup.tsx +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchFulfillOrderPopup.tsx @@ -1,8 +1,8 @@ +import { orderAnalytics } from '@cowprotocol/analytics' + import { MiddlewareAPI } from '@reduxjs/toolkit' import { Dispatch } from 'redux' -import { orderAnalytics } from 'legacy/components/analytics' - import { ExecutedSummary } from 'common/pure/ExecutedSummary' import { parseOrder } from 'utils/orderUtils/parseOrder' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchPresignOrdersPopup.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchPresignOrdersPopup.ts index b8c3bcb04c..5e9ccdc52c 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchPresignOrdersPopup.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/batchPresignOrdersPopup.ts @@ -1,6 +1,7 @@ +import { orderAnalytics } from '@cowprotocol/analytics' + import { Dispatch, MiddlewareAPI } from 'redux' -import { orderAnalytics } from '../../../components/analytics' import { addPopup } from '../../application/reducer' import { AppState } from '../../index' import { PresignedOrdersParams } from '../actions' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/index.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/index.ts index 6c4190f6f5..e4e8161399 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/index.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/index.ts @@ -1,4 +1,3 @@ export { popupMiddleware } from './popupMiddleware' export { soundMiddleware } from './soundMiddleware' export { appziMiddleware } from './appziMiddleware' -export { composableOrdersPopupMiddleware } from './composableOrdersPopupMiddleware' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/pendingOrderPopup.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/pendingOrderPopup.ts index 208c437c45..10e801ef6d 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/pendingOrderPopup.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/pendingOrderPopup.ts @@ -1,7 +1,8 @@ +import { orderAnalytics } from '@cowprotocol/analytics' + import { MiddlewareAPI } from '@reduxjs/toolkit' import { Dispatch } from 'redux' -import { orderAnalytics } from '../../../components/analytics' import { addPopup, AddPopupPayload } from '../../application/reducer' import { AppState } from '../../index' import { AddPendingOrderParams } from '../actions' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/popupMiddleware.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/popupMiddleware.ts index b90d059b41..c007d14c4d 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/popupMiddleware.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/popupMiddleware.ts @@ -1,8 +1,8 @@ +import { isTruthy } from '@cowprotocol/common-utils' + import { isAnyOf } from '@reduxjs/toolkit' import { Middleware } from 'redux' -import { isTruthy } from 'legacy/utils/misc' - import { batchCancelOrdersPopup } from './batchCancelOrdersPopup' import { batchExpireOrdersPopup } from './batchExpireOrdersPopup' import { batchFulfillOrderPopup } from './batchFulfillOrderPopup' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts index 87a094ec6e..76ba9c1439 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts @@ -1,8 +1,8 @@ +import { getCowSoundError, getCowSoundSend, getCowSoundSuccess } from '@cowprotocol/common-utils' + import { AnyAction, Dispatch, MiddlewareAPI } from 'redux' import { instance, mock, resetCalls, when } from 'ts-mockito' -import { getCowSoundError, getCowSoundSend, getCowSoundSuccess } from 'legacy/utils/sound' - import { soundMiddleware } from './soundMiddleware' import { AppState } from '../../index' @@ -11,7 +11,7 @@ const mockStore = mock>() const nextMock = jest.fn() const actionMock = mock() -jest.mock('legacy/utils/sound') +jest.mock('@cowprotocol/common-utils') describe('soundMiddleware', () => { beforeEach(() => { diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts index 5a80d95192..23eb9683de 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts @@ -1,8 +1,9 @@ // On each Pending, Expired, Fulfilled order action a corresponding sound is dispatched +import { getCowSoundError, getCowSoundSend, getCowSoundSuccess } from '@cowprotocol/common-utils' + import { isAnyOf } from '@reduxjs/toolkit' import { AnyAction, Dispatch, Middleware, MiddlewareAPI } from 'redux' -import { getCowSoundError, getCowSoundSend, getCowSoundSuccess } from '../../../utils/sound' import { addPopup } from '../../application/reducer' import { AppState } from '../../index' import { AddPendingOrderParams, BatchOrdersUpdateParams, UpdateOrderParams } from '../actions' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/updateOrderPopup.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/updateOrderPopup.ts index ec774ddeb2..8d86c9828f 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/updateOrderPopup.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/updateOrderPopup.ts @@ -1,11 +1,10 @@ +import { orderAnalytics } from '@cowprotocol/analytics' +import { BlockExplorerLinkType } from '@cowprotocol/common-utils' import { OrderClass } from '@cowprotocol/cow-sdk' import { MiddlewareAPI } from '@reduxjs/toolkit' import { Dispatch } from 'redux' -import { BlockExplorerLinkType } from 'legacy/utils' - -import { orderAnalytics } from '../../../components/analytics' import { addPopup } from '../../application/reducer' import { AppState } from '../../index' import { UpdateOrderParams } from '../actions' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/mocks.ts b/apps/cowswap-frontend/src/legacy/state/orders/mocks.ts index 53bfe946f0..229a3b7894 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/mocks.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/mocks.ts @@ -1,12 +1,12 @@ +import { RADIX_DECIMAL } from '@cowprotocol/common-const' import { OrderClass, OrderKind } from '@cowprotocol/cow-sdk' import { Token } from '@uniswap/sdk-core' -import { RADIX_DECIMAL } from 'legacy/constants' -import store from 'legacy/state' -import { serializeToken } from 'legacy/state/user/hooks' - import { Order, OrderStatus, SerializedOrder, addPendingOrder, AddPendingOrderParams } from './actions' +import { cowSwapStore } from '../index' +import { serializeToken } from '../user/hooks' + const randomNumberInRange = (min: number, max: number) => { return Math.random() * (max - min) + min } @@ -122,6 +122,6 @@ export const mockOrderDispatches = { }, } - store.dispatch(addPendingOrder(actionParams)) + cowSwapStore.dispatch(addPendingOrder(actionParams)) }, } diff --git a/apps/cowswap-frontend/src/legacy/state/orders/priceUtils.ts b/apps/cowswap-frontend/src/legacy/state/orders/priceUtils.ts index 4c06b8fca2..4c01fee136 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/priceUtils.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/priceUtils.ts @@ -1,8 +1,8 @@ // Copied from @cowprotocol/cow-js -import { BigNumber } from 'bignumber.js' +import { DEFAULT_DECIMALS } from '@cowprotocol/common-const' -import { DEFAULT_DECIMALS } from 'legacy/constants' +import { BigNumber } from 'bignumber.js' interface PriceTokenInfo { amount: BigNumber | string diff --git a/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts b/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts index ad959f0526..26d7908258 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts @@ -3,8 +3,6 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { createReducer, PayloadAction } from '@reduxjs/toolkit' import { Writable } from 'types' -import { flatOrdersStateNetwork } from 'modules/orders/utils/flatOrdersStateNetwork' - import { OrderID } from 'api/gnosisProtocol' import { getIsComposableCowDiscreteOrder } from 'utils/orderUtils/getIsComposableCowDiscreteOrder' import { getIsComposableCowParentOrder } from 'utils/orderUtils/getIsComposableCowParentOrder' @@ -35,6 +33,7 @@ import { CONFIRMED_STATES, } from './actions' import { ContractDeploymentBlocks, MAX_ITEMS_PER_STATUS } from './consts' +import { flatOrdersStateNetwork } from './flatOrdersStateNetwork' export interface OrderObject { id: OrderID diff --git a/apps/cowswap-frontend/src/legacy/state/orders/utils.test.ts b/apps/cowswap-frontend/src/legacy/state/orders/utils.test.ts index f2335c134d..9cef5fc005 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/utils.test.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/utils.test.ts @@ -1,10 +1,9 @@ +import { USDC_MAINNET as USDC, USDT } from '@cowprotocol/common-const' import { OrderKind, OrderStatus, SigningScheme } from '@cowprotocol/cow-sdk' import { Price } from '@uniswap/sdk-core' import ms from 'ms.macro' -import { USDC_MAINNET as USDC, USDT } from 'legacy/constants/tokens' - import { generateOrder } from './mocks' import { classifyOrder, getOrderMarketPrice, isOrderUnfillable } from './utils' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/utils.ts b/apps/cowswap-frontend/src/legacy/state/orders/utils.ts index 7c0fde7b4a..3461931b06 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/utils.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/utils.ts @@ -1,21 +1,20 @@ +import { ONE_HUNDRED_PERCENT, PENDING_ORDERS_BUFFER, ZERO_FRACTION } from '@cowprotocol/common-const' +import { buildPriceFromCurrencyAmounts } from '@cowprotocol/common-utils' import { EnrichedOrder, OrderClass, OrderKind, OrderStatus } from '@cowprotocol/cow-sdk' import { Currency, CurrencyAmount, Price } from '@uniswap/sdk-core' import JSBI from 'jsbi' -import { PENDING_ORDERS_BUFFER, ZERO_FRACTION } from 'legacy/constants' -import { ONE_HUNDRED_PERCENT } from 'legacy/constants/misc' -import { AppDispatch } from 'legacy/state' -import { Order, updateOrder, UpdateOrderParams as UpdateOrderParamsAction } from 'legacy/state/orders/actions' -import { OUT_OF_MARKET_PRICE_DELTA_PERCENTAGE } from 'legacy/state/orders/consts' -import { UpdateOrderParams } from 'legacy/state/orders/hooks' -import { serializeToken } from 'legacy/state/user/hooks' - -import { buildPriceFromCurrencyAmounts } from 'modules/utils/orderUtils/buildPriceFromCurrencyAmounts' - import { getIsComposableCowParentOrder } from 'utils/orderUtils/getIsComposableCowParentOrder' import { getOrderSurplus } from 'utils/orderUtils/getOrderSurplus' +import { Order, updateOrder, UpdateOrderParams as UpdateOrderParamsAction } from './actions' +import { OUT_OF_MARKET_PRICE_DELTA_PERCENTAGE } from './consts' +import { UpdateOrderParams } from './hooks' + +import { AppDispatch } from '../index' +import { serializeToken } from '../user/hooks' + export type OrderTransitionStatus = | 'unknown' | 'fulfilled' diff --git a/apps/cowswap-frontend/src/legacy/state/price/actions.ts b/apps/cowswap-frontend/src/legacy/state/price/actions.ts index 0d4d8bfe8e..10457c4fcf 100644 --- a/apps/cowswap-frontend/src/legacy/state/price/actions.ts +++ b/apps/cowswap-frontend/src/legacy/state/price/actions.ts @@ -2,9 +2,8 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { createAction } from '@reduxjs/toolkit' -import { LegacyFeeQuoteParams } from 'api/gnosisProtocol/legacy/types' - import { QuoteInformationObject } from './reducer' +import { LegacyFeeQuoteParams } from './types' export type UpdateQuoteParams = Omit diff --git a/apps/cowswap-frontend/src/legacy/state/price/hooks.ts b/apps/cowswap-frontend/src/legacy/state/price/hooks.ts index f8b611598c..798c0e7bd9 100644 --- a/apps/cowswap-frontend/src/legacy/state/price/hooks.ts +++ b/apps/cowswap-frontend/src/legacy/state/price/hooks.ts @@ -4,11 +4,6 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { useDispatch, useSelector } from 'react-redux' -import { AppDispatch, AppState } from 'legacy/state' -import { useSwapState } from 'legacy/state/swap/hooks' - -import { useWalletInfo } from 'modules/wallet' - import { updateQuote, UpdateQuoteParams, @@ -22,6 +17,8 @@ import { } from './actions' import { QuoteInformationObject, QuotesMap } from './reducer' +import { AppDispatch, AppState } from '../index' + type GetNewQuoteCallback = (params: GetQuoteParams) => void type RefreshQuoteCallback = (params: RefreshQuoteParams) => void type AddPriceCallback = (params: UpdateQuoteParams) => void @@ -77,16 +74,6 @@ export const useGetQuoteAndStatus = (params: QuoteParams): UseGetQuoteAndStatus return { quote, isGettingNewQuote, isRefreshingQuote } } -// syntactic sugar for not needing to pass swapstate -export function useIsQuoteRefreshing() { - const { chainId } = useWalletInfo() - const { - INPUT: { currencyId }, - } = useSwapState() - const { isRefreshingQuote } = useGetQuoteAndStatus({ token: currencyId, chainId }) - return isRefreshingQuote -} - export const useGetNewQuote = (): GetNewQuoteCallback => { const dispatch = useDispatch() return useCallback((params: GetQuoteParams) => dispatch(getNewQuote(params)), [dispatch]) diff --git a/apps/cowswap-frontend/src/legacy/state/price/middleware.ts b/apps/cowswap-frontend/src/legacy/state/price/middleware.ts index 7632c2ba63..43cc24900d 100644 --- a/apps/cowswap-frontend/src/legacy/state/price/middleware.ts +++ b/apps/cowswap-frontend/src/legacy/state/price/middleware.ts @@ -1,10 +1,11 @@ -import { Middleware, isAnyOf } from '@reduxjs/toolkit' +import { initialPriceLoadAnalytics } from '@cowprotocol/analytics' -import { initialPriceLoadAnalytics } from 'legacy/components/analytics' -import { AppState } from 'legacy/state' +import { Middleware, isAnyOf } from '@reduxjs/toolkit' import * as PriceActions from './actions' +import { AppState } from '../index' + const isUpdateQuoteAction = isAnyOf(PriceActions.updateQuote) export const priceMiddleware: Middleware, AppState> = (store) => (next) => (action) => { diff --git a/apps/cowswap-frontend/src/legacy/state/price/reducer.ts b/apps/cowswap-frontend/src/legacy/state/price/reducer.ts index 73f9c2bf8b..1751d9522c 100644 --- a/apps/cowswap-frontend/src/legacy/state/price/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/price/reducer.ts @@ -4,16 +4,17 @@ import { OrderKind } from '@cowprotocol/cow-sdk' import { createReducer, PayloadAction, current } from '@reduxjs/toolkit' import { FeeInformation, PriceInformation } from 'types' -import { Writable } from 'legacy/types' - -import { LegacyFeeQuoteParams } from 'api/gnosisProtocol/legacy/types' - import { updateQuote, setQuoteError, getNewQuote, refreshQuote, QuoteError } from './actions' +import { LegacyFeeQuoteParams } from './types' import { PrefillStateRequired } from '../orders/reducer' // API Doc: https://protocol-rinkeby.dev.gnosisdev.com/api +type Writable = { + -readonly [K in keyof T]: T[K] +} + export const EMPTY_FEE = { feeAsCurrency: undefined, amount: '0', diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/legacy/types.ts b/apps/cowswap-frontend/src/legacy/state/price/types.ts similarity index 87% rename from apps/cowswap-frontend/src/api/gnosisProtocol/legacy/types.ts rename to apps/cowswap-frontend/src/legacy/state/price/types.ts index f380b208c4..49094cc816 100644 --- a/apps/cowswap-frontend/src/api/gnosisProtocol/legacy/types.ts +++ b/apps/cowswap-frontend/src/legacy/state/price/types.ts @@ -1,8 +1,17 @@ import { AppData, AppDataHash, EnrichedOrder, PriceQuality, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' -import { FeeInformation, PriceInformation } from 'types' +type GpPriceStrategy = 'COWSWAP' | 'LEGACY' -import { GpPriceStrategy } from 'legacy/state/gas/atoms' +interface PriceInformation { + token: string + amount: string | null + quoteId?: number +} + +export interface FeeInformation { + expirationDate: string + amount: string +} interface FeeQuoteParams extends Pick { amount: string diff --git a/apps/cowswap-frontend/src/legacy/state/profile/hooks.tsx b/apps/cowswap-frontend/src/legacy/state/profile/hooks.tsx index 07704d829e..c8d83b3c2b 100644 --- a/apps/cowswap-frontend/src/legacy/state/profile/hooks.tsx +++ b/apps/cowswap-frontend/src/legacy/state/profile/hooks.tsx @@ -1,9 +1,9 @@ import { useCallback } from 'react' -import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' - import { closeAnnouncement } from './actions' +import { useAppDispatch, useAppSelector } from '../hooks' + export function useAnnouncementVisible(contentHash?: string): boolean { const announcementVisible = useAppSelector((state) => state.profile.announcementVisible) diff --git a/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts b/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts index 66ea956c4d..42089c4eb7 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts +++ b/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts @@ -1,9 +1,17 @@ +import { ONE_FRACTION } from '@cowprotocol/common-const' +import { CanonicalMarketParams, getCanonicalMarket } from '@cowprotocol/common-utils' import { CurrencyAmount, Currency, TradeType, Price, Percent } from '@uniswap/sdk-core' -import { FeeInformation, PriceInformation } from 'types' +interface PriceInformation { + token: string + amount: string | null + quoteId?: number +} -import { ONE_FRACTION } from 'legacy/constants/misc' -import { CanonicalMarketParams, getCanonicalMarket } from 'legacy/utils/misc' +interface FeeInformation { + expirationDate: string + amount: string +} export type FeeForTrade = { feeAsCurrency: CurrencyAmount } & Pick diff --git a/apps/cowswap-frontend/src/legacy/state/swap/actions.ts b/apps/cowswap-frontend/src/legacy/state/swap/actions.ts index 200de24486..8c0b06d0c9 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/actions.ts +++ b/apps/cowswap-frontend/src/legacy/state/swap/actions.ts @@ -1,9 +1,6 @@ import { createAction } from '@reduxjs/toolkit' -export enum Field { - INPUT = 'INPUT', - OUTPUT = 'OUTPUT', -} +import { Field } from '../types' export interface ReplaceOnlyTradeRawStatePayload { readonly chainId: number | null diff --git a/apps/cowswap-frontend/src/legacy/state/swap/extension.ts b/apps/cowswap-frontend/src/legacy/state/swap/extension.ts index d6cfdf4f0b..15d82fc17d 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/extension.ts +++ b/apps/cowswap-frontend/src/legacy/state/swap/extension.ts @@ -3,10 +3,10 @@ import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' import JSBI from 'jsbi' -import { QuoteInformationObject } from 'legacy/state/price/reducer' - import TradeGp, { _constructTradePrice } from './TradeGp' +import { QuoteInformationObject } from '../price/reducer' + interface TradeParams { parsedAmount?: CurrencyAmount inputCurrency?: Currency | null diff --git a/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts b/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts index 994ea43f08..6b7b0fe0a7 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/swap/reducer.ts @@ -1,12 +1,11 @@ +import { NATIVE_CURRENCY_BUY_TOKEN, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' +import { parsedQueryString } from '@cowprotocol/common-hooks' +import { getIsNativeToken, getIsWrapOrUnwrap } from '@cowprotocol/common-utils' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { createReducer } from '@reduxjs/toolkit' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' -import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' -import { parsedQueryString } from 'legacy/hooks/useParsedQueryString' import { - Field, replaceOnlyTradeRawState, replaceSwapState, selectCurrency, @@ -14,13 +13,11 @@ import { setRecipientAddress, switchCurrencies, typeInput, -} from 'legacy/state/swap/actions' - -import { getIsNativeToken } from 'utils/getIsNativeToken' -import { getIsWrapOrUnwrap } from 'utils/getIsWrapOrUnwrap' - +} from './actions' import { queryParametersToSwapState } from './utils' +import { Field } from '../types' + export interface SwapState { // Mod: added chainId chainId: number | null diff --git a/apps/cowswap-frontend/src/legacy/state/swap/trade.test.ts b/apps/cowswap-frontend/src/legacy/state/swap/trade.test.ts index 2e1e27ef02..e0209d8d12 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/trade.test.ts +++ b/apps/cowswap-frontend/src/legacy/state/swap/trade.test.ts @@ -1,11 +1,9 @@ +import { DEFAULT_PRECISION, LONG_PRECISION, WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const' import { OrderKind } from '@cowprotocol/cow-sdk' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { parseUnits } from '@ethersproject/units' import { CurrencyAmount, Fraction, Price, Currency, Percent, Token, TradeType } from '@uniswap/sdk-core' -import { DEFAULT_PRECISION, LONG_PRECISION } from 'legacy/constants' -import { WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens' - import { stringToCurrency } from './extension' import Trade, { _constructTradePrice } from './TradeGp' import TradeGp from './TradeGp' diff --git a/apps/cowswap-frontend/src/legacy/state/swap/utils.ts b/apps/cowswap-frontend/src/legacy/state/swap/utils.ts index 503ecd6f26..43bdd3004b 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/utils.ts +++ b/apps/cowswap-frontend/src/legacy/state/swap/utils.ts @@ -1,14 +1,14 @@ +import { TOKEN_SHORTHANDS, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' +import { isAddress } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency } from '@uniswap/sdk-core' import { ParsedQs } from 'qs' -import { TOKEN_SHORTHANDS, WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' -import { isAddress } from 'legacy/utils' - -import { Field } from './actions' import { SwapState } from './reducer' +import { Field } from '../types' + export function isWrappingTrade( sellCurrency: Currency | null | undefined, buyCurrency: Currency | null | undefined, diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/types.ts b/apps/cowswap-frontend/src/legacy/state/types.ts similarity index 73% rename from apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/types.ts rename to apps/cowswap-frontend/src/legacy/state/types.ts index 3b873c4d6c..a9dc73eaa8 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/types.ts +++ b/apps/cowswap-frontend/src/legacy/state/types.ts @@ -8,3 +8,8 @@ export enum ConfirmOperationType { CONVERT_VCOW, CLAIM_VESTED_COW, } + +export enum Field { + INPUT = 'INPUT', + OUTPUT = 'OUTPUT', +} diff --git a/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx b/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx index b6a85b8eb2..d4a328ff5a 100644 --- a/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx +++ b/apps/cowswap-frontend/src/legacy/state/user/hooks.tsx @@ -1,20 +1,13 @@ import { useCallback, useMemo } from 'react' +import { L2_DEADLINE_FROM_NOW, NATIVE_CURRENCY_BUY_TOKEN, SupportedLocale } from '@cowprotocol/common-const' +import { calculateValidTo } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, Percent, Token } from '@uniswap/sdk-core' import JSBI from 'jsbi' import { shallowEqual } from 'react-redux' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' -import { SupportedLocale } from 'legacy/constants/locales' -import { L2_DEADLINE_FROM_NOW } from 'legacy/constants/misc' -import { AppState } from 'legacy/state' -import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' - -import { useWalletInfo } from 'modules/wallet' - -import { calculateValidTo } from 'utils/time' - import { addSerializedToken, initFavouriteTokens, @@ -30,7 +23,9 @@ import { } from './reducer' import { SerializedToken } from './types' -import { useSwapActionHandlers } from '../swap/hooks' +import { useAppDispatch, useAppSelector } from '../hooks' +import { AppState } from '../index' +import { setRecipient } from '../swap/actions' export function deserializeToken(serializedToken: SerializedToken): Token { return new Token( @@ -107,7 +102,12 @@ export function useIsRecipientToggleVisible(): boolean { export function useRecipientToggleManager(): [boolean, (value?: boolean) => void] { const dispatch = useAppDispatch() const isVisible = useIsRecipientToggleVisible() - const { onChangeRecipient } = useSwapActionHandlers() + const onChangeRecipient = useCallback( + (recipient: string | null) => { + dispatch(setRecipient({ recipient })) + }, + [dispatch] + ) const toggleVisibility = useCallback( (value?: boolean) => { diff --git a/apps/cowswap-frontend/src/legacy/state/user/reducer.ts b/apps/cowswap-frontend/src/legacy/state/user/reducer.ts index a9d8b4f11d..428a2f6d38 100644 --- a/apps/cowswap-frontend/src/legacy/state/user/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/user/reducer.ts @@ -1,15 +1,13 @@ +import { COMMON_BASES, DEFAULT_DEADLINE_FROM_NOW, SupportedLocale } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { ConnectionType } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' import { createSlice } from '@reduxjs/toolkit' -import { SupportedLocale } from 'legacy/constants/locales' -import { DEFAULT_DEADLINE_FROM_NOW } from 'legacy/constants/misc' -import { COMMON_BASES } from 'legacy/constants/routing' -import { updateVersion } from 'legacy/state/global/actions' -import { SerializedPair, SerializedToken } from 'legacy/state/user/types' +import { SerializedPair, SerializedToken } from './types' -import { ConnectionType } from 'modules/wallet' +import { updateVersion } from '../global/actions' // MOD imports // import { serializeToken } from './hooks' diff --git a/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx b/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx index bee9e3bd97..82fe28e0a3 100644 --- a/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx +++ b/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx @@ -1,12 +1,13 @@ -import { transparentize, darken, lighten } from 'polished' +import Cursor1 from '@cowprotocol/assets/cow-swap/cursor1.gif' +import Cursor2 from '@cowprotocol/assets/cow-swap/cursor2.gif' +import Cursor3 from '@cowprotocol/assets/cow-swap/cursor3.gif' +import Cursor4 from '@cowprotocol/assets/cow-swap/cursor4.gif' +import { ButtonSize } from '@cowprotocol/ui' + +import { transparentize, lighten, darken } from 'polished' import { createGlobalStyle, css } from 'styled-components/macro' -import Cursor1 from 'legacy/assets/cow-swap/cursor1.gif' -import Cursor2 from 'legacy/assets/cow-swap/cursor2.gif' -import Cursor3 from 'legacy/assets/cow-swap/cursor3.gif' -import Cursor4 from 'legacy/assets/cow-swap/cursor4.gif' import { colorsUniswap } from 'legacy/theme/colorsUniswap' -import { ButtonSize } from 'legacy/theme/enum' import { Colors } from 'legacy/theme/styled' import { UI } from 'common/constants/theme' @@ -400,7 +401,7 @@ export const UniThemedGlobalStyle = css` ${UI.COLOR_YELLOW_LIGHT}: ${({ theme }) => theme.alert2}; ${UI.COLOR_GREEN}: ${({ theme }) => theme.success}; ${UI.COLOR_RED}: ${({ theme }) => theme.danger}; - + // Base ${UI.COLOR_BORDER}: var(${UI.COLOR_GREY}); ${UI.COLOR_CONTAINER_BG_01}: ${({ theme }) => theme.bg1}; @@ -409,37 +410,43 @@ export const UniThemedGlobalStyle = css` ${UI.BORDER_RADIUS_NORMAL}: 24px; ${UI.PADDING_NORMAL}: 24px; ${UI.BOX_SHADOW_NORMAL}: 0 1.5rem 1rem #00000008,0 .75rem .75rem #0000000a,0 .25rem .375rem #0000000d; - + // Icons ${UI.ICON_SIZE_NORMAL}: 24px; ${UI.ICON_COLOR_NORMAL}: var(${UI.COLOR_TEXT1}); // [STATE] Information (light blue) ${UI.COLOR_INFORMATION}: var(${UI.COLOR_LIGHT_BLUE}); - ${UI.COLOR_INFORMATION_BG}: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.information) : transparentize(0.85, theme.information))}; - ${UI.COLOR_INFORMATION_TEXT}: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.information) : darken(0.2, theme.information))}; + ${UI.COLOR_INFORMATION_BG}: ${({ theme }) => + theme.darkMode ? transparentize(0.9, theme.information) : transparentize(0.85, theme.information)}; + ${UI.COLOR_INFORMATION_TEXT}: ${({ theme }) => + theme.darkMode ? lighten(0.2, theme.information) : darken(0.2, theme.information)}; // [STATE] Alert (yellow) ${UI.COLOR_ALERT}: var(${UI.COLOR_YELLOW}); - ${UI.COLOR_ALERT_BG}: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.alert) : transparentize(0.85, theme.alert))}; + ${UI.COLOR_ALERT_BG}: ${({ theme }) => + theme.darkMode ? transparentize(0.9, theme.alert) : transparentize(0.85, theme.alert)}; ${UI.COLOR_ALERT_TEXT}: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.alert) : darken(0.2, theme.alert))}; - + // [STATE] Alert2 (yellow lighter) ${UI.COLOR_ALERT2}: var(${UI.COLOR_YELLOW_LIGHT}); ${UI.COLOR_ALERT2_BG}: var(${UI.COLOR_YELLOW_LIGHT}); ${UI.COLOR_ALERT2_TEXT}: var(${UI.COLOR_BLUE}); - + // [STATE] Success (green) ${UI.COLOR_SUCCESS}: var(${UI.COLOR_GREEN}); - ${UI.COLOR_SUCCESS_BG}: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.success) : transparentize(0.85, theme.success))}; - ${UI.COLOR_SUCCESS_TEXT}: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.success) : darken(0.1, theme.success))}; + ${UI.COLOR_SUCCESS_BG}: ${({ theme }) => + theme.darkMode ? transparentize(0.9, theme.success) : transparentize(0.85, theme.success)}; + ${UI.COLOR_SUCCESS_TEXT}: ${({ theme }) => + theme.darkMode ? lighten(0.2, theme.success) : darken(0.1, theme.success)}; - // [STATE] Danger (red) ${UI.COLOR_DANGER}: var(${UI.COLOR_RED}); - ${UI.COLOR_DANGER_BG}: ${({ theme }) => (theme.darkMode ? transparentize(0.9, theme.danger) : transparentize(0.85, theme.danger))}; - ${UI.COLOR_DANGER_TEXT}: ${({ theme }) => (theme.darkMode ? lighten(0.2, theme.danger) : darken(0.2, theme.danger))}; - + ${UI.COLOR_DANGER_BG}: ${({ theme }) => + theme.darkMode ? transparentize(0.9, theme.danger) : transparentize(0.85, theme.danger)}; + ${UI.COLOR_DANGER_TEXT}: ${({ theme }) => + theme.darkMode ? lighten(0.2, theme.danger) : darken(0.2, theme.danger)}; + // Text ${UI.COLOR_TEXT1}: ${({ theme }) => theme.text1}; ${UI.COLOR_TEXT1_INACTIVE}: ${({ theme }) => transparentize(0.4, theme.text1)}; @@ -464,7 +471,7 @@ export const UniThemedGlobalStyle = css` html { color: var(${UI.COLOR_TEXT1}); - background-color: var(${UI.COLOR_CONTAINER_BG_02}) + background-color: var(${UI.COLOR_CONTAINER_BG_02}); } body { min-height: 100vh; diff --git a/apps/cowswap-frontend/src/legacy/theme/components.tsx b/apps/cowswap-frontend/src/legacy/theme/components.tsx index 3b1b36f7af..ebd98144fa 100644 --- a/apps/cowswap-frontend/src/legacy/theme/components.tsx +++ b/apps/cowswap-frontend/src/legacy/theme/components.tsx @@ -1,12 +1,9 @@ -import React, { HTMLProps } from 'react' +import React from 'react' -import { ArrowLeft, ExternalLink as LinkIconFeather, Trash, X } from 'react-feather' +import { ArrowLeft, Trash, X } from 'react-feather' import { Link } from 'react-router-dom' import styled, { keyframes } from 'styled-components/macro' -import { externalLinkAnalytics, outboundLink } from 'legacy/components/analytics' -import { anonymizeLink } from 'legacy/utils/anonymizeLink' - import { UI } from 'common/constants/theme' export const ButtonText = styled.button` @@ -95,55 +92,6 @@ export const StyledInternalLink = styled(Link)` } ` -export const StyledLink = styled.a` - text-decoration: none; - cursor: pointer; - color: ${({ theme }) => theme.text3}; - font-weight: 500; - - :hover { - text-decoration: underline; - } - - :focus { - outline: none; - text-decoration: none; - } - - :active { - text-decoration: none; - } -` - -const LinkIconWrapper = styled.a` - text-decoration: none; - cursor: pointer; - align-items: center; - justify-content: center; - display: flex; - - :hover { - text-decoration: none; - opacity: 0.7; - } - - :focus { - outline: none; - text-decoration: none; - } - - :active { - text-decoration: none; - } -` - -export const LinkIcon = styled(LinkIconFeather)` - height: 16px; - width: 18px; - margin-left: 10px; - stroke: ${({ theme }) => theme.text3}; -` - export const TrashIcon = styled(Trash)` height: 16px; width: 18px; @@ -176,66 +124,6 @@ export const UniTokenAnimated = styled.img` filter: drop-shadow(0px 2px 4px rgba(0, 0, 0, 0.15)); ` -export function handleClickExternalLink(event: React.MouseEvent) { - const { target, href } = event.currentTarget - - const anonymizedHref = anonymizeLink(href) - - // don't prevent default, don't redirect if it's a new tab - if (target === '_blank' || event.ctrlKey || event.metaKey) { - outboundLink({ label: anonymizedHref }, () => { - console.debug('Fired outbound link event', anonymizedHref) - }) - } else { - event.preventDefault() - // send a ReactGA event and then trigger a location change - outboundLink({ label: anonymizedHref }, () => { - window.location.href = anonymizedHref - }) - } -} - -/** - * Outbound link that handles firing google analytics events - */ -export function ExternalLink({ - target = '_blank', - href, - rel = 'noopener noreferrer', - onClickOptional, - ...rest -}: Omit, 'as' | 'ref' | 'onClick'> & { - href: string - onClickOptional?: React.MouseEventHandler -}) { - return ( - { - if (onClickOptional) onClickOptional(event) - handleClickExternalLink(event) - externalLinkAnalytics(href) - }} - {...rest} - /> - ) -} - -export function ExternalLinkIcon({ - target = '_blank', - href, - rel = 'noopener noreferrer', - ...rest -}: Omit, 'as' | 'ref' | 'onClick'> & { href: string }) { - return ( - - - - ) -} - const rotate = keyframes` from { transform: rotate(0deg); diff --git a/apps/cowswap-frontend/src/legacy/theme/styled.d.ts b/apps/cowswap-frontend/src/legacy/theme/styled.d.ts index 7e0a5f3a3f..cc2c5d35a2 100644 --- a/apps/cowswap-frontend/src/legacy/theme/styled.d.ts +++ b/apps/cowswap-frontend/src/legacy/theme/styled.d.ts @@ -1,4 +1,4 @@ -import { ButtonSize } from 'legacy/theme/enum' +import { ButtonSize } from '@cowprotocol/ui' export type Color = string diff --git a/apps/cowswap-frontend/src/legacy/utils/constructSameAddressMap.ts b/apps/cowswap-frontend/src/legacy/utils/constructSameAddressMap.ts deleted file mode 100644 index 2d911f648c..0000000000 --- a/apps/cowswap-frontend/src/legacy/utils/constructSameAddressMap.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { SupportedChainId } from '@cowprotocol/cow-sdk' - -const DEFAULT_NETWORKS = [SupportedChainId.MAINNET, SupportedChainId.GOERLI] - -export function constructSameAddressMap( - address: T, - additionalNetworks: SupportedChainId[] = [] -): { [chainId: number]: T } { - return DEFAULT_NETWORKS.concat(additionalNetworks).reduce<{ [chainId: number]: T }>((memo, chainId) => { - memo[chainId] = address - return memo - }, {}) -} diff --git a/apps/cowswap-frontend/src/legacy/utils/listVersionLabel.ts b/apps/cowswap-frontend/src/legacy/utils/listVersionLabel.ts deleted file mode 100644 index 8717e0a5ea..0000000000 --- a/apps/cowswap-frontend/src/legacy/utils/listVersionLabel.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Version } from '@uniswap/token-lists' - -export default function listVersionLabel(version: Version): string { - return `v${version.major}.${version.minor}.${version.patch}` -} diff --git a/apps/cowswap-frontend/src/legacy/utils/price.ts b/apps/cowswap-frontend/src/legacy/utils/price.ts index 3db573c1d0..43c2249ebf 100644 --- a/apps/cowswap-frontend/src/legacy/utils/price.ts +++ b/apps/cowswap-frontend/src/legacy/utils/price.ts @@ -1,13 +1,13 @@ +import { toErc20Address } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/cow-sdk' import { Percent } from '@uniswap/sdk-core' import BigNumberJs from 'bignumber.js' import { FeeInformation, PriceInformation } from 'types' -import { toErc20Address } from 'legacy/utils/tokens' - import { getQuote } from 'api/gnosisProtocol' -import { LegacyFeeQuoteParams, LegacyPriceQuoteParams, LegacyQuoteParams } from 'api/gnosisProtocol/legacy/types' + +import { LegacyFeeQuoteParams, LegacyPriceQuoteParams, LegacyQuoteParams } from '../state/price/types' export type QuoteResult = [PromiseSettledResult, PromiseSettledResult] @@ -58,7 +58,7 @@ export async function getBestQuote({ }) }) } else { - console.debug('[GP PRICE::API] getBestQuote - Attempting best quote retrieval using LEGACY strategy, hang tight.') + console.debug('legacy strategy, hang tight.') const { getBestQuoteLegacy } = await import('legacy/utils/priceLegacy') diff --git a/apps/cowswap-frontend/src/legacy/utils/priceLegacy.ts b/apps/cowswap-frontend/src/legacy/utils/priceLegacy.ts index bc39b49392..488b728d74 100644 --- a/apps/cowswap-frontend/src/legacy/utils/priceLegacy.ts +++ b/apps/cowswap-frontend/src/legacy/utils/priceLegacy.ts @@ -1,3 +1,5 @@ +import { PRICE_API_TIMEOUT_MS } from '@cowprotocol/common-const' +import { getCanonicalMarket, isPromiseFulfilled, withTimeout } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/contracts' import { BigNumber } from '@ethersproject/bignumber' @@ -5,9 +7,6 @@ import * as Sentry from '@sentry/browser' import BigNumberJs from 'bignumber.js' import { FeeInformation, PriceInformation } from 'types' -import { PRICE_API_TIMEOUT_MS } from 'legacy/constants' -import { getCanonicalMarket, isPromiseFulfilled, withTimeout } from 'legacy/utils/misc' - import { getPriceQuote as getPriceQuote1inch, PriceQuote1inch, @@ -15,18 +14,19 @@ import { } from 'api/1inch' import { getQuote } from 'api/gnosisProtocol' import GpQuoteError, { GpQuoteErrorCodes } from 'api/gnosisProtocol/errors/QuoteError' +import { + getPriceQuote as getPriceQuoteMatcha, + MatchaPriceQuote, + toPriceInformation as toPriceInformationMatcha, +} from 'api/matcha-0x' + import { LegacyPriceInformationWithSource, LegacyPriceQuoteError, LegacyPriceQuoteParams, LegacyPromiseRejectedResultWithSource, LegacyQuoteParams, -} from 'api/gnosisProtocol/legacy/types' -import { - getPriceQuote as getPriceQuoteMatcha, - MatchaPriceQuote, - toPriceInformation as toPriceInformationMatcha, -} from 'api/matcha-0x' +} from '../state/price/types' /** * ************************************************** * @@ -147,7 +147,7 @@ function _extractPriceAndErrorPromiseValues( } function _checkFeeErrorForData(error: GpQuoteError) { - console.warn('[getBestQuote:Legacy]::Fee error', error) + console.warn('legacy]::Fee error', error) const feeAmount = error?.data?.fee_amount || error?.data?.feeAmount const feeExpiration = error?.data?.expiration diff --git a/apps/cowswap-frontend/src/legacy/utils/prices.ts b/apps/cowswap-frontend/src/legacy/utils/prices.ts index 13571b1a92..42912414f0 100644 --- a/apps/cowswap-frontend/src/legacy/utils/prices.ts +++ b/apps/cowswap-frontend/src/legacy/utils/prices.ts @@ -1,14 +1,13 @@ -import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' - -import { Field } from 'legacy/state/swap/actions' -import TradeGp from 'legacy/state/swap/TradeGp' - import { ALLOWED_PRICE_IMPACT_HIGH, ALLOWED_PRICE_IMPACT_LOW, ALLOWED_PRICE_IMPACT_MEDIUM, BLOCKED_PRICE_IMPACT_NON_EXPERT, -} from '../constants/misc' +} from '@cowprotocol/common-const' +import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' + +import TradeGp from 'legacy/state/swap/TradeGp' +import { Field } from 'legacy/state/types' const IMPACT_TIERS = [ BLOCKED_PRICE_IMPACT_NON_EXPERT, diff --git a/apps/cowswap-frontend/src/legacy/utils/trade.ts b/apps/cowswap-frontend/src/legacy/utils/trade.ts index 7559a2dccb..55d856f7cc 100644 --- a/apps/cowswap-frontend/src/legacy/utils/trade.ts +++ b/apps/cowswap-frontend/src/legacy/utils/trade.ts @@ -1,3 +1,5 @@ +import { RADIX_DECIMAL, NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' +import { isAddress, shortenAddress, formatTokenAmount, formatSymbol } from '@cowprotocol/common-utils' import { EcdsaSigningScheme, OrderClass, @@ -12,17 +14,13 @@ import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { orderBookApi } from 'cowSdk' -import { NATIVE_CURRENCY_BUY_ADDRESS, RADIX_DECIMAL } from 'legacy/constants' import { ChangeOrderStatusParams, Order, OrderStatus } from 'legacy/state/orders/actions' import { AddUnserialisedPendingOrderParams } from 'legacy/state/orders/hooks' -import { isAddress, shortenAddress } from 'legacy/utils/index' import { AppDataInfo } from 'modules/appData' import { getTrades, OrderID } from 'api/gnosisProtocol' import { getProfileData } from 'api/gnosisProtocol/api' -import { formatTokenAmount } from 'utils/amountFormat' -import { formatSymbol } from 'utils/format' export type PostOrderParams = { account: string diff --git a/apps/cowswap-frontend/src/lib/hooks/multicall.ts b/apps/cowswap-frontend/src/lib/hooks/multicall.ts index e507f78a4f..21c7aa5138 100644 --- a/apps/cowswap-frontend/src/lib/hooks/multicall.ts +++ b/apps/cowswap-frontend/src/lib/hooks/multicall.ts @@ -1,9 +1,8 @@ -import { SkipFirst } from 'legacy/types/tuple' - -import { useWalletInfo } from 'modules/wallet' +import { useBlockNumber } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' -import useBlockNumber from 'lib/hooks/useBlockNumber' -import multicall from 'lib/state/multicall' +import { multicall } from 'legacy/state/multicall' +import { SkipFirst } from 'legacy/types/tuple' export type { CallStateResult } from '@uniswap/redux-multicall' // re-export for convenience export { NEVER_RELOAD } from '@uniswap/redux-multicall' // re-export for convenience diff --git a/apps/cowswap-frontend/src/lib/hooks/useApproval.ts b/apps/cowswap-frontend/src/lib/hooks/useApproval.ts index 09d883c051..3f9d6d1372 100644 --- a/apps/cowswap-frontend/src/lib/hooks/useApproval.ts +++ b/apps/cowswap-frontend/src/lib/hooks/useApproval.ts @@ -1,16 +1,15 @@ import { useCallback, useMemo } from 'react' +import { useTokenContract } from '@cowprotocol/common-hooks' +import { calculateGasMargin } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { MaxUint256 } from '@ethersproject/constants' import { TransactionResponse } from '@ethersproject/providers' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { useTokenContract } from 'legacy/hooks/useContract' import { useTokenAllowance } from 'legacy/hooks/useTokenAllowance' -import { calculateGasMargin } from 'legacy/utils/calculateGasMargin' - -import { useWalletInfo } from 'modules/wallet' export enum ApprovalState { UNKNOWN = 'UNKNOWN', diff --git a/apps/cowswap-frontend/src/lib/hooks/useCurrency.ts b/apps/cowswap-frontend/src/lib/hooks/useCurrency.ts index 5cdf894684..12e4687e15 100644 --- a/apps/cowswap-frontend/src/lib/hooks/useCurrency.ts +++ b/apps/cowswap-frontend/src/lib/hooks/useCurrency.ts @@ -1,17 +1,14 @@ import { useMemo } from 'react' +import { TOKEN_SHORTHANDS } from '@cowprotocol/common-const' +import { useBytes32TokenContract, useTokenContract } from '@cowprotocol/common-hooks' +import { isAddress } from '@cowprotocol/common-utils' +import { isChainAllowed, useWalletInfo } from '@cowprotocol/wallet' import { arrayify } from '@ethersproject/bytes' import { parseBytes32String } from '@ethersproject/strings' import { Currency, Token } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' -import { TOKEN_SHORTHANDS } from 'legacy/constants/tokens' -import { useBytes32TokenContract, useTokenContract } from 'legacy/hooks/useContract' -import { isAddress } from 'legacy/utils' - -import { useWalletInfo } from 'modules/wallet' -import { isChainAllowed } from 'modules/wallet/web3-react/connection' - import { NEVER_RELOAD, useSingleCallResult } from 'lib/hooks/multicall' import useNativeCurrency from 'lib/hooks/useNativeCurrency' diff --git a/apps/cowswap-frontend/src/lib/hooks/useNativeCurrency.ts b/apps/cowswap-frontend/src/lib/hooks/useNativeCurrency.ts index 46ff26ac6b..2104ea7478 100644 --- a/apps/cowswap-frontend/src/lib/hooks/useNativeCurrency.ts +++ b/apps/cowswap-frontend/src/lib/hooks/useNativeCurrency.ts @@ -1,12 +1,10 @@ import { useMemo } from 'react' +import { nativeOnChain } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { NativeCurrency } from '@uniswap/sdk-core' -import { nativeOnChain } from 'legacy/constants/tokens' - -import { useWalletInfo } from 'modules/wallet' - export const MAINNET_NATIVE_CURRENCY = nativeOnChain(SupportedChainId.MAINNET) export default function useNativeCurrency(): NativeCurrency { diff --git a/apps/cowswap-frontend/src/lib/hooks/useTokenList/fetchTokenList.ts b/apps/cowswap-frontend/src/lib/hooks/useTokenList/fetchTokenList.ts index 6cf74d380e..e072b22b9d 100644 --- a/apps/cowswap-frontend/src/lib/hooks/useTokenList/fetchTokenList.ts +++ b/apps/cowswap-frontend/src/lib/hooks/useTokenList/fetchTokenList.ts @@ -1,9 +1,6 @@ +import { contenthashToUri, parseENSAddress, uriToHttp } from '@cowprotocol/common-utils' import type { TokenList } from '@uniswap/token-lists' -import contenthashToUri from 'lib/utils/contenthashToUri' -import parseENSAddress from 'lib/utils/parseENSAddress' -import uriToHttp from 'lib/utils/uriToHttp' - import validateTokenList from './validateTokenList' export const DEFAULT_TOKEN_LIST = 'https://gateway.ipfs.io/ipns/tokens.uniswap.org' diff --git a/apps/cowswap-frontend/src/lib/hooks/useTokenList/filtering.ts b/apps/cowswap-frontend/src/lib/hooks/useTokenList/filtering.ts index 67784b69d4..2770f83eca 100644 --- a/apps/cowswap-frontend/src/lib/hooks/useTokenList/filtering.ts +++ b/apps/cowswap-frontend/src/lib/hooks/useTokenList/filtering.ts @@ -1,8 +1,7 @@ +import { isAddress } from '@cowprotocol/common-utils' import { NativeCurrency, Token } from '@uniswap/sdk-core' import { TokenInfo } from '@uniswap/token-lists' -import { isAddress } from 'legacy/utils' - const alwaysTrue = () => true /** Creates a filter function that filters tokens that do not match the query. */ diff --git a/apps/cowswap-frontend/src/lib/i18n.tsx b/apps/cowswap-frontend/src/lib/i18n.tsx index 760217dbec..f56a09da5d 100644 --- a/apps/cowswap-frontend/src/lib/i18n.tsx +++ b/apps/cowswap-frontend/src/lib/i18n.tsx @@ -1,5 +1,7 @@ import { ReactNode, useEffect } from 'react' +import { DEFAULT_LOCALE, SupportedLocale } from '@cowprotocol/common-const' + import { i18n } from '@lingui/core' import { I18nProvider } from '@lingui/react' import { @@ -36,8 +38,6 @@ import { } from 'make-plural/plurals' import { PluralCategory } from 'make-plural/plurals' -import { DEFAULT_LOCALE, SupportedLocale } from 'legacy/constants/locales' - type LocalePlural = { [key in SupportedLocale]: (n: number | string, ord?: boolean) => PluralCategory } diff --git a/apps/cowswap-frontend/src/lib/state/multicall.tsx b/apps/cowswap-frontend/src/lib/state/multicall.tsx deleted file mode 100644 index aab5f6c2cf..0000000000 --- a/apps/cowswap-frontend/src/lib/state/multicall.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { createMulticall /*, ListenerOptions */ } from '@uniswap/redux-multicall' -import { useWeb3React } from '@web3-react/core' - -import { combineReducers, createStore } from 'redux' - -import { useInterfaceMulticall } from 'legacy/hooks/useContract' - -import useBlockNumber from 'lib/hooks/useBlockNumber' - -const multicall = createMulticall() -const reducer = combineReducers({ [multicall.reducerPath]: multicall.reducer }) -export const store = createStore(reducer) - -export default multicall - -export function MulticallUpdater() { - const { chainId } = useWeb3React() - const latestBlockNumber = useBlockNumber() - const contract = useInterfaceMulticall() - - return -} diff --git a/apps/cowswap-frontend/src/lib/utils/contenthashToUri.test.skip.ts b/apps/cowswap-frontend/src/lib/utils/contenthashToUri.test.skip.ts deleted file mode 100644 index 7a44dd1c64..0000000000 --- a/apps/cowswap-frontend/src/lib/utils/contenthashToUri.test.skip.ts +++ /dev/null @@ -1,21 +0,0 @@ -import contenthashToUri, { hexToUint8Array } from './contenthashToUri' - -// this test is skipped for now because importing CID results in -// TypeError: TextDecoder is not a constructor - -describe('#contenthashToUri', () => { - it('1inch.tokens.eth contenthash', () => { - expect(contenthashToUri('0xe3010170122013e051d1cfff20606de36845d4fe28deb9861a319a5bc8596fa4e610e8803918')).toEqual( - 'ipfs://QmPgEqyV3m8SB52BS2j2mJpu9zGprhj2BGCHtRiiw2fdM1' - ) - }) - it('uniswap.eth contenthash', () => { - expect(contenthashToUri('0xe5010170000f6170702e756e69737761702e6f7267')).toEqual('ipns://app.uniswap.org') - }) -}) - -describe('#hexToUint8Array', () => { - it('common case', () => { - expect(hexToUint8Array('0x010203fdfeff')).toEqual(new Uint8Array([1, 2, 3, 253, 254, 255])) - }) -}) diff --git a/apps/cowswap-frontend/src/mocks/orderMock.ts b/apps/cowswap-frontend/src/mocks/orderMock.ts index 7ad4b4b03a..cbea22a4b7 100644 --- a/apps/cowswap-frontend/src/mocks/orderMock.ts +++ b/apps/cowswap-frontend/src/mocks/orderMock.ts @@ -1,7 +1,7 @@ +import { COW, GNO } from '@cowprotocol/common-const' import { OrderClass, SupportedChainId } from '@cowprotocol/cow-sdk' import { OrderKind } from '@cowprotocol/cow-sdk' -import { COW, GNO } from 'legacy/constants/tokens' import { Order, OrderStatus } from 'legacy/state/orders/actions' export const getOrderMock = (chainId: SupportedChainId): Order => { diff --git a/apps/cowswap-frontend/src/mocks/tradeStateMock.ts b/apps/cowswap-frontend/src/mocks/tradeStateMock.ts index 68d4717173..55d6737961 100644 --- a/apps/cowswap-frontend/src/mocks/tradeStateMock.ts +++ b/apps/cowswap-frontend/src/mocks/tradeStateMock.ts @@ -1,9 +1,9 @@ +import { COW, GNO } from '@cowprotocol/common-const' import { OrderClass, OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount, Percent } from '@uniswap/sdk-core' -import { COW, GNO } from 'legacy/constants/tokens' import { PriceImpact } from 'legacy/hooks/usePriceImpact' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { getAppData } from 'modules/appData' import { TradeFlowContext } from 'modules/limitOrders/services/types' diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx index e1792c5d96..4246e40f43 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/SurplusCard.tsx @@ -1,18 +1,17 @@ +import { FiatAmount, TokenAmount } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' + import { transparentize } from 'polished' import styled from 'styled-components/macro' import QuestionHelper, { QuestionWrapper } from 'legacy/components/QuestionHelper' -import { ExternalLink } from 'legacy/theme' import { useUsdAmount } from 'modules/usdAmount' import { UI } from 'common/constants/theme' -import { FiatAmount } from 'common/pure/FiatAmount' -import { TokenAmount } from 'common/pure/TokenAmount' import { useTotalSurplus } from 'common/state/totalSurplusState' import useNativeCurrency from 'lib/hooks/useNativeCurrency' - import { InfoCard } from './styled' export function SurplusCard() { diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx index a50d70bf37..0c653be3b0 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/index.tsx @@ -1,35 +1,42 @@ import { Fragment, useMemo } from 'react' +import { + getEtherscanLink, + getExplorerLabel, + shortenAddress, + getExplorerAddressLink, + isMobile, +} from '@cowprotocol/common-utils' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { MouseoverTooltip } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' +import { + ConnectionType, + useWalletInfo, + WalletDetails, + getConnectionIcon, + getConnectionName, + getIsCoinbaseWallet, + getIsMetaMask, + Identicon, + useWalletDetails, + useIsWalletConnect, + getWeb3ReactConnection, + getIsHardWareWallet, +} from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { Connector } from '@web3-react/types' import { Trans } from '@lingui/macro' import Copy from 'legacy/components/Copy' -import { MouseoverTooltip } from 'legacy/components/Tooltip' import { ActivityDescriptors, groupActivitiesByDay, useMultipleActivityDescriptors, } from 'legacy/hooks/useRecentActivity' -import { ExternalLink } from 'legacy/theme' -import { getEtherscanLink, getExplorerLabel, shortenAddress } from 'legacy/utils' -import { getExplorerAddressLink } from 'legacy/utils/explorer' -import { isMobile } from 'legacy/utils/userAgent' import Activity from 'modules/account/containers/Transaction' -import { ConnectionType, useDisconnectWallet, useWalletInfo, WalletDetails } from 'modules/wallet' -import { Identicon } from 'modules/wallet/api/container/Identicon' -import { useWalletDetails } from 'modules/wallet/api/hooks' -import { useIsWalletConnect } from 'modules/wallet/web3-react/hooks/useIsWalletConnect' -import { - getConnectionIcon, - getConnectionName, - getIsCoinbaseWallet, - getIsMetaMask, -} from 'modules/wallet/api/utils/connection' -import { getIsHardWareWallet, getWeb3ReactConnection } from 'modules/wallet/web3-react/connection' import { UNSUPPORTED_WALLET_TEXT } from 'common/containers/WalletUnsupportedNetworkBanner' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' @@ -56,6 +63,7 @@ import { } from './styled' import { SurplusCard } from './SurplusCard' +import { useDisconnectWallet } from '../../hooks/useDisconnectWallet' import { CreationDateText } from '../Transaction/styled' export const NETWORK_LABELS: { [chainId in ChainId]?: string } = { @@ -194,9 +202,7 @@ export function AccountDetails({ )} - {(ENSName || account) && ( - - )} + {(ENSName || account) && } diff --git a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts index 158dee73d6..e39cce9603 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts +++ b/apps/cowswap-frontend/src/modules/account/containers/AccountDetails/styled.ts @@ -1,11 +1,12 @@ +import { ButtonSecondary } from '@cowprotocol/ui' +import { ExternalLink, StyledLink } from '@cowprotocol/ui' + import { transparentize } from 'polished' import styled from 'styled-components/macro' -import { ButtonSecondary } from 'legacy/components/Button' import { YellowCard } from 'legacy/components/Card' import { CopyIcon, TransactionStatusText } from 'legacy/components/Copy' import { QuestionWrapper } from 'legacy/components/QuestionHelper' -import { ExternalLink, StyledLink } from 'legacy/theme' import { UI } from 'common/constants/theme' @@ -594,8 +595,8 @@ export const WalletIconWrapper = styled.div` ` interface WalletSelectorProps { - isHardWareWallet?: boolean; - onClick?: () => void; + isHardWareWallet?: boolean + onClick?: () => void } export const WalletSelector = styled.div` @@ -608,7 +609,7 @@ export const WalletSelector = styled.div` ${({ isHardWareWallet }) => isHardWareWallet && ` - cursor: pointer; + cursor: pointer; border: 1px solid var(${UI.COLOR_TEXT1_OPACITY_25}); background: transparent; padding: 6px 10px; diff --git a/apps/cowswap-frontend/src/modules/account/containers/CopyHelper/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/CopyHelper/index.tsx index ab432809d0..7b3526ef7a 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/CopyHelper/index.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/CopyHelper/index.tsx @@ -1,10 +1,11 @@ import React, { useCallback } from 'react' +import { useCopyClipboard } from '@cowprotocol/common-hooks' + import { Trans } from '@lingui/macro' import { CheckCircle, Copy } from 'react-feather' import styled from 'styled-components/macro' -import useCopyClipboard from 'legacy/hooks/useCopyClipboard' import { LinkStyledButton } from 'legacy/theme' const CopyIcon = styled(LinkStyledButton)` diff --git a/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx index c16a7c4b6c..2b8d9012b8 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/OrdersPanel/index.tsx @@ -1,12 +1,14 @@ import { useSetAtom } from 'jotai' +import { ReactComponent as Close } from '@cowprotocol/assets/images/x.svg' +import { useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' + import { transparentize } from 'polished' import styled from 'styled-components/macro' -import { ReactComponent as Close } from 'legacy/assets/images/x.svg' import { useToggleWalletModal } from 'legacy/state/application/hooks' -import { toggleAccountSelectorModalAtom, useWalletDetails, useWalletInfo } from 'modules/wallet' +import { toggleAccountSelectorModalAtom } from 'modules/wallet/containers/AccountSelectorModal/state' import { UI } from 'common/constants/theme' import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity' diff --git a/apps/cowswap-frontend/src/modules/account/containers/SimpleAccountDetails/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/SimpleAccountDetails/index.tsx index f846963f44..5432607944 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/SimpleAccountDetails/index.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/SimpleAccountDetails/index.tsx @@ -1,11 +1,11 @@ import { Fragment } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' + import styled from 'styled-components/macro' import { useMultipleActivityDescriptors, groupActivitiesByDay } from 'legacy/hooks/useRecentActivity' -import { useWalletInfo } from 'modules/wallet' - import { renderActivities } from '../AccountDetails' import { AccountDetailsProps } from '../AccountDetails' import { LowerSectionSimple, Wrapper } from '../AccountDetails/styled' diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx b/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx index fa0bec7d4c..8bcdc9fa56 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx @@ -1,10 +1,10 @@ import { ReactNode } from 'react' +import { V_COW_CONTRACT_ADDRESS, V_COW, COW } from '@cowprotocol/common-const' +import { TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount } from '@uniswap/sdk-core' import { OrderProgressBar } from 'legacy/components/OrderProgressBar' -import { V_COW_CONTRACT_ADDRESS } from 'legacy/constants' -import { V_COW, COW } from 'legacy/constants/tokens' import { useToken } from 'legacy/hooks/Tokens' import { getActivityState } from 'legacy/hooks/useActivityDerivedState' import { ActivityStatus } from 'legacy/hooks/useRecentActivity' @@ -17,7 +17,6 @@ import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue' import { CurrencyLogo } from 'common/pure/CurrencyLogo' import { RateInfoParams, RateInfo } from 'common/pure/RateInfo' import { SafeWalletLink } from 'common/pure/SafeWalletLink' -import { TokenAmount } from 'common/pure/TokenAmount' import { StatusDetails } from './StatusDetails' import { diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/StatusDetails.tsx b/apps/cowswap-frontend/src/modules/account/containers/Transaction/StatusDetails.tsx index 4cf611e58e..b951179bac 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/StatusDetails.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/StatusDetails.tsx @@ -1,15 +1,16 @@ +import OrderCancelledImage from '@cowprotocol/assets/cow-swap/order-cancelled.svg' +import OrderCheckImage from '@cowprotocol/assets/cow-swap/order-check.svg' +import OrderExpiredImage from '@cowprotocol/assets/cow-swap/order-expired.svg' +import OrderOpenImage from '@cowprotocol/assets/cow-swap/order-open.svg' +import PresignaturePendingImage from '@cowprotocol/assets/cow-swap/order-presignature-pending.svg' +import { ExplorerDataType, getExplorerLink } from '@cowprotocol/common-utils' +import { getSafeWebUrl } from '@cowprotocol/core' + import { ExternalLink as LinkIconFeather } from 'react-feather' import SVG from 'react-inlinesvg' -import OrderCancelledImage from 'legacy/assets/cow-swap/order-cancelled.svg' -import OrderCheckImage from 'legacy/assets/cow-swap/order-check.svg' -import OrderExpiredImage from 'legacy/assets/cow-swap/order-expired.svg' -import OrderOpenImage from 'legacy/assets/cow-swap/order-open.svg' -import PresignaturePendingImage from 'legacy/assets/cow-swap/order-presignature-pending.svg' import { getActivityState } from 'legacy/hooks/useActivityDerivedState' -import { ExplorerDataType, getExplorerLink } from 'legacy/utils/getExplorerLink' -import { getSafeWebUrl } from 'api/gnosisSafe' import { CancelButton } from 'common/pure/CancelButton' import { isOrderCancellable } from 'common/utils/isOrderCancellable' diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/index.tsx b/apps/cowswap-frontend/src/modules/account/containers/Transaction/index.tsx index b51b2d36d5..728e9f0c64 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/index.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/index.tsx @@ -1,13 +1,12 @@ +import { RowFixed } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { SafeInfoResponse } from '@safe-global/api-kit' -import { RowFixed } from 'legacy/components/Row' import { useActivityDerivedState } from 'legacy/hooks/useActivityDerivedState' import { ActivityDescriptors, ActivityStatus, ActivityType } from 'legacy/hooks/useRecentActivity' import { EnhancedTransactionDetails } from 'legacy/state/enhancedTransactions/reducer' import { Order } from 'legacy/state/orders/actions' -import { useWalletInfo } from 'modules/wallet' - import { ActivityDetails } from './ActivityDetails' import { TransactionStatusText as ActivityDetailsText, TransactionWrapper, Wrapper } from './styled' diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts b/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts index 71f4752e66..631eb8876d 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts +++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts @@ -1,13 +1,13 @@ +import { StyledSVG, FiatAmount, RowFixed } from '@cowprotocol/ui' +import { ExternalLink, StyledLink } from '@cowprotocol/ui' + import { transparentize } from 'polished' import styled, { css, keyframes } from 'styled-components/macro' -import { StyledSVG } from 'legacy/components/Loader' -import { RowFixed } from 'legacy/components/Row' -import { ExternalLink, LinkStyledButton, StyledLink } from 'legacy/theme' +import { LinkStyledButton } from 'legacy/theme' import { UI } from 'common/constants/theme' import { StyledLogo } from 'common/pure/CurrencyLogo' -import { FiatAmount } from 'common/pure/FiatAmount' import { RateWrapper } from 'common/pure/RateInfo' export const TransactionWrapper = styled.div` diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useDisconnectWallet.ts b/apps/cowswap-frontend/src/modules/account/hooks/useDisconnectWallet.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useDisconnectWallet.ts rename to apps/cowswap-frontend/src/modules/account/hooks/useDisconnectWallet.ts diff --git a/apps/cowswap-frontend/src/modules/account/pure/ConnectedAccountBlocked/index.tsx b/apps/cowswap-frontend/src/modules/account/pure/ConnectedAccountBlocked/index.tsx index 56ddce4e84..e51246ab8c 100644 --- a/apps/cowswap-frontend/src/modules/account/pure/ConnectedAccountBlocked/index.tsx +++ b/apps/cowswap-frontend/src/modules/account/pure/ConnectedAccountBlocked/index.tsx @@ -1,10 +1,12 @@ +import { useTheme } from '@cowprotocol/common-hooks' +import { ExternalLink } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { AlertOctagon } from 'react-feather' import styled from 'styled-components/macro' import Column from 'legacy/components/Column' -import useTheme from 'legacy/hooks/useTheme' -import { ExternalLink, ThemedText } from 'legacy/theme' +import { ThemedText } from 'legacy/theme' import { CopyHelper } from 'modules/account/containers/CopyHelper' diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/containers/AdvancedOrdersWidget/index.tsx b/apps/cowswap-frontend/src/modules/advancedOrders/containers/AdvancedOrdersWidget/index.tsx index 3eacbd0b76..e2f1e20f9e 100644 --- a/apps/cowswap-frontend/src/modules/advancedOrders/containers/AdvancedOrdersWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/advancedOrders/containers/AdvancedOrdersWidget/index.tsx @@ -3,7 +3,7 @@ import { PropsWithChildren, ReactNode } from 'react' import { OrderKind } from '@cowprotocol/cow-sdk' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { useAdvancedOrdersActions } from 'modules/advancedOrders/hooks/useAdvancedOrdersActions' import { useAdvancedOrdersDerivedState } from 'modules/advancedOrders/hooks/useAdvancedOrdersDerivedState' diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersActions.ts b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersActions.ts index 871cb922e5..9df7020b55 100644 --- a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersActions.ts +++ b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersActions.ts @@ -1,10 +1,10 @@ import { useSetAtom } from 'jotai' import { useCallback } from 'react' +import { changeSwapAmountAnalytics } from '@cowprotocol/analytics' import { Currency } from '@uniswap/sdk-core' -import { changeSwapAmountAnalytics } from 'legacy/components/analytics' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { useNavigateOnCurrencySelection } from 'modules/trade/hooks/useNavigateOnCurrencySelection' import { useSwitchTokensPlaces } from 'modules/trade/hooks/useSwitchTokensPlaces' diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useComposableCowContract.ts b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useComposableCowContract.ts index e4ad17f9fc..3d85e43969 100644 --- a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useComposableCowContract.ts +++ b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useComposableCowContract.ts @@ -1,8 +1,6 @@ -import { ComposableCoW, ComposableCoWAbi } from '@cowswap/abis' - -import { useContract } from 'legacy/hooks/useContract' - -import { useWalletInfo } from 'modules/wallet' +import { ComposableCoW, ComposableCoWAbi } from '@cowprotocol/abis' +import { useContract } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' import { COMPOSABLE_COW_ADDRESS } from '../const' diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersAtom.ts b/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersAtom.ts index 854f1c0153..b0244edc12 100644 --- a/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersAtom.ts +++ b/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersAtom.ts @@ -1,10 +1,9 @@ import { atom } from 'jotai' import { atomWithStorage } from 'jotai/utils' +import { getJotaiIsolatedStorage } from '@cowprotocol/core' import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' -import { getJotaiIsolatedStorage } from 'jotaiStore' - import { DEFAULT_TRADE_DERIVED_STATE, TradeDerivedState } from 'modules/trade/types/TradeDerivedState' import { ExtendedTradeRawState, getDefaultTradeRawState } from 'modules/trade/types/TradeRawState' diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersSettingsAtom.ts b/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersSettingsAtom.ts index afe566f91d..5d6e2626c5 100644 --- a/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersSettingsAtom.ts +++ b/apps/cowswap-frontend/src/modules/advancedOrders/state/advancedOrdersSettingsAtom.ts @@ -1,7 +1,7 @@ import { atom } from 'jotai' import { atomWithStorage } from 'jotai/utils' -import { getJotaiIsolatedStorage } from 'jotaiStore' +import { getJotaiIsolatedStorage } from '@cowprotocol/core' export interface AdvancedOrdersSettingsState { readonly showRecipient: boolean diff --git a/apps/cowswap-frontend/src/modules/appData/hooks.ts b/apps/cowswap-frontend/src/modules/appData/hooks.ts index 582b89c498..389cca11d7 100644 --- a/apps/cowswap-frontend/src/modules/appData/hooks.ts +++ b/apps/cowswap-frontend/src/modules/appData/hooks.ts @@ -1,11 +1,9 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useMemo } from 'react' -import { DEFAULT_APP_CODE, SAFE_APP_CODE } from 'legacy/constants' - -import { useIsSafeApp } from 'modules/wallet' - -import { isInjectedWidget } from 'common/utils/isInjectedWidget' +import { DEFAULT_APP_CODE, SAFE_APP_CODE } from '@cowprotocol/common-const' +import { isInjectedWidget } from '@cowprotocol/common-utils' +import { useIsSafeApp } from '@cowprotocol/wallet' import { addAppDataToUploadQueueAtom, appDataHooksAtom, appDataInfoAtom } from './state/atoms' import { AppDataInfo } from './types' diff --git a/apps/cowswap-frontend/src/modules/appData/updater/AppDataUpdater.tsx b/apps/cowswap-frontend/src/modules/appData/updater/AppDataUpdater.tsx index 79a38d70b4..481b8b96ae 100644 --- a/apps/cowswap-frontend/src/modules/appData/updater/AppDataUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/appData/updater/AppDataUpdater.tsx @@ -1,11 +1,10 @@ import React from 'react' +import { percentToBips } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { Percent } from '@uniswap/sdk-core' -import { percentToBips } from 'legacy/utils/misc' - import { useUtm } from 'modules/utm' -import { useWalletInfo } from 'modules/wallet' import { AppDataHooksUpdater } from './AppDataHooksUpdater' import { AppDataInfoUpdater, UseAppDataParams } from './AppDataInfoUpdater' diff --git a/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts b/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts index ef6bf94536..0239246bd0 100644 --- a/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts +++ b/apps/cowswap-frontend/src/modules/appData/utils/buildAppData.ts @@ -1,11 +1,10 @@ import { stringifyDeterministic } from '@cowprotocol/app-data' +import { environmentName } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { metadataApiSDK } from 'cowSdk' import { keccak256, toUtf8Bytes } from 'ethers/lib/utils' -import { environmentName } from 'legacy/utils/environments' - import { UtmParams } from 'modules/utm' import { AppDataHooks, AppDataInfo, AppDataOrderClass, AppDataRootSchema } from '../types' diff --git a/apps/cowswap-frontend/src/modules/appData/utils/fullAppData.ts b/apps/cowswap-frontend/src/modules/appData/utils/fullAppData.ts index eb801f6436..08cdc6fac3 100644 --- a/apps/cowswap-frontend/src/modules/appData/utils/fullAppData.ts +++ b/apps/cowswap-frontend/src/modules/appData/utils/fullAppData.ts @@ -1,4 +1,4 @@ -import { environmentName } from 'legacy/utils/environments' +import { environmentName } from '@cowprotocol/common-utils' import { AppDataInfo } from '../types' import { toKeccak256 } from '../utils/buildAppData' diff --git a/apps/cowswap-frontend/src/modules/application/containers/App/RoutesApp.tsx b/apps/cowswap-frontend/src/modules/application/containers/App/RoutesApp.tsx index 6e83f67b24..588f1828d7 100644 --- a/apps/cowswap-frontend/src/modules/application/containers/App/RoutesApp.tsx +++ b/apps/cowswap-frontend/src/modules/application/containers/App/RoutesApp.tsx @@ -1,10 +1,11 @@ import { lazy, ReactNode, Suspense } from 'react' +import { DISCORD_LINK, DOCS_LINK, DUNE_DASHBOARD_LINK, TWITTER_LINK } from '@cowprotocol/common-const' +import { Loader } from '@cowprotocol/ui' + import { Navigate, Route, Routes } from 'react-router-dom' import { Loading } from 'legacy/components/FlashingLoading' -import Loader from 'legacy/components/Loader' -import { DISCORD_LINK, DOCS_LINK, DUNE_DASHBOARD_LINK, TWITTER_LINK } from 'legacy/constants' import { RedirectPathToSwapOnly, RedirectToPath } from 'legacy/pages/Swap/redirects' import { Routes as RoutesEnum, RoutesValues } from 'common/constants/routes' @@ -35,9 +36,6 @@ const EthFlowFaq = lazy(() => import(/* webpackChunkName: "eth_flow_faq" */ 'pag const AccountTokensOverview = lazy(() => import(/* webpackChunkName: "tokens_overview" */ 'pages/Account/Tokens')) const AccountNotFound = lazy(() => import(/* webpackChunkName: "affiliate" */ 'pages/error/NotFound')) -// Misc -const KitchenSink = lazy(() => import(/* webpackChunkName: "kitchen_sink" */ 'pages/KitchenSink')) - function createRedirectExternal(url: string) { return () => { window.location.replace(url) @@ -68,7 +66,6 @@ const lazyRoutes: LazyRouteProps[] = [ { route: RoutesEnum.PRIVACY_POLICY, element: }, { route: RoutesEnum.COOKIE_POLICY, element: }, { route: RoutesEnum.TERMS_CONDITIONS, element: }, - { route: RoutesEnum.KITCHEN_SINK, element: }, ] export function RoutesApp() { diff --git a/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx b/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx index 306481a0c5..557ee7d30d 100644 --- a/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx +++ b/apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx @@ -1,31 +1,34 @@ -import ApplicationUpdater from 'legacy/state/application/updater' -import EnhancedTransactionUpdater from 'legacy/state/enhancedTransactions/updater' +import { WalletUpdater } from '@cowprotocol/wallet' + import { GasPriceStrategyUpdater } from 'legacy/state/gas/gas-price-strategy-updater' -import GasUpdater from 'legacy/state/gas/updater' -import ListsUpdater from 'legacy/state/lists/updater' -import LogsUpdater from 'legacy/state/logs/updater' -import { - CancelledOrdersUpdater, - ExpiredOrdersUpdater, - GpOrdersUpdater, - PendingOrdersUpdater, - UnfillableOrdersUpdater, -} from 'legacy/state/orders/updaters' -import { SpotPricesUpdater } from 'legacy/state/orders/updaters/SpotPricesUpdater' -import FeesUpdater from 'legacy/state/price/updater' -import SentryUpdater from 'legacy/state/sentry/updater' -import UserUpdater from 'legacy/state/user/updater' +import { MulticallUpdater } from 'legacy/state/multicall' import { UploadToIpfsUpdater } from 'modules/appData/updater/UploadToIpfsUpdater' import { InjectedWidgetUpdater } from 'modules/injectedWidget' import { EthFlowDeadlineUpdater, EthFlowSlippageUpdater } from 'modules/swap/state/EthFlow/updaters' import { TokensListUpdater } from 'modules/tokensList/updaters/TokensListUpdater' import { UsdPricesUpdater } from 'modules/usdAmount' -import { WalletUpdater, HwAccountIndexUpdater } from 'modules/wallet' import { TotalSurplusUpdater } from 'common/state/totalSurplusState' +import { ApplicationUpdater } from 'common/updaters/ApplicationUpdater' +import { CancelReplaceTxUpdater } from 'common/updaters/CancelReplaceTxUpdater' +import { FeesUpdater } from 'common/updaters/FeesUpdater' +import { FinalizeTxUpdater } from 'common/updaters/FinalizeTxUpdater' +import { GasUpdater } from 'common/updaters/GasUpdater' +import { HwAccountIndexUpdater } from 'common/updaters/HwAccountIndexUpdater' +import { ListsUpdater } from 'common/updaters/ListsUpdater' +import { LogsUpdater } from 'common/updaters/LogsUpdater' +import { + CancelledOrdersUpdater, + ExpiredOrdersUpdater, + GpOrdersUpdater, + PendingOrdersUpdater, + UnfillableOrdersUpdater, +} from 'common/updaters/orders' +import { SpotPricesUpdater } from 'common/updaters/orders/SpotPricesUpdater' +import { SentryUpdater } from 'common/updaters/SentryUpdater' import { ThemeFromUrlUpdater } from 'common/updaters/ThemeFromUrlUpdater' -import { MulticallUpdater } from 'lib/state/multicall' +import { UserUpdater } from 'common/updaters/UserUpdater' export function Updaters() { return ( @@ -36,7 +39,8 @@ export function Updaters() { - + + diff --git a/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx b/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx index cd5f7727d4..757a14fce6 100644 --- a/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx +++ b/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx @@ -1,21 +1,22 @@ +import { isInjectedWidget } from '@cowprotocol/common-utils' + import { initializeAnalytics } from 'legacy/components/AmplitudeAnalytics' -import { useAnalyticsReporter } from 'legacy/components/analytics' import ErrorBoundary from 'legacy/components/ErrorBoundary' import Footer from 'legacy/components/Footer' import Header from 'legacy/components/Header' import URLWarning from 'legacy/components/Header/URLWarning' import TopLevelModals from 'legacy/components/TopLevelModals' -import ApeModeQueryParamReader from 'legacy/hooks/useApeModeQueryParamReader' import DarkModeQueryParamReader from 'legacy/theme' import { useInitializeUtm } from 'modules/utm' -import { isInjectedWidget } from 'common/utils/isInjectedWidget' import RedirectAnySwapAffectedUsers from 'pages/error/AnySwapAffectedUsers/RedirectAnySwapAffectedUsers' import { RoutesApp } from './RoutesApp' import * as styledEl from './styled' +import { useAnalyticsReporter } from '../../../../common/hooks/useAnalyticsReporter' + export function App() { initializeAnalytics() useAnalyticsReporter() @@ -27,7 +28,6 @@ export function App() { - diff --git a/apps/cowswap-frontend/src/modules/application/containers/PageTitle/index.tsx b/apps/cowswap-frontend/src/modules/application/containers/PageTitle/index.tsx index 1ede20b483..05a566bf39 100644 --- a/apps/cowswap-frontend/src/modules/application/containers/PageTitle/index.tsx +++ b/apps/cowswap-frontend/src/modules/application/containers/PageTitle/index.tsx @@ -1,6 +1,6 @@ -import { Helmet } from 'react-helmet' +import { APP_TITLE } from '@cowprotocol/common-const' -import { APP_TITLE } from 'legacy/constants' +import { Helmet } from 'react-helmet' type PageTitleProps = { title?: string diff --git a/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx b/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx index 4b86b52fff..2ec8e3ab9f 100644 --- a/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx @@ -2,17 +2,19 @@ import { useAtom, useAtomValue } from 'jotai' import { useSetAtom } from 'jotai' import { useCallback, useMemo, useRef, useState } from 'react' +import { openFortuneCookieAnalytics, shareFortuneTwitterAnalytics } from '@cowprotocol/analytics' +import fortuneCookieImage from '@cowprotocol/assets/cow-swap/fortune-cookie.png' +import twitterImage from '@cowprotocol/assets/cow-swap/twitter.svg' +import { useInterval } from '@cowprotocol/common-hooks' +import { addBodyClass, removeBodyClass } from '@cowprotocol/common-utils' +import { ExternalLink } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { X } from 'react-feather' import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import fortuneCookieImage from 'legacy/assets/cow-swap/fortune-cookie.png' -import twitterImage from 'legacy/assets/cow-swap/twitter.svg' -import { openFortuneCookieAnalytics, shareFortuneTwitterAnalytics } from 'legacy/components/analytics/events/cowFortune' import Confetti from 'legacy/components/Confetti' -import { ExternalLink } from 'legacy/theme' -import { addBodyClass, removeBodyClass } from 'legacy/utils/toggleBodyClass' import { useOpenRandomFortune } from 'modules/fortune/hooks/useOpenRandomFortune' import { lastCheckedFortuneAtom } from 'modules/fortune/state/checkedFortunesListAtom' @@ -23,7 +25,6 @@ import { } from 'modules/fortune/state/fortuneStateAtom' import { UI } from 'common/constants/theme' -import useInterval from 'lib/hooks/useInterval' import { SuccessBanner } from 'pages/Claim/styled' const FortuneButton = styled.div<{ isDailyFortuneChecked: boolean }>` diff --git a/apps/cowswap-frontend/src/modules/fortune/hooks/useOpenRandomFortune.ts b/apps/cowswap-frontend/src/modules/fortune/hooks/useOpenRandomFortune.ts index a1ef978284..aa60fabcc1 100644 --- a/apps/cowswap-frontend/src/modules/fortune/hooks/useOpenRandomFortune.ts +++ b/apps/cowswap-frontend/src/modules/fortune/hooks/useOpenRandomFortune.ts @@ -2,13 +2,13 @@ import { useAtom, useAtomValue } from 'jotai' import { useSetAtom } from 'jotai' import { useCallback } from 'react' +import { getRandomInt } from '@cowprotocol/common-utils' + import { CheckedFortunesList, checkedFortunesListAtom } from 'modules/fortune/state/checkedFortunesListAtom' import { fortunesListAtom } from 'modules/fortune/state/fortunesListAtom' import { updateOpenFortuneAtom } from 'modules/fortune/state/fortuneStateAtom' import { FortuneItem } from 'modules/fortune/types' -import { getRandomInt } from 'utils/getRandomInt' - function getRandomFortuneFromList(items: FortuneItem[], checkedFortunes: CheckedFortunesList): FortuneItem | null { const list = items.filter((item) => !checkedFortunes[item.id]) const index = getRandomInt(0, list.length - 1) diff --git a/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts b/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts index 8f4003c8cc..e19fa38250 100644 --- a/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts +++ b/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts @@ -1,7 +1,7 @@ import { atom } from 'jotai' import { loadable } from 'jotai/utils' -import { RAW_CODE_LINK } from 'legacy/constants' +import { RAW_CODE_LINK } from '@cowprotocol/common-const' import { FortuneItem } from 'modules/fortune/types' diff --git a/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts b/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts index 51572471e2..54c63dd2a7 100644 --- a/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts +++ b/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts @@ -1,9 +1,9 @@ import { useSetAtom } from 'jotai' import { useCallback, useEffect, useRef } from 'react' -import { useNavigate } from 'react-router-dom' +import { deepEqual } from '@cowprotocol/common-utils' -import { deepEqual } from 'utils/deepEqual' +import { useNavigate } from 'react-router-dom' import { injectedWidgetMetaDataAtom } from '../state/injectedWidgetMetaDataAtom' import { injectedWidgetParamsAtom } from '../state/injectedWidgetParamsAtom' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx index 96ca662ee9..7c8fa13f95 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersConfirmModal/index.tsx @@ -1,6 +1,8 @@ import { useAtom, useAtomValue } from 'jotai' import React from 'react' +import { TokenSymbol } from '@cowprotocol/ui' + import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { LimitOrdersWarnings } from 'modules/limitOrders/containers/LimitOrdersWarnings' @@ -16,7 +18,6 @@ import { TradeConfirmation, TradeConfirmModal, useTradeConfirmActions } from 'mo import { useRateInfoParams } from 'common/hooks/useRateInfoParams' import { CurrencyPreviewInfo } from 'common/pure/CurrencyAmountPreview' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { LOW_RATE_THRESHOLD_PERCENT } from '../../const/trade' import { LimitOrdersDetails } from '../../pure/LimitOrdersDetails' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx index 865d955012..1b3494b41c 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx @@ -2,6 +2,8 @@ import { useSetAtom } from 'jotai' import { useAtomValue } from 'jotai' import React, { useCallback, useEffect } from 'react' +import { isFractionFalsy } from '@cowprotocol/common-utils' +import { useIsSafeViaWc, useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import styled from 'styled-components/macro' @@ -19,7 +21,6 @@ import { useTradePriceImpact } from 'modules/trade' import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning' import { TradeFormValidation, useGetTradeFormValidation } from 'modules/tradeFormValidation' import { useTradeQuote } from 'modules/tradeQuote' -import { useIsSafeViaWc, useWalletInfo } from 'modules/wallet' import { HIGH_FEE_WARNING_PERCENTAGE } from 'common/constants/common' import { useShouldZeroApprove } from 'common/hooks/useShouldZeroApprove' @@ -29,7 +30,6 @@ import { SmallVolumeWarningBanner, } from 'common/pure/InlineBanner/banners' import { ZeroApprovalWarning } from 'common/pure/ZeroApprovalWarning' -import { isFractionFalsy } from 'utils/isFractionFalsy' import { calculatePercentageInRelationToReference } from 'utils/orderUtils/calculatePercentageInRelationToReference' import { RateImpactWarning } from '../../pure/RateImpactWarning' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/hooks/useLimitOrdersWidgetActions.ts b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/hooks/useLimitOrdersWidgetActions.ts index 80537087d3..2eb10dca7c 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/hooks/useLimitOrdersWidgetActions.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/hooks/useLimitOrdersWidgetActions.ts @@ -1,10 +1,11 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useCallback } from 'react' +import { changeSwapAmountAnalytics } from '@cowprotocol/analytics' +import { tryParseCurrencyAmount } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/cow-sdk' -import { changeSwapAmountAnalytics } from 'legacy/components/analytics' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { updateLimitOrdersRawStateAtom } from 'modules/limitOrders' import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOrdersDerivedState' @@ -15,8 +16,6 @@ import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap' import { useOnCurrencySelection } from 'modules/trade/hooks/useOnCurrencySelection' import { useSwitchTokensPlaces } from 'modules/trade/hooks/useSwitchTokensPlaces' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' - export function useLimitOrdersWidgetActions(): TradeWidgetActions { const { inputCurrency, outputCurrency, orderKind } = useLimitOrdersDerivedState() const { activeRate } = useAtomValue(limitRateAtom) diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx index f6443a6725..a416b9bbb4 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx @@ -3,7 +3,7 @@ import React, { useMemo } from 'react' import { OrderKind } from '@cowprotocol/cow-sdk' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { LimitOrdersWarnings } from 'modules/limitOrders/containers/LimitOrdersWarnings' import { useLimitOrdersWidgetActions } from 'modules/limitOrders/containers/LimitOrdersWidget/hooks/useLimitOrdersWidgetActions' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts index 1aedd73326..c35fd1d766 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/limitOrdersPropsChecker.ts @@ -1,3 +1,4 @@ +import { areFractionsEqual, genericPropsChecker, getAddress } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { PriceImpact } from 'legacy/hooks/usePriceImpact' @@ -10,9 +11,6 @@ import { TradeFormValidation } from 'modules/tradeFormValidation' import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types' import { RateInfoParams } from 'common/pure/RateInfo' -import { areFractionsEqual } from 'utils/areFractionsEqual' -import { genericPropsChecker } from 'utils/genericPropsChecker' -import { getAddress } from 'utils/getAddress' import { LimitOrdersFormState } from '../../hooks/useLimitOrdersFormState' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/index.tsx index a89744eeea..f7cd7ede74 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/index.tsx @@ -1,9 +1,12 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useCallback, useEffect, useMemo, useState } from 'react' +import { formatInputAmount, getAddress, isFractionFalsy } from '@cowprotocol/common-utils' +import { TokenSymbol, Loader } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' + import { RefreshCw } from 'react-feather' -import Loader from 'legacy/components/Loader' import QuestionHelper from 'legacy/components/QuestionHelper' import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOrdersDerivedState' @@ -14,15 +17,10 @@ import { HeadingText } from 'modules/limitOrders/pure/RateInput/HeadingText' import { executionPriceAtom } from 'modules/limitOrders/state/executionPriceAtom' import { limitRateAtom, updateLimitRateAtom } from 'modules/limitOrders/state/limitRateAtom' import { toFraction } from 'modules/limitOrders/utils/toFraction' -import { useWalletInfo } from 'modules/wallet' import { ordersTableFeatures } from 'common/constants/featureFlags' import { ExecutionPrice } from 'common/pure/ExecutionPrice' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { getQuoteCurrency, getQuoteCurrencyByStableCoin } from 'common/services/getQuoteCurrency' -import { formatInputAmount } from 'utils/amountFormat' -import { getAddress } from 'utils/getAddress' -import { isFractionFalsy } from 'utils/isFractionFalsy' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts b/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts index 866f62721d..41610c6005 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/RateInput/styled.ts @@ -1,7 +1,8 @@ +import { Loader } from '@cowprotocol/ui' + import { transparentize } from 'polished' import styled from 'styled-components/macro' -import Loader from 'legacy/components/Loader' import Input from 'legacy/components/NumericalInput' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts index 54809b697a..cee5622916 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useGetInitialPrice.ts @@ -1,19 +1,18 @@ import { useEffect, useState } from 'react' +import { useIsWindowVisible } from '@cowprotocol/common-hooks' +import { getAddress } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, Fraction } from '@uniswap/sdk-core' import * as Sentry from '@sentry/browser' import ms from 'ms.macro' import { useAsyncMemo } from 'use-async-memo' -import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible' - import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOrdersDerivedState' import { parsePrice } from 'modules/limitOrders/utils/parsePrice' -import { useWalletInfo } from 'modules/wallet' import { getNativePrice } from 'api/gnosisProtocol' -import { getAddress } from 'utils/getAddress' type PriceResult = number | Error | undefined diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts index 452b9da788..bb909d67ce 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.test.ts @@ -1,5 +1,7 @@ import { useAtomValue, useSetAtom } from 'jotai' +import { useIsBundlingSupported } from '@cowprotocol/wallet' + import { renderHook } from '@testing-library/react-hooks' import { PriceImpact } from 'legacy/hooks/usePriceImpact' @@ -8,7 +10,6 @@ import { useSafeBundleFlowContext } from 'modules/limitOrders/hooks/useSafeBundl import { safeBundleFlow } from 'modules/limitOrders/services/safeBundleFlow' import { tradeFlow } from 'modules/limitOrders/services/tradeFlow' import { TradeFlowContext } from 'modules/limitOrders/services/types' -import { useIsBundlingSupported } from 'modules/wallet' import { useNeedsApproval } from 'common/hooks/useNeedsApproval' import { TradeAmounts } from 'common/types' @@ -25,8 +26,8 @@ jest.mock('modules/limitOrders/services/safeBundleFlow') jest.mock('modules/limitOrders/hooks/useSafeBundleFlowContext') jest.mock('common/hooks/useNeedsApproval') -jest.mock('modules/wallet', () => { - const actual = jest.requireActual('modules/wallet') +jest.mock('@cowprotocol/wallet', () => { + const actual = jest.requireActual('@cowprotocol/wallet') return new Proxy(actual, { get: (target, property) => { @@ -41,7 +42,7 @@ jest.mock('modules/wallet', () => { }, }) }) -jest.mock('legacy/components/analytics/hooks/useAnalyticsReporter.ts') +jest.mock('common/hooks/useAnalyticsReporter') const mockTradeFlow = tradeFlow as jest.MockedFunction const mockSafeBundleFlow = safeBundleFlow as jest.MockedFunction diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts index 7855d436f6..fd92f776ac 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useIsSafeApprovalBundle.ts @@ -1,9 +1,8 @@ +import { useIsBundlingSupported } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { useIsBundlingSupported } from 'modules/wallet' - import { useNeedsApproval } from 'common/hooks/useNeedsApproval' export function useIsSafeApprovalBundle(amount: Nullish>): boolean { diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersFormState.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersFormState.ts index ee996f4d13..0343726766 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersFormState.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersFormState.ts @@ -1,12 +1,12 @@ import { useAtomValue } from 'jotai' +import { isFractionFalsy } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Fraction } from '@uniswap/sdk-core' import { limitRateAtom } from 'modules/limitOrders/state/limitRateAtom' import { useTradeQuote } from 'modules/tradeQuote' import { useSafeMemo } from 'common/hooks/useSafeMemo' -import { isFractionFalsy } from 'utils/isFractionFalsy' import { useLimitOrdersDerivedState } from './useLimitOrdersDerivedState' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSafeBundleFlowContext.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSafeBundleFlowContext.ts index 1d33afccf9..dcdf51a474 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSafeBundleFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSafeBundleFlowContext.ts @@ -1,7 +1,7 @@ -import { useTokenContract } from 'legacy/hooks/useContract' +import { useTokenContract } from '@cowprotocol/common-hooks' +import { useSafeAppsSdk } from '@cowprotocol/wallet' import { SafeBundleFlowContext, TradeFlowContext } from 'modules/limitOrders/services/types' -import { useSafeAppsSdk } from 'modules/wallet/web3-react/hooks/useSafeAppsSdk' import { useTradeSpenderAddress } from 'common/hooks/useTradeSpenderAddress' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSetupLimitOrderAmountsFromUrl.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSetupLimitOrderAmountsFromUrl.ts index 90cd978d61..a94c20fb14 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSetupLimitOrderAmountsFromUrl.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useSetupLimitOrderAmountsFromUrl.ts @@ -1,6 +1,9 @@ import { useSetAtom } from 'jotai' import { useCallback, useLayoutEffect, useMemo } from 'react' +import { tryParseCurrencyAmount } from '@cowprotocol/common-utils' +import { FractionUtils } from '@cowprotocol/common-utils' +import { getIntOrFloat } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/cow-sdk' import { Price } from '@uniswap/sdk-core' @@ -12,10 +15,6 @@ import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOr import { useUpdateActiveRate } from 'modules/limitOrders/hooks/useUpdateActiveRate' import { TRADE_URL_BUY_AMOUNT_KEY, TRADE_URL_SELL_AMOUNT_KEY } from 'modules/trade/const/tradeUrl' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' -import { FractionUtils } from 'utils/fractionUtils' -import { getIntOrFloat } from 'utils/getIntOrFloat' - /** * Parse sell/buy amount from URL and apply to Limit orders widget * Example: diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts index 3d0f49ba9c..b993a8130d 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts @@ -1,12 +1,13 @@ import { useAtomValue } from 'jotai' +import { useGP2SettlementContract } from '@cowprotocol/common-hooks' import { OrderClass } from '@cowprotocol/cow-sdk' +import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' import { useDispatch } from 'react-redux' -import { useGP2SettlementContract } from 'legacy/hooks/useContract' import { AppDispatch } from 'legacy/state' import { useAppData } from 'modules/appData' @@ -14,7 +15,6 @@ import { useRateImpact } from 'modules/limitOrders/hooks/useRateImpact' import { TradeFlowContext } from 'modules/limitOrders/services/types' import { limitOrdersSettingsAtom } from 'modules/limitOrders/state/limitOrdersSettingsAtom' import { useTradeQuote } from 'modules/tradeQuote' -import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet' import { useLimitOrdersDerivedState } from './useLimitOrdersDerivedState' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useUpdateCurrencyAmount.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useUpdateCurrencyAmount.ts index bbc2ede726..17b695c8f9 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useUpdateCurrencyAmount.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useUpdateCurrencyAmount.ts @@ -1,17 +1,17 @@ import { useSetAtom } from 'jotai' import { useCallback } from 'react' +import { FractionUtils } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/cow-sdk' import { Fraction } from '@uniswap/sdk-core' import { Writeable } from 'types' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOrdersDerivedState' import { LimitOrdersRawState, updateLimitOrdersRawStateAtom } from 'modules/limitOrders/state/limitOrdersRawStateAtom' -import { FractionUtils } from 'utils/fractionUtils' import { calculateAmountForRate } from 'utils/orderUtils/calculateAmountForRate' type CurrencyAmountProps = { diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/index.tsx index be050ea38d..25fb8a440e 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/DeadlineSelector/index.tsx @@ -1,11 +1,11 @@ import { ChangeEventHandler, useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { ButtonPrimary, ButtonSecondary } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { Menu } from '@reach/menu-button' import { ChevronDown } from 'react-feather' -import { ButtonPrimary, ButtonSecondary } from 'legacy/components/Button' - import { calculateMinMax, formatDateToLocalTime, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/index.tsx index cbefe4f3ea..f31603ba88 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/ExecutionPriceTooltip/index.tsx @@ -1,11 +1,10 @@ +import { FiatAmount, TokenAmount } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Fraction, Price } from '@uniswap/sdk-core' import { useUsdAmount } from 'modules/usdAmount' import { ExecutionPrice } from 'common/pure/ExecutionPrice' -import { FiatAmount } from 'common/pure/FiatAmount' import { RateTooltipHeader } from 'common/pure/OrderExecutionStatusList' -import { TokenAmount } from 'common/pure/TokenAmount' import { convertAmountToCurrency } from 'utils/orderUtils/calculateExecutionPrice' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/index.tsx index d41eb8b05b..b65af754c7 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/InfoBanner/index.tsx @@ -1,10 +1,10 @@ import { useState, useEffect } from 'react' +import AlertIcon from '@cowprotocol/assets/cow-swap/alert-circle.svg' + import SVG from 'react-inlinesvg' import { HashLink } from 'react-router-hash-link' -import AlertIcon from 'legacy/assets/cow-swap/alert-circle.svg' - import * as styledEl from './styled' export function InfoBanner() { diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx index d9fcd3f2e7..8e246a0168 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx @@ -1,10 +1,11 @@ import { SetStateAction } from 'jotai' -import { OrderClass, OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' +import { COW, GNO } from '@cowprotocol/common-const' +import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { OrderKind } from '@cowprotocol/cow-sdk' +import { OrderClass } from '@cowprotocol/cow-sdk' import { CurrencyAmount } from '@uniswap/sdk-core' -import { COW, GNO } from 'legacy/constants/tokens' - import { getAppData } from 'modules/appData' import { defaultLimitOrdersSettings } from 'modules/limitOrders/state/limitOrdersSettingsAtom' import { initLimitRateState } from 'modules/limitOrders/state/limitRateAtom' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx index 0a086921f6..a201d11707 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.tsx @@ -1,14 +1,16 @@ import React, { useMemo, useState } from 'react' +import ArrowDownImage from '@cowprotocol/assets/cow-swap/arrowDownRight.svg' +import { DEFAULT_DATE_FORMAT } from '@cowprotocol/common-const' +import { formatInputAmount } from '@cowprotocol/common-utils' +import { isAddress, shortenAddress } from '@cowprotocol/common-utils' import { Currency, Price } from '@uniswap/sdk-core' import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import ArrowDownImage from 'legacy/assets/cow-swap/arrowDownRight.svg' import { InfoIcon } from 'legacy/components/InfoIcon' import QuestionHelper from 'legacy/components/QuestionHelper' -import { isAddress, shortenAddress } from 'legacy/utils' import { ExecutionPriceTooltip } from 'modules/limitOrders/pure/ExecutionPriceTooltip' import { OrderType } from 'modules/limitOrders/pure/OrderType' @@ -19,11 +21,9 @@ import { PartiallyFillableOverrideDispatcherType } from 'modules/limitOrders/sta import { calculateLimitOrdersDeadline } from 'modules/limitOrders/utils/calculateLimitOrdersDeadline' import { ordersTableFeatures } from 'common/constants/featureFlags' -import { DEFAULT_DATE_FORMAT } from 'common/constants/intl' import { UI } from 'common/constants/theme' import { ExecutionPrice } from 'common/pure/ExecutionPrice' import { RateInfoParams } from 'common/pure/RateInfo' -import { formatInputAmount } from 'utils/amountFormat' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx index a59dd4bcf3..cc33942ac7 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx @@ -1,6 +1,7 @@ +import IMAGE_CARET_DOWN from '@cowprotocol/assets/cow-swap/carret-down.svg' + import { Menu } from '@reach/menu-button' -import IMAGE_CARET_DOWN from 'legacy/assets/cow-swap/carret-down.svg' import { InfoIcon } from 'legacy/components/InfoIcon' import { DetailsRow } from 'modules/limitOrders/pure/LimitOrdersDetails/styled' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.cosmos.tsx index b37a7bb897..1a960c2370 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.cosmos.tsx @@ -1,4 +1,4 @@ -import { GNO_GNOSIS_CHAIN } from 'legacy/utils/gnosis_chain/constants' +import { GNO_GNOSIS_CHAIN } from '@cowprotocol/common-const' import { RateImpactIndicator } from './index' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx index aa10f40114..b91dec12ad 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactIndicator/index.tsx @@ -1,14 +1,13 @@ +import { TokenSymbol } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' import { Currency } from '@uniswap/sdk-core' import { AlertTriangle } from 'react-feather' import styled from 'styled-components/macro' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' - import { LOW_RATE_THRESHOLD_PERCENT } from 'modules/limitOrders/const/trade' import { UI } from 'common/constants/theme' -import { TokenSymbol } from 'common/pure/TokenSymbol' interface RateImpactProps { rateImpact: number diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.cosmos.tsx index 2f8500fc93..234e81092a 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.cosmos.tsx @@ -1,7 +1,6 @@ +import { COW } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { COW } from 'legacy/constants/tokens' - import { RateImpactWarning } from './index' const Fixtures = { diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx index fb62d0415c..0b62777663 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/RateImpactWarning/index.tsx @@ -1,3 +1,4 @@ +import { TokenSymbol } from '@cowprotocol/ui' import { Currency } from '@uniswap/sdk-core' import { transparentize, lighten, darken } from 'polished' @@ -7,7 +8,6 @@ import styled from 'styled-components/macro' import { LOW_RATE_THRESHOLD_PERCENT } from 'modules/limitOrders/const/trade' import { UI } from 'common/constants/theme' -import { TokenSymbol } from 'common/pure/TokenSymbol' interface RateImpactAcknowledge { withAcknowledge: boolean diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts index 709933594a..54e51d1798 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts @@ -1,5 +1,5 @@ +import { Erc20, GPv2Settlement } from '@cowprotocol/abis' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { Erc20, GPv2Settlement } from '@cowswap/abis' import { Web3Provider } from '@ethersproject/providers' import SafeAppsSDK from '@safe-global/safe-apps-sdk' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersRawStateAtom.ts b/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersRawStateAtom.ts index fbec1895e0..c0d8afc079 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersRawStateAtom.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersRawStateAtom.ts @@ -1,10 +1,9 @@ import { atom } from 'jotai' import { atomWithStorage } from 'jotai/utils' +import { getJotaiIsolatedStorage } from '@cowprotocol/core' import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' -import { getJotaiIsolatedStorage } from 'jotaiStore' - import { DEFAULT_TRADE_DERIVED_STATE, TradeDerivedState } from 'modules/trade/types/TradeDerivedState' import { ExtendedTradeRawState, getDefaultTradeRawState } from 'modules/trade/types/TradeRawState' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersSettingsAtom.ts b/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersSettingsAtom.ts index 634d9ebd86..5241831bd5 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersSettingsAtom.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/state/limitOrdersSettingsAtom.ts @@ -1,7 +1,8 @@ import { atom } from 'jotai' import { atomWithStorage } from 'jotai/utils' -import { getJotaiIsolatedStorage } from 'jotaiStore' +import { getJotaiIsolatedStorage } from '@cowprotocol/core' + import { Milliseconds, Timestamp } from 'types' import { defaultLimitOrderDeadline } from 'modules/limitOrders/pure/DeadlineSelector/deadlines' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/state/limitRateAtom.ts b/apps/cowswap-frontend/src/modules/limitOrders/state/limitRateAtom.ts index 5887799588..66f79dd58c 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/state/limitRateAtom.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/state/limitRateAtom.ts @@ -1,9 +1,8 @@ import { atom } from 'jotai' +import { atomWithPartialUpdate } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Fraction } from '@uniswap/sdk-core' -import { atomWithPartialUpdate } from 'utils/jotai/atomWithPartialUpdate' - export interface LimitRateState { readonly isLoading: boolean readonly isLoadingMarketRate: boolean diff --git a/apps/cowswap-frontend/src/modules/limitOrders/updaters/InitialPriceUpdater/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/updaters/InitialPriceUpdater/index.tsx index aa6161f7db..4a7f8d6480 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/updaters/InitialPriceUpdater/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/updaters/InitialPriceUpdater/index.tsx @@ -1,9 +1,9 @@ import { useSetAtom } from 'jotai' import { useLayoutEffect, useState } from 'react' -import { Writeable } from 'types' +import { usePrevious } from '@cowprotocol/common-hooks' -import usePrevious from 'legacy/hooks/usePrevious' +import { Writeable } from 'types' import { useGetInitialPrice } from 'modules/limitOrders/hooks/useGetInitialPrice' import { useUpdateActiveRate } from 'modules/limitOrders/hooks/useUpdateActiveRate' diff --git a/apps/cowswap-frontend/src/modules/limitOrders/updaters/QuoteObserverUpdater/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/updaters/QuoteObserverUpdater/index.tsx index ecfba21327..75fcfa3997 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/updaters/QuoteObserverUpdater/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/updaters/QuoteObserverUpdater/index.tsx @@ -1,14 +1,13 @@ import { useSetAtom } from 'jotai' import { useEffect } from 'react' +import { FractionUtils } from '@cowprotocol/common-utils' import { CurrencyAmount, Percent, Price } from '@uniswap/sdk-core' import { updateLimitRateAtom } from 'modules/limitOrders/state/limitRateAtom' import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' import { useTradeQuote } from 'modules/tradeQuote' -import { FractionUtils } from 'utils/fractionUtils' - export const LIMIT_ORDERS_PRICE_SLIPPAGE = new Percent(1, 10) // 0.1% export function QuoteObserverUpdater() { diff --git a/apps/cowswap-frontend/src/modules/limitOrders/utils/calculateLimitOrdersDeadline.ts b/apps/cowswap-frontend/src/modules/limitOrders/utils/calculateLimitOrdersDeadline.ts index 6e74aef9d2..d6a120a074 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/utils/calculateLimitOrdersDeadline.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/utils/calculateLimitOrdersDeadline.ts @@ -1,9 +1,9 @@ +import { calculateValidTo } from '@cowprotocol/common-utils' + import { Timestamp } from 'types' import { LimitOrdersSettingsState } from 'modules/limitOrders/state/limitOrdersSettingsAtom' -import { calculateValidTo } from 'utils/time' - export function calculateLimitOrdersDeadline(settingsState: LimitOrdersSettingsState): Timestamp { return settingsState.customDeadlineTimestamp ? settingsState.customDeadlineTimestamp diff --git a/apps/cowswap-frontend/src/modules/limitOrders/utils/parsePrice.ts b/apps/cowswap-frontend/src/modules/limitOrders/utils/parsePrice.ts index 1e38742387..75ba2cafc5 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/utils/parsePrice.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/utils/parsePrice.ts @@ -1,7 +1,6 @@ +import { DEFAULT_DECIMALS } from '@cowprotocol/common-const' import { Currency } from '@uniswap/sdk-core' -import { DEFAULT_DECIMALS } from 'legacy/constants' - /** * @deprecated use rawToTokenAmount */ diff --git a/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx b/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx index 290cb15b5d..d7f223602f 100644 --- a/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx +++ b/apps/cowswap-frontend/src/modules/mainMenu/constants/mainMenu.tsx @@ -1,21 +1,26 @@ -import { Globe } from 'react-feather' - -import IMAGE_CODE from 'legacy/assets/cow-swap/code.svg' -import IMAGE_COOKIE_POLICY from 'legacy/assets/cow-swap/cookie-policy.svg' -import IMAGE_DISCORD from 'legacy/assets/cow-swap/discord.svg' -import IMAGE_DOCS from 'legacy/assets/cow-swap/doc.svg' -import IMAGE_GAME from 'legacy/assets/cow-swap/game.gif' -import IMAGE_INFO from 'legacy/assets/cow-swap/info.svg' -import IMAGE_SLICER from 'legacy/assets/cow-swap/ninja-cow.png' -import IMAGE_PIE from 'legacy/assets/cow-swap/pie.svg' -import IMAGE_PRIVACY_POLICY from 'legacy/assets/cow-swap/privacy-policy.svg' -import IMAGE_TERMS_AND_CONDITIONS from 'legacy/assets/cow-swap/terms-and-conditions.svg' -import IMAGE_TWITTER from 'legacy/assets/cow-swap/twitter.svg' -import { CONTRACTS_CODE_LINK, DISCORD_LINK, DOCS_LINK, DUNE_DASHBOARD_LINK, TWITTER_LINK } from 'legacy/constants' -import { ExternalLink } from 'legacy/theme' -import { getExplorerBaseUrl } from 'legacy/utils/explorer' +import IMAGE_CODE from '@cowprotocol/assets/cow-swap/code.svg' +import IMAGE_COOKIE_POLICY from '@cowprotocol/assets/cow-swap/cookie-policy.svg' +import IMAGE_DISCORD from '@cowprotocol/assets/cow-swap/discord.svg' +import IMAGE_DOCS from '@cowprotocol/assets/cow-swap/doc.svg' +import IMAGE_GAME from '@cowprotocol/assets/cow-swap/game.gif' +import IMAGE_INFO from '@cowprotocol/assets/cow-swap/info.svg' +import IMAGE_SLICER from '@cowprotocol/assets/cow-swap/ninja-cow.png' +import IMAGE_PIE from '@cowprotocol/assets/cow-swap/pie.svg' +import IMAGE_PRIVACY_POLICY from '@cowprotocol/assets/cow-swap/privacy-policy.svg' +import IMAGE_TERMS_AND_CONDITIONS from '@cowprotocol/assets/cow-swap/terms-and-conditions.svg' +import IMAGE_TWITTER from '@cowprotocol/assets/cow-swap/twitter.svg' +import { + CONTRACTS_CODE_LINK, + DISCORD_LINK, + DOCS_LINK, + DUNE_DASHBOARD_LINK, + TWITTER_LINK, +} from '@cowprotocol/common-const' +import { getExplorerBaseUrl } from '@cowprotocol/common-utils' +import { ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' -import { useWalletInfo } from 'modules/wallet' +import { Globe } from 'react-feather' import { Routes } from 'common/constants/routes' diff --git a/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx b/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx index 2215781845..b5ba054f26 100644 --- a/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx +++ b/apps/cowswap-frontend/src/modules/mainMenu/pure/MenuTree/index.tsx @@ -1,11 +1,12 @@ +import IMAGE_MOON from '@cowprotocol/assets/cow-swap/moon.svg' +import IMAGE_SUN from '@cowprotocol/assets/cow-swap/sun.svg' +import { ExternalLink as ExternalLinkComponent } from '@cowprotocol/ui' + import SVG from 'react-inlinesvg' -import IMAGE_MOON from 'legacy/assets/cow-swap/moon.svg' -import IMAGE_SUN from 'legacy/assets/cow-swap/sun.svg' import { HeaderLinks as Wrapper, StyledNavLink } from 'legacy/components/Header/styled' import MenuDropdown from 'legacy/components/MenuDropdown' import { MenuSection, MenuTitle } from 'legacy/components/MenuDropdown/styled' -import { ExternalLink as ExternalLinkComponent } from 'legacy/theme/components' import { CustomItem, diff --git a/apps/cowswap-frontend/src/modules/operations/bundle/buildApproveTx.ts b/apps/cowswap-frontend/src/modules/operations/bundle/buildApproveTx.ts index 7a2e6ac24b..abd22db931 100644 --- a/apps/cowswap-frontend/src/modules/operations/bundle/buildApproveTx.ts +++ b/apps/cowswap-frontend/src/modules/operations/bundle/buildApproveTx.ts @@ -1,4 +1,4 @@ -import { Erc20 } from '@cowswap/abis' +import { Erc20 } from '@cowprotocol/abis' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { estimateApprove } from 'common/hooks/useApproveCallback' diff --git a/apps/cowswap-frontend/src/modules/operations/bundle/buildPresignTx.ts b/apps/cowswap-frontend/src/modules/operations/bundle/buildPresignTx.ts index 49f9fcc256..d4157a7d5b 100644 --- a/apps/cowswap-frontend/src/modules/operations/bundle/buildPresignTx.ts +++ b/apps/cowswap-frontend/src/modules/operations/bundle/buildPresignTx.ts @@ -1,4 +1,4 @@ -import { GPv2Settlement } from '@cowswap/abis' +import { GPv2Settlement } from '@cowprotocol/abis' export type BuildPresignTxParams = { orderId: string diff --git a/apps/cowswap-frontend/src/modules/operations/bundle/buildWrapTx.ts b/apps/cowswap-frontend/src/modules/operations/bundle/buildWrapTx.ts index e0d9e9d577..0adeb8e0c2 100644 --- a/apps/cowswap-frontend/src/modules/operations/bundle/buildWrapTx.ts +++ b/apps/cowswap-frontend/src/modules/operations/bundle/buildWrapTx.ts @@ -1,4 +1,4 @@ -import { Weth } from '@cowswap/abis' +import { Weth } from '@cowprotocol/abis' export type BuildWrapTxParams = { wrappedNativeContract: Weth diff --git a/apps/cowswap-frontend/src/modules/orders/hooks/useSWROrdersRequest.ts b/apps/cowswap-frontend/src/modules/orders/hooks/useSWROrdersRequest.ts index 49f4fe2d97..d3fada025a 100644 --- a/apps/cowswap-frontend/src/modules/orders/hooks/useSWROrdersRequest.ts +++ b/apps/cowswap-frontend/src/modules/orders/hooks/useSWROrdersRequest.ts @@ -1,8 +1,7 @@ import { useMemo } from 'react' -import { AMOUNT_OF_ORDERS_TO_FETCH } from 'legacy/constants' - -import { useWalletInfo } from 'modules/wallet' +import { AMOUNT_OF_ORDERS_TO_FETCH } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' export function useSWROrdersRequest(): { owner: string; limit: number } | null { const { account } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/modules/orders/hooks/useSWRProdOrders.ts b/apps/cowswap-frontend/src/modules/orders/hooks/useSWRProdOrders.ts index da01743db6..0e438f14bf 100644 --- a/apps/cowswap-frontend/src/modules/orders/hooks/useSWRProdOrders.ts +++ b/apps/cowswap-frontend/src/modules/orders/hooks/useSWRProdOrders.ts @@ -1,14 +1,12 @@ import { useMemo } from 'react' +import { GP_ORDER_UPDATE_INTERVAL } from '@cowprotocol/common-const' +import { isBarnBackendEnv } from '@cowprotocol/common-utils' import { EnrichedOrder } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import useSWR from 'swr' -import { GP_ORDER_UPDATE_INTERVAL } from 'legacy/constants' -import { isBarnBackendEnv } from 'legacy/utils/environments' - -import { useWalletInfo } from 'modules/wallet' - import { getOrders } from 'api/gnosisProtocol' import { useApiOrders } from './useApiOrders' diff --git a/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts b/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts index e3e42c175d..0d04ef6ea3 100644 --- a/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts +++ b/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts @@ -1,12 +1,12 @@ import { useCallback, useRef } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' import { useAllTokens } from 'legacy/hooks/Tokens' import { useTokenLazy } from 'legacy/hooks/useTokenLazy' import { TokensByAddress, TokenWithLogo } from 'modules/tokensList/state/tokensListAtom' -import { useWalletInfo } from 'modules/wallet' import { getTokenFromMapping } from 'utils/orderUtils/getTokenFromMapping' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx index 1c76ec5bc4..760b94f5b9 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/MultipleCancellationMenu/index.tsx @@ -1,12 +1,12 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useCallback, useEffect } from 'react' +import { useWalletDetails } from '@cowprotocol/wallet' + import { transparentize } from 'polished' import { Trash2 } from 'react-feather' import styled from 'styled-components/macro' -import { useWalletDetails } from 'modules/wallet' - import { UI } from 'common/constants/theme' import { useMultipleOrdersCancellation } from 'common/hooks/useMultipleOrdersCancellation' import { ordersToCancelAtom, updateOrdersToCancelAtom } from 'common/hooks/useMultipleOrdersCancellation/state' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersReceiptModal/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersReceiptModal/index.tsx index e13b1738ed..4cc7b9f947 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersReceiptModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersReceiptModal/index.tsx @@ -1,13 +1,12 @@ +import { useENS } from '@cowprotocol/ens' +import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount } from '@uniswap/sdk-core' import JSBI from 'jsbi' -import useENS from 'legacy/hooks/useENS' - import { PendingOrdersPrices } from 'modules/orders/state/pendingOrdersPricesAtom' import { ReceiptModal } from 'modules/ordersTable/pure/ReceiptModal' import { useTwapOrderById, useTwapOrderByChildId } from 'modules/twap' -import { useWalletInfo } from 'modules/wallet' import { calculatePrice } from 'utils/orderUtils/calculatePrice' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx index e56a3abbfa..d614a6f8a6 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx @@ -1,10 +1,12 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useCallback, useEffect, useMemo } from 'react' +import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' +import { useIsSafeViaWc, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' + import { useLocation, useNavigate } from 'react-router-dom' import styled from 'styled-components/macro' -import { GP_VAULT_RELAYER } from 'legacy/constants' import { Order } from 'legacy/state/orders/actions' import { pendingOrdersPricesAtom } from 'modules/orders/state/pendingOrdersPricesAtom' @@ -16,7 +18,6 @@ import { useSelectReceiptOrder } from 'modules/ordersTable/containers/OrdersRece import { OrderActions } from 'modules/ordersTable/pure/OrdersTableContainer/types' import { buildOrdersTableUrl, parseOrdersTableUrl } from 'modules/ordersTable/utils/buildOrdersTableUrl' import { useBalancesAndAllowances } from 'modules/tokens' -import { useIsSafeViaWc, useWalletDetails, useWalletInfo } from 'modules/wallet' import { useCancelOrder } from 'common/hooks/useCancelOrder' import { ordersToCancelAtom, updateOrdersToCancelAtom } from 'common/hooks/useMultipleOrdersCancellation/state' @@ -26,6 +27,7 @@ import { ParsedOrder } from 'utils/orderUtils/parseOrder' import { OrdersTableList, useOrdersTableList } from './hooks/useOrdersTableList' import { useValidatePageUrlParams } from './hooks/useValidatePageUrlParams' +import { useCategorizeRecentActivity } from '../../../../common/hooks/useCategorizeRecentActivity' import { OrdersTableContainer, TabOrderTypes } from '../../pure/OrdersTableContainer' import { getParsedOrderFromItem, OrderTableItem, tableItemsToOrders } from '../../utils/orderTableGroupUtils' @@ -103,6 +105,7 @@ export function OrdersTableWidget({ // Get effective balance const balancesAndAllowances = useBalancesAndAllowances({ account, spender, tokens }) + const { pendingActivity } = useCategorizeRecentActivity() const toggleOrdersForCancellation = useCallback( (orders: ParsedOrder[]) => { @@ -160,6 +163,7 @@ export function OrdersTableWidget({ selectedOrders={ordersToCancel} allowsOffchainSigning={allowsOffchainSigning} orderType={orderType} + pendingActivities={pendingActivity} > {isOpenOrdersTab && orders.length && } diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx index 01d725a782..a1e9a5ab86 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx @@ -1,18 +1,17 @@ import { useContext } from 'react' +import AlertTriangle from '@cowprotocol/assets/cow-swap/alert.svg' +import { ZERO_FRACTION } from '@cowprotocol/common-const' +import { SymbolElement, TokenAmount, TokenAmountProps } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Fraction, Percent } from '@uniswap/sdk-core' import { darken, transparentize } from 'polished' import SVG from 'react-inlinesvg' import styled, { ThemeContext } from 'styled-components/macro' -import AlertTriangle from 'legacy/assets/cow-swap/alert.svg' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' -import { ZERO_FRACTION } from 'legacy/constants' - import { HIGH_FEE_WARNING_PERCENTAGE } from 'common/constants/common' import { calculateOrderExecutionStatus, ExecuteIndicator } from 'common/pure/OrderExecutionStatusList' -import { SymbolElement, TokenAmount, TokenAmountProps } from 'common/pure/TokenAmount' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx index 0fbfe8a87e..975b764807 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx @@ -1,18 +1,18 @@ import React, { useCallback, useContext, useEffect, useState } from 'react' +import AlertTriangle from '@cowprotocol/assets/cow-swap/alert.svg' +import { ZERO_FRACTION } from '@cowprotocol/common-const' +import { useTimeAgo } from '@cowprotocol/common-hooks' +import { getAddress, getEtherscanLink } from '@cowprotocol/common-utils' import { OrderClass, SupportedChainId } from '@cowprotocol/cow-sdk' +import { TokenAmount, TokenSymbol, Loader } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Percent, Price } from '@uniswap/sdk-core' import SVG from 'react-inlinesvg' import { ThemeContext } from 'styled-components/macro' -import AlertTriangle from 'legacy/assets/cow-swap/alert.svg' -import Loader from 'legacy/components/Loader' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' -import { ZERO_FRACTION } from 'legacy/constants' -import useTimeAgo from 'legacy/hooks/useTimeAgo' import { CREATING_STATES, OrderStatus } from 'legacy/state/orders/actions' -import { getEtherscanLink } from 'legacy/utils' import { PendingOrderPrices } from 'modules/orders/state/pendingOrdersPricesAtom' import { EstimatedExecutionPrice } from 'modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice' @@ -30,11 +30,8 @@ import { getIsEthFlowOrder } from 'modules/swap/containers/EthFlowStepper' import { useSafeMemo } from 'common/hooks/useSafeMemo' import { CurrencyLogo } from 'common/pure/CurrencyLogo' import { RateInfo } from 'common/pure/RateInfo' -import { TokenAmount } from 'common/pure/TokenAmount' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { getQuoteCurrency } from 'common/services/getQuoteCurrency' import { isOrderCancellable } from 'common/utils/isOrderCancellable' -import { getAddress } from 'utils/getAddress' import { calculatePercentageInRelationToReference } from 'utils/orderUtils/calculatePercentageInRelationToReference' import { calculatePriceDifference, PriceDifference } from 'utils/orderUtils/calculatePriceDifference' import { getIsComposableCowParentOrder } from 'utils/orderUtils/getIsComposableCowParentOrder' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx index 59da992d15..7fa718815c 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx @@ -1,5 +1,6 @@ import React, { useCallback, useState, useEffect, useMemo, useRef } from 'react' +import iconOrderExecution from '@cowprotocol/assets/cow-swap/orderExecution.svg' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency, Price } from '@uniswap/sdk-core' @@ -10,7 +11,6 @@ import SVG from 'react-inlinesvg' import { useLocation } from 'react-router-dom' import styled from 'styled-components/macro' -import iconOrderExecution from 'legacy/assets/cow-swap/orderExecution.svg' import { QuestionWrapper } from 'legacy/components/QuestionHelper' import QuestionHelper from 'legacy/components/QuestionHelper' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx index 0f77268d15..9b96ba327d 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx @@ -50,6 +50,7 @@ const orderActions: OrderActions = { export default ( transparentize(0.3, theme.text1)}; } - - ${Web3StatusWrapper} { - margin: 0 auto; - } ` const Header = styled.div` @@ -144,6 +139,7 @@ export interface OrdersProps extends OrdersTabsProps, OrdersTableProps { isOpenOrdersTab: boolean isSafeViaWc: boolean displayOrdersOnlyForSafeApp: boolean + pendingActivities: string[] children?: ReactNode orderType: TabOrderTypes } @@ -170,6 +166,7 @@ export function OrdersTableContainer({ getSpotPrice, children, orderType, + pendingActivities, }: OrdersProps) { const content = () => { if (!isWalletConnected) { @@ -188,7 +185,7 @@ export function OrdersTableContainer({

- + ) } diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts index 89c9e45e14..742785a504 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts @@ -1,8 +1,8 @@ +import { COW, DAI, GNO, USDC } from '@cowprotocol/common-const' +import { WETH_GOERLI } from '@cowprotocol/common-const' import { OrderKind, OrderClass } from '@cowprotocol/cow-sdk' -import { COW, DAI, GNO, USDC } from 'legacy/constants/tokens' import { OrderStatus } from 'legacy/state/orders/actions' -import { WETH_GOERLI } from 'legacy/utils/goerli/constants' import { ParsedOrder, parseOrder } from 'utils/orderUtils/parseOrder' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts index 8968e26a34..c7e0077ed9 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts @@ -1,10 +1,10 @@ +import { isEnoughAmount } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core' import { BalancesAndAllowances } from 'modules/tokens' import { RateInfoParams } from 'common/pure/RateInfo' -import { isEnoughAmount } from 'utils/isEnoughAmount' import { ParsedOrder } from 'utils/orderUtils/parseOrder' export interface OrderParams { diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/CurrencyField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/CurrencyField.tsx index 05b1f2a7b5..ddb834a39e 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/CurrencyField.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/CurrencyField.tsx @@ -1,7 +1,7 @@ +import { TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { CurrencySelectButton } from 'common/pure/CurrencySelectButton' -import { TokenAmount } from 'common/pure/TokenAmount' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/DateField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/DateField.tsx index 38642583fe..63ae1693af 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/DateField.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/DateField.tsx @@ -1,6 +1,6 @@ -import { format } from 'date-fns' +import { useTimeAgo } from '@cowprotocol/common-hooks' -import useTimeAgo from 'legacy/hooks/useTimeAgo' +import { format } from 'date-fns' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx index 7786024f61..eed9c96389 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx @@ -1,6 +1,6 @@ +import { TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount } from '@uniswap/sdk-core' -import { TokenAmount } from 'common/pure/TokenAmount' import { ParsedOrder } from 'utils/orderUtils/parseOrder' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FilledField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FilledField.tsx index 5c2752ac09..866e6c7e93 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FilledField.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FilledField.tsx @@ -1,8 +1,9 @@ // Code based on https://github.com/cowprotocol/explorer/blob/develop/src/components/orders/FilledProgress/index.tsx +import { TokenAmount } from '@cowprotocol/ui' + import { ProgressBarWrapper, ProgressBar } from 'modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled' -import { TokenAmount } from 'common/pure/TokenAmount' import { getFilledAmounts } from 'utils/orderUtils/getFilledAmounts' import { ParsedOrder } from 'utils/orderUtils/parseOrder' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/IdField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/IdField.tsx index 73eef077b1..4947ceeda0 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/IdField.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/IdField.tsx @@ -1,7 +1,6 @@ +import { getEtherscanLink } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' - -import { ExternalLink } from 'legacy/theme' -import { getEtherscanLink } from 'legacy/utils' +import { ExternalLink } from '@cowprotocol/ui' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/PriceField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/PriceField.tsx index 9a6b7a469d..9e53548174 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/PriceField.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/PriceField.tsx @@ -1,7 +1,7 @@ +import { TokenAmount } from '@cowprotocol/ui' +import { TokenSymbol } from '@cowprotocol/ui' import { Fraction } from '@uniswap/sdk-core' -import { TokenAmount } from 'common/pure/TokenAmount' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { ParsedOrder } from 'utils/orderUtils/parseOrder' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/SurplusField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/SurplusField.tsx index 7cd1495a1b..235ec3282c 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/SurplusField.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/SurplusField.tsx @@ -1,7 +1,7 @@ import { OrderKind } from '@cowprotocol/cow-sdk' +import { TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount } from '@uniswap/sdk-core' -import { TokenAmount } from 'common/pure/TokenAmount' import { ParsedOrder } from 'utils/orderUtils/parseOrder' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx index 93a75c77f2..00eea420be 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx @@ -1,9 +1,8 @@ +import safeLogo from '@cowprotocol/assets/cow-swap/safe-logo.svg' import { SupportedChainId } from '@cowprotocol/cow-sdk' import styled from 'styled-components/macro' -import safeLogo from 'modules/wallet/api/assets/safe-logo.svg' - import { SafeWalletLink } from 'common/pure/SafeWalletLink' import { FieldLabel } from '../FieldLabel' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/index.tsx index 512aae78c7..1674420030 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/index.tsx @@ -1,10 +1,10 @@ +import { ExplorerDataType, getExplorerLink, shortenAddress } from '@cowprotocol/common-utils' import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' +import { ExternalLink } from '@cowprotocol/ui' import { CurrencyAmount, Fraction, Token } from '@uniswap/sdk-core' import { OrderStatus } from 'legacy/state/orders/actions' -import { CloseIcon, ExternalLink } from 'legacy/theme' -import { shortenAddress } from 'legacy/utils' -import { ExplorerDataType, getExplorerLink } from 'legacy/utils/getExplorerLink' +import { CloseIcon } from 'legacy/theme' import { TwapOrderItem } from 'modules/twap/types' diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts index 6f92e99b9d..40f48d20d3 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts @@ -1,6 +1,6 @@ -import styled from 'styled-components/macro' +import { AutoRow } from '@cowprotocol/ui' -import { AutoRow } from 'legacy/components/Row' +import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts index 15b298c94a..d778e690b3 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts @@ -1,10 +1,10 @@ import { useEffect, useState } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' import { useDerivedTradeState } from 'modules/trade' -import { useWalletInfo } from 'modules/wallet' import { useSafeMemo } from 'common/hooks/useSafeMemo' diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts index ccf2505ac0..fb53e69be3 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts @@ -2,13 +2,12 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useEffect, useMemo } from 'react' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' import { Nullish } from 'types' -import { useWalletInfo } from 'modules/wallet' - import { useIsPermitEnabled } from 'common/hooks/featureFlags/useIsPermitEnabled' import { addPermitInfoForTokenAtom, permittableTokensAtom } from '../state/atoms' diff --git a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts index d5ab345122..a55a0fb9a0 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts @@ -1,10 +1,9 @@ +import { GP_VAULT_RELAYER, NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import type { Web3Provider } from '@ethersproject/providers' import { DAI_LIKE_PERMIT_TYPEHASH, Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' -import { GP_VAULT_RELAYER, NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants' - import { PermitProviderConnector } from 'modules/wallet/utils/PermitProviderConnector' import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData' diff --git a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts index 0032cb19bc..207abece48 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts @@ -1,9 +1,8 @@ +import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' import { Web3Provider } from '@ethersproject/providers' import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' -import { GP_VAULT_RELAYER } from 'legacy/constants' - import { PermitProviderConnector } from 'modules/wallet/utils/PermitProviderConnector' import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData' diff --git a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useEthFlowActions.ts b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useEthFlowActions.ts index 557a19e047..0bea93ab97 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useEthFlowActions.ts +++ b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useEthFlowActions.ts @@ -2,17 +2,18 @@ import { useSetAtom } from 'jotai' import { useAtomValue } from 'jotai' import { useMemo } from 'react' -import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' +import { WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' + import { WrapUnwrapCallback } from 'legacy/hooks/useWrapCallback' -import { Field } from 'legacy/state/swap/actions' -import { useDerivedSwapInfo, useSwapActionHandlers } from 'legacy/state/swap/hooks' +import { Field } from 'legacy/state/types' import { useSwapConfirmManager } from 'modules/swap/hooks/useSwapConfirmManager' import { HandleSwapCallback } from 'modules/swap/pure/SwapButtons' -import { useWalletInfo } from 'modules/wallet' import { TradeApproveCallback } from 'common/containers/TradeApprove/useTradeApproveCallback' +import { useDerivedSwapInfo, useSwapActionHandlers } from '../../../hooks/useSwapState' import { ethFlowContextAtom, updateEthFlowContextAtom } from '../../../state/EthFlow/ethFlowContextAtom' export interface EthFlowActionCallbacks { diff --git a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useRemainingNativeTxsAndCosts.ts b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useRemainingNativeTxsAndCosts.ts index 489f2f2408..58376d2694 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useRemainingNativeTxsAndCosts.ts +++ b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useRemainingNativeTxsAndCosts.ts @@ -1,15 +1,14 @@ import { useMemo } from 'react' +import { AVG_APPROVE_COST_GWEI } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' import { BigNumber } from '@ethersproject/bignumber' import { CurrencyAmount, Currency } from '@uniswap/sdk-core' import { parseUnits } from 'ethers/lib/utils' -import { AVG_APPROVE_COST_GWEI } from 'legacy/constants' import { useGasPrices } from 'legacy/state/gas/hooks' -import { useWalletInfo } from 'modules/wallet' - import { BalanceChecks } from '../../../pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent' export const MINIMUM_TXS = '10' diff --git a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useSetupEthFlow.ts b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useSetupEthFlow.ts index 72b41992d7..88c2d2e034 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useSetupEthFlow.ts +++ b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/hooks/useSetupEthFlow.ts @@ -1,9 +1,10 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useEffect, useState } from 'react' +import { delay } from '@cowprotocol/common-utils' + import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' import { ActivityDescriptors, ActivityStatus } from 'legacy/hooks/useRecentActivity' -import { delay } from 'legacy/utils/misc' import { EthFlowActions } from './useEthFlowActions' diff --git a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/index.tsx index ab11eed1bf..09af53c8e8 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/EthFlow/index.tsx @@ -1,6 +1,7 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { useSingleActivityDescriptor } from 'legacy/hooks/useRecentActivity' @@ -14,7 +15,6 @@ import { HandleSwapCallback } from 'modules/swap/pure/SwapButtons' import { ethFlowContextAtom } from 'modules/swap/state/EthFlow/ethFlowContextAtom' import { useCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalance' import { useWrappedToken } from 'modules/trade/hooks/useWrappedToken' -import { useWalletInfo } from 'modules/wallet' import { useTradeApproveCallback, useTradeApproveState } from 'common/containers/TradeApprove' import { CowModal } from 'common/pure/Modal' diff --git a/apps/cowswap-frontend/src/modules/swap/containers/EthFlowStepper/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/EthFlowStepper/index.tsx index e685f0d5a9..46b09bfcb2 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/EthFlowStepper/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/EthFlowStepper/index.tsx @@ -1,4 +1,6 @@ -import { NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants' +import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' +import { formatSymbol } from '@cowprotocol/common-utils' + import { useAllTransactions } from 'legacy/state/enhancedTransactions/hooks' import { EnhancedTransactionDetails } from 'legacy/state/enhancedTransactions/reducer' import { Order, OrderStatus } from 'legacy/state/orders/actions' @@ -11,7 +13,6 @@ import { } from 'modules/swap/pure/EthFlow/EthFlowStepper' import useNativeCurrency from 'lib/hooks/useNativeCurrency' -import { formatSymbol } from 'utils/format' type EthFlowStepperProps = { order: Order | undefined diff --git a/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx index 6508b41056..b25922ad7f 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/FeesDiscount/index.tsx @@ -1,10 +1,11 @@ +import { AutoRow } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { BoxProps, Text } from 'rebass' import styled, { DefaultTheme } from 'styled-components/macro' import { SUBSIDY_INFO_MESSAGE } from 'legacy/components/CowSubsidyModal/constants' -import { AutoRow } from 'legacy/components/Row' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' import useCowBalanceAndSubsidy from 'legacy/hooks/useCowBalanceAndSubsidy' import { StyledInfoIcon } from 'modules/swap/pure/styled' diff --git a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowFee/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowFee/index.tsx index 59b641ddeb..52e7136694 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowFee/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowFee/index.tsx @@ -1,5 +1,8 @@ import { useMemo } from 'react' +import { formatFiatAmount, formatTokenAmount } from '@cowprotocol/common-utils' +import { FractionUtils } from '@cowprotocol/common-utils' +import { formatSymbol } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Token, TradeType } from '@uniswap/sdk-core' import TradeGp from 'legacy/state/swap/TradeGp' @@ -9,9 +12,6 @@ import { RowFeeContent } from 'modules/swap/pure/Row/RowFeeContent' import { RowWithShowHelpersProps } from 'modules/swap/pure/Row/types' import useNativeCurrency from 'lib/hooks/useNativeCurrency' -import { formatFiatAmount, formatTokenAmount } from 'utils/amountFormat' -import { formatSymbol } from 'utils/format' -import { FractionUtils } from 'utils/fractionUtils' export const GASLESS_FEE_TOOLTIP_MSG = 'On CoW Swap you sign your order (hence no gas costs!). The fees are covering your gas costs already.' diff --git a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowReceivedAfterSlippage/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowReceivedAfterSlippage/index.tsx index 046ff8937c..f81ee43f1b 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowReceivedAfterSlippage/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowReceivedAfterSlippage/index.tsx @@ -2,8 +2,8 @@ import { useMemo } from 'react' import { Percent, TradeType } from '@uniswap/sdk-core' -import { Field } from 'legacy/state/swap/actions' import TradeGp from 'legacy/state/swap/TradeGp' +import { Field } from 'legacy/state/types' import { computeSlippageAdjustedAmounts } from 'legacy/utils/prices' import { RowReceivedAfterSlippageContent } from 'modules/swap/pure/Row/RowReceivedAfterSlippageContent' diff --git a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowSlippage/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowSlippage/index.tsx index ffe552649a..e5f9dbcfc9 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/Row/RowSlippage/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/Row/RowSlippage/index.tsx @@ -1,5 +1,6 @@ import { useMemo } from 'react' +import { formatPercent } from '@cowprotocol/common-utils' import { Percent } from '@uniswap/sdk-core' import { useToggleSettingsMenu } from 'legacy/state/application/hooks' @@ -8,7 +9,6 @@ import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow' import { RowSlippageContent } from 'modules/swap/pure/Row/RowSlippageContent' import useNativeCurrency from 'lib/hooks/useNativeCurrency' -import { formatPercent } from 'utils/amountFormat' export interface RowSlippageProps { allowedSlippage: Percent diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SetRecipient/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SetRecipient/index.tsx index 1583782fa0..55b110aa4b 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/SetRecipient/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/SetRecipient/index.tsx @@ -1,10 +1,11 @@ import { useContext } from 'react' +import { AutoRow } from '@cowprotocol/ui' + import { ArrowDown } from 'react-feather' import { ThemeContext } from 'styled-components/macro' import { AddressInputPanel } from 'legacy/components/AddressInputPanel' -import { AutoRow } from 'legacy/components/Row' import { ArrowWrapper } from 'legacy/components/swap/styleds' export interface SetRecipientProps { diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SurplusModalSetup/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SurplusModalSetup/index.tsx index cad0a44151..65f41ef968 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/SurplusModalSetup/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/SurplusModalSetup/index.tsx @@ -1,8 +1,8 @@ import { useCallback, useEffect } from 'react' -import { useOrder } from 'legacy/state/orders/hooks' +import { useWalletInfo } from '@cowprotocol/wallet' -import { useWalletInfo } from 'modules/wallet' +import { useOrder } from 'legacy/state/orders/hooks' import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue' import { CowModal } from 'common/pure/Modal' diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapModals/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SwapModals/index.tsx index bfb450a0b3..420510807f 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/SwapModals/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapModals/index.tsx @@ -1,10 +1,10 @@ import React from 'react' +import { genericPropsChecker } from '@cowprotocol/common-utils' + import { ConfirmSwapModalSetup, ConfirmSwapModalSetupProps } from 'modules/swap/containers/ConfirmSwapModalSetup' import { EthFlowModal, EthFlowProps } from 'modules/swap/containers/EthFlow' -import { genericPropsChecker } from 'utils/genericPropsChecker' - import { SurplusModalSetup } from '../SurplusModalSetup' export interface SwapModalsProps { diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx index c3e1bf2ce2..07a12bff92 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx @@ -1,20 +1,15 @@ import React, { useMemo, useState } from 'react' +import { isFractionFalsy } from '@cowprotocol/common-utils' +import { useIsSafeViaWc, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' + import { NetworkAlert } from 'legacy/components/NetworkAlert/NetworkAlert' import SettingsTab from 'legacy/components/Settings' import useCowBalanceAndSubsidy from 'legacy/hooks/useCowBalanceAndSubsidy' import { useModalIsOpen } from 'legacy/state/application/hooks' import { ApplicationModal } from 'legacy/state/application/reducer' import { useIsTradeUnsupported } from 'legacy/state/lists/hooks' -import { Field } from 'legacy/state/swap/actions' -import { - useDerivedSwapInfo, - useHighFeeWarning, - useIsFeeGreaterThanInput, - useSwapActionHandlers, - useSwapState, - useUnknownImpactWarning, -} from 'legacy/state/swap/hooks' +import { Field } from 'legacy/state/types' import { useExpertModeManager, useUserSlippageTolerance } from 'legacy/state/user/hooks' import { ConfirmSwapModalSetupProps } from 'modules/swap/containers/ConfirmSwapModalSetup' @@ -40,15 +35,21 @@ import { TradeWidget, TradeWidgetContainer, useTradePriceImpact } from 'modules/ import { useTradeRouteContext } from 'modules/trade/hooks/useTradeRouteContext' import { useWrappedToken } from 'modules/trade/hooks/useWrappedToken' import { useTradeUsdAmounts } from 'modules/usdAmount' -import { useIsSafeViaWc, useWalletDetails, useWalletInfo } from 'modules/wallet' import { useRateInfoParams } from 'common/hooks/useRateInfoParams' import { useShouldZeroApprove } from 'common/hooks/useShouldZeroApprove' import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types' import useNativeCurrency from 'lib/hooks/useNativeCurrency' -import { isFractionFalsy } from 'utils/isFractionFalsy' import { useIsSwapEth } from '../../hooks/useIsSwapEth' +import { + useDerivedSwapInfo, + useHighFeeWarning, + useIsFeeGreaterThanInput, + useSwapActionHandlers, + useSwapState, + useUnknownImpactWarning, +} from '../../hooks/useSwapState' const BUTTON_STATES_TO_SHOW_BUNDLE_APPROVAL_BANNER = [ SwapButtonState.ApproveAndSwap, diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/propsChecker.ts b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/propsChecker.ts index ff7ed8ff2b..9b292674e1 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/propsChecker.ts +++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/propsChecker.ts @@ -1,11 +1,12 @@ +import { genericPropsChecker } from '@cowprotocol/common-utils' +import { areFractionsEqual } from '@cowprotocol/common-utils' + import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { SwapFormProps } from 'modules/swap/containers/SwapWidget/types' import { ReceiveAmountInfo } from 'modules/swap/helpers/tradeReceiveAmount' import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types' -import { areFractionsEqual } from 'utils/areFractionsEqual' -import { genericPropsChecker } from 'utils/genericPropsChecker' function isReceiveAmountInfoEqual(prev: ReceiveAmountInfo | null, next: ReceiveAmountInfo | null): boolean { if (!prev || !next) { diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/types.ts b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/types.ts index 059cfabd08..b610f65bd1 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/types.ts +++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/types.ts @@ -2,10 +2,11 @@ import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { BalanceAndSubsidy } from 'legacy/hooks/useCowBalanceAndSubsidy' import { PriceImpact } from 'legacy/hooks/usePriceImpact' -import { SwapActions } from 'legacy/state/swap/hooks' import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types' +import { SwapActions } from '../../hooks/useSwapState' + export interface SwapFormProps { chainId: number | undefined recipient: string | null diff --git a/apps/cowswap-frontend/src/modules/swap/containers/TradeBasicDetails/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/TradeBasicDetails/index.tsx index 9d7893925b..7904ad0440 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/TradeBasicDetails/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/TradeBasicDetails/index.tsx @@ -1,8 +1,8 @@ +import { INITIAL_ALLOWED_SLIPPAGE_PERCENT } from '@cowprotocol/common-const' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { BoxProps } from 'rebass' -import { INITIAL_ALLOWED_SLIPPAGE_PERCENT } from 'legacy/constants' import TradeGp from 'legacy/state/swap/TradeGp' import { RowFee } from 'modules/swap/containers/Row/RowFee' diff --git a/apps/cowswap-frontend/src/modules/swap/containers/TradeSummary/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/TradeSummary/index.tsx index 376e8041a2..b8bb423882 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/TradeSummary/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/TradeSummary/index.tsx @@ -1,10 +1,10 @@ +import { useWalletDetails } from '@cowprotocol/wallet' import { Percent } from '@uniswap/sdk-core' import TradeGp from 'legacy/state/swap/TradeGp' import { TradeSummaryContent } from 'modules/swap/pure/TradeSummary' import { useUsdAmount } from 'modules/usdAmount' -import { useWalletDetails } from 'modules/wallet' // Sub-components diff --git a/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.test.ts b/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.test.ts index 2bd20f1c70..a1e1da4f79 100644 --- a/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.test.ts +++ b/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.test.ts @@ -1,9 +1,9 @@ import { ReactElement } from 'react' +import { COW, GNO } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount, Price, Token, TradeType } from '@uniswap/sdk-core' -import { COW, GNO } from 'legacy/constants/tokens' import TradeGp from 'legacy/state/swap/TradeGp' import { getInputReceiveAmountInfo, getOutputReceiveAmountInfo } from './tradeReceiveAmount' diff --git a/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.tsx b/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.tsx index 2ea808af17..aa2627c132 100644 --- a/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.tsx +++ b/apps/cowswap-frontend/src/modules/swap/helpers/tradeReceiveAmount.tsx @@ -1,11 +1,10 @@ import { ReactNode } from 'react' +import { TokenAmount, TokenAmountProps } from '@cowprotocol/ui' import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' import TradeGp from 'legacy/state/swap/TradeGp' -import { TokenAmount, TokenAmountProps } from 'common/pure/TokenAmount' - export interface ReceiveAmountInfo { type: 'from' | 'to' amountBeforeFees: ReactNode diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts index 45f6e06254..a1369547a6 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useBaseSafeBundleFlowContext.ts @@ -1,12 +1,11 @@ +import { useGP2SettlementContract } from '@cowprotocol/common-hooks' import { OrderKind } from '@cowprotocol/cow-sdk' +import { useSafeAppsSdk } from '@cowprotocol/wallet' import { TradeType } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' -import { useGP2SettlementContract } from 'legacy/hooks/useContract' - import { getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext' import { BaseSafeFlowContext } from 'modules/swap/services/types' -import { useSafeAppsSdk } from 'modules/wallet/web3-react/hooks/useSafeAppsSdk' import { useTradeSpenderAddress } from 'common/hooks/useTradeSpenderAddress' diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts index 5c6226a6e0..088ad2711b 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useCheckEthFlowOrderExists.ts @@ -1,8 +1,8 @@ import { useAtomValue } from 'jotai' import { useCallback } from 'react' -import { ZERO_ADDRESS } from 'legacy/constants/misc' -import { useEthFlowContract } from 'legacy/hooks/useContract' +import { ZERO_ADDRESS } from '@cowprotocol/common-const' +import { useEthFlowContract } from '@cowprotocol/common-hooks' import { ethFlowInFlightOrderIdsAtom } from '../state/EthFlow/ethFlowInFlightOrderIdsAtom' diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts index 29fdcaaa2a..7cd8122b69 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useEthFlowContext.ts @@ -1,9 +1,9 @@ import { useSetAtom } from 'jotai' +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' +import { useEthFlowContract } from '@cowprotocol/common-hooks' import { OrderKind } from '@cowprotocol/cow-sdk' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' -import { useEthFlowContract } from 'legacy/hooks/useContract' import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' import { FlowType, getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext' diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts index ac199e0902..5b4f2fd8e0 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useFlowContext.ts @@ -1,5 +1,10 @@ +import { Erc20, Weth } from '@cowprotocol/abis' +import { GpEther as ETHER, NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' +import { useTokenContract, useWETHContract } from '@cowprotocol/common-hooks' +import { calculateValidTo, getAddress } from '@cowprotocol/common-utils' import { OrderClass, OrderKind } from '@cowprotocol/cow-sdk' -import { Erc20, Weth } from '@cowswap/abis' +import { useENSAddress } from '@cowprotocol/ens' +import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' import { Web3Provider } from '@ethersproject/providers' import { SafeInfoResponse } from '@safe-global/api-kit' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' @@ -7,14 +12,9 @@ import { useWeb3React } from '@web3-react/core' import { useDispatch } from 'react-redux' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' -import { GpEther as ETHER } from 'legacy/constants/tokens' -import { useTokenContract, useWETHContract } from 'legacy/hooks/useContract' -import useENSAddress from 'legacy/hooks/useENSAddress' import { AppDispatch } from 'legacy/state' import { useCloseModals } from 'legacy/state/application/hooks' import { AddOrderCallback, useAddPendingOrder } from 'legacy/state/orders/hooks' -import { useDerivedSwapInfo, useSwapState } from 'legacy/state/swap/hooks' import TradeGp from 'legacy/state/swap/TradeGp' import { useUserTransactionTTL } from 'legacy/state/user/hooks' import { computeSlippageAdjustedAmounts } from 'legacy/utils/prices' @@ -27,12 +27,9 @@ import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow' import { SwapConfirmManager, useSwapConfirmManager } from 'modules/swap/hooks/useSwapConfirmManager' import { BaseFlowContext } from 'modules/swap/services/types' import { SwapFlowAnalyticsContext } from 'modules/trade/utils/analytics' -import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from 'modules/wallet' - -import { getAddress } from 'utils/getAddress' -import { calculateValidTo } from 'utils/time' import { useIsSafeEthFlow } from './useIsSafeEthFlow' +import { useDerivedSwapInfo, useSwapState } from './useSwapState' const _computeInputAmountForSignature = (params: { input: CurrencyAmount diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.test.tsx b/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.test.tsx index cd751a26de..e8c23f5bfb 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.test.tsx +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.test.tsx @@ -1,8 +1,7 @@ import { renderHook } from '@testing-library/react-hooks' import { PriceImpact } from 'legacy/hooks/usePriceImpact' -import { Field } from 'legacy/state/swap/actions' -import { useSwapActionHandlers } from 'legacy/state/swap/hooks' +import { Field } from 'legacy/state/types' import { useSafeBundleApprovalFlowContext } from 'modules/swap/hooks/useSafeBundleApprovalFlowContext' import { ethFlow } from 'modules/swap/services/ethFlow' @@ -15,17 +14,18 @@ import { useEthFlowContext } from './useEthFlowContext' import { useHandleSwap } from './useHandleSwap' import { useSafeBundleEthFlowContext } from './useSafeBundleEthFlowContext' import { useSwapFlowContext } from './useSwapFlowContext' +import { useSwapActionHandlers } from './useSwapState' +jest.mock('./useSwapState') jest.mock('./useSwapFlowContext') jest.mock('./useEthFlowContext') jest.mock('./useSafeBundleApprovalFlowContext') jest.mock('./useSafeBundleEthFlowContext') -jest.mock('legacy/state/swap/hooks') jest.mock('modules/swap/services/swapFlow') jest.mock('modules/swap/services/ethFlow') jest.mock('modules/swap/services/safeBundleFlow') jest.mock('modules/twap/state/twapOrdersListAtom', () => ({})) -jest.mock('legacy/components/analytics/hooks/useAnalyticsReporter.ts') +jest.mock('common/hooks/useAnalyticsReporter') const mockUseSwapActionHandlers = useSwapActionHandlers as jest.MockedFunction const mockSwapFlow = swapFlow as jest.MockedFunction diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.ts index 7ecfe2c12e..20dc460162 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useHandleSwap.ts @@ -1,8 +1,7 @@ import { useCallback } from 'react' import { PriceImpact } from 'legacy/hooks/usePriceImpact' -import { Field } from 'legacy/state/swap/actions' -import { useSwapActionHandlers } from 'legacy/state/swap/hooks' +import { Field } from 'legacy/state/types' import { useSafeBundleApprovalFlowContext } from 'modules/swap/hooks/useSafeBundleApprovalFlowContext' import { ethFlow } from 'modules/swap/services/ethFlow' @@ -15,6 +14,7 @@ import { useConfirmPriceImpactWithoutFee } from 'common/hooks/useConfirmPriceImp import { useEthFlowContext } from './useEthFlowContext' import { useSafeBundleEthFlowContext } from './useSafeBundleEthFlowContext' import { useSwapFlowContext } from './useSwapFlowContext' +import { useSwapActionHandlers } from './useSwapState' export function useHandleSwap(priceImpactParams: PriceImpact): () => Promise { const swapFlowContext = useSwapFlowContext() diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useIsEoaEthFlow.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useIsEoaEthFlow.ts index 3ee54396d4..5d2a630fe7 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useIsEoaEthFlow.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useIsEoaEthFlow.ts @@ -1,6 +1,6 @@ -import { getEthFlowEnabled } from 'modules/swap/helpers/getEthFlowEnabled' +import { useIsSmartContractWallet } from '@cowprotocol/wallet' -import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet' +import { getEthFlowEnabled } from 'modules/swap/helpers/getEthFlowEnabled' import { useIsSwapEth } from './useIsSwapEth' diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts index 7a9d6428ef..b1badd3a31 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useIsSafeEthFlow.ts @@ -1,4 +1,4 @@ -import { useIsBundlingSupported } from 'modules/wallet' +import { useIsBundlingSupported } from '@cowprotocol/wallet' import { useIsSwapEth } from './useIsSwapEth' diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts index 5e6425be86..7fc8ee6a35 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleApprovalFlowContext.ts @@ -1,4 +1,4 @@ -import { useTokenContract } from 'legacy/hooks/useContract' +import { useTokenContract } from '@cowprotocol/common-hooks' import { FlowType } from 'modules/swap/hooks/useFlowContext' import { SafeBundleApprovalFlowContext } from 'modules/swap/services/types' diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleEthFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleEthFlowContext.ts index e946713168..65ac47fc2b 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleEthFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSafeBundleEthFlowContext.ts @@ -1,4 +1,4 @@ -import { useWETHContract } from 'legacy/hooks/useContract' +import { useWETHContract } from '@cowprotocol/common-hooks' import { FlowType } from 'modules/swap/hooks/useFlowContext' import { SafeBundleEthFlowContext } from 'modules/swap/services/types' diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSetupSwapAmountsFromUrl.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSetupSwapAmountsFromUrl.ts index 6e2f09e5d7..a3cb22aa90 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSetupSwapAmountsFromUrl.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSetupSwapAmountsFromUrl.ts @@ -1,13 +1,14 @@ import { useCallback, useLayoutEffect, useMemo } from 'react' +import { getIntOrFloat } from '@cowprotocol/common-utils' + import { useLocation, useNavigate } from 'react-router-dom' -import { Field } from 'legacy/state/swap/actions' -import { useSwapActionHandlers } from 'legacy/state/swap/hooks' +import { Field } from 'legacy/state/types' import { TRADE_URL_BUY_AMOUNT_KEY, TRADE_URL_SELL_AMOUNT_KEY } from 'modules/trade/const/tradeUrl' -import { getIntOrFloat } from 'utils/getIntOrFloat' +import { useSwapActionHandlers } from './useSwapState' /** * Parse sell/buy amount from URL and apply to Swap widget diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts index 68688e3968..0b4939f98b 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts @@ -1,11 +1,17 @@ +import { + useIsSmartContractWallet, + useGnosisSafeInfo, + useWalletDetails, + useWalletInfo, + useIsBundlingSupported, +} from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { useToggleWalletModal } from 'legacy/state/application/hooks' import { useIsTradeUnsupported } from 'legacy/state/lists/hooks' import { useGetQuoteAndStatus, useIsBestQuoteLoading } from 'legacy/state/price/hooks' -import { Field } from 'legacy/state/swap/actions' -import { useDerivedSwapInfo, useSwapActionHandlers } from 'legacy/state/swap/hooks' +import { Field } from 'legacy/state/types' import { useExpertModeManager } from 'legacy/state/user/hooks' import { useIsTokenPermittable } from 'modules/permit' @@ -21,12 +27,11 @@ import { useWrapNativeFlow } from 'modules/trade' import { useIsNativeIn } from 'modules/trade/hooks/useIsNativeInOrOut' import { useIsWrappedOut } from 'modules/trade/hooks/useIsWrappedInOrOut' import { useWrappedToken } from 'modules/trade/hooks/useWrappedToken' -import { useGnosisSafeInfo, useIsBundlingSupported, useWalletDetails, useWalletInfo } from 'modules/wallet' import { useTradeApproveState } from 'common/containers/TradeApprove/useTradeApproveState' -import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet' import { useSafeBundleEthFlowContext } from './useSafeBundleEthFlowContext' +import { useDerivedSwapInfo, useSwapActionHandlers } from './useSwapState' export interface SwapButtonInput { feeWarningAccepted: boolean diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapCurrenciesAmounts.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapCurrenciesAmounts.ts index 60036372c1..9d0c1e51f3 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapCurrenciesAmounts.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapCurrenciesAmounts.ts @@ -1,12 +1,13 @@ import { useMemo } from 'react' import { ParsedAmounts } from 'legacy/hooks/usePriceImpact/types' -import { Field } from 'legacy/state/swap/actions' -import { useSwapState } from 'legacy/state/swap/hooks' -import { useDerivedSwapInfo } from 'legacy/state/swap/hooks' +import { Field } from 'legacy/state/types' import { useSafeMemoObject } from 'common/hooks/useSafeMemo' +import { useSwapState } from './useSwapState' +import { useDerivedSwapInfo } from './useSwapState' + export function useSwapCurrenciesAmounts(): ParsedAmounts { const { independentField } = useSwapState() const { v2Trade: trade, parsedAmount } = useDerivedSwapInfo() diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts index 44bf0aad89..7c88f9d00b 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts @@ -1,9 +1,8 @@ +import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' +import { useGP2SettlementContract } from '@cowprotocol/common-hooks' import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { TradeType } from '@uniswap/sdk-core' -import { GP_VAULT_RELAYER } from 'legacy/constants' -import { useGP2SettlementContract } from 'legacy/hooks/useContract' - import { useIsTokenPermittable } from 'modules/permit' import { FlowType, getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext' import { SwapFlowContext } from 'modules/swap/services/types' diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapRawState.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapRawState.ts index 481307e5d8..bab6dc5cdb 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapRawState.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapRawState.ts @@ -2,10 +2,11 @@ import { useCallback } from 'react' import { useAppDispatch } from 'legacy/state/hooks' import { replaceOnlyTradeRawState, ReplaceOnlyTradeRawStatePayload } from 'legacy/state/swap/actions' -import { useSwapState } from 'legacy/state/swap/hooks' import { ExtendedTradeRawState, TradeRawState } from 'modules/trade/types/TradeRawState' +import { useSwapState } from './useSwapState' + export function useSwapRawState(): TradeRawState { const swapState = useSwapState() diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapSlippage.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapSlippage.ts index bbb7308b06..1ccd9f92e4 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapSlippage.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapSlippage.ts @@ -1,6 +1,6 @@ +import { INITIAL_ALLOWED_SLIPPAGE_PERCENT } from '@cowprotocol/common-const' import { Percent } from '@uniswap/sdk-core' -import { INITIAL_ALLOWED_SLIPPAGE_PERCENT } from 'legacy/constants' import { useUserSlippageToleranceWithDefault } from 'legacy/state/user/hooks' export function useSwapSlippage(): Percent { diff --git a/apps/cowswap-frontend/src/legacy/state/swap/hooks.test.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.test.ts similarity index 95% rename from apps/cowswap-frontend/src/legacy/state/swap/hooks.test.ts rename to apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.test.ts index 04ac6376f1..9dbd371abb 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/hooks.test.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.test.ts @@ -1,9 +1,9 @@ import { parse } from 'qs' -import { Field } from './actions' -import { queryParametersToSwapState } from './utils' +import { queryParametersToSwapState } from 'legacy/state/swap/utils' +import { Field } from 'legacy/state/types' -jest.mock('legacy/components/analytics/hooks/useAnalyticsReporter.ts') +jest.mock('common/hooks/useAnalyticsReporter') describe('hooks', () => { describe('#queryParametersToSwapState', () => { diff --git a/apps/cowswap-frontend/src/legacy/state/swap/hooks.tsx b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx similarity index 95% rename from apps/cowswap-frontend/src/legacy/state/swap/hooks.tsx rename to apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx index 835cf5f5c7..c0de1c1112 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/hooks.tsx +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapState.tsx @@ -1,38 +1,36 @@ import { useCallback, useEffect, useMemo, useState } from 'react' +import { changeSwapAmountAnalytics, switchTokensAnalytics } from '@cowprotocol/analytics' +import { FEE_SIZE_THRESHOLD } from '@cowprotocol/common-const' +import { formatSymbol, isAddress, tryParseCurrencyAmount } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useENS } from '@cowprotocol/ens' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { t } from '@lingui/macro' -import { changeSwapAmountAnalytics, switchTokensAnalytics } from 'legacy/components/analytics' -import { FEE_SIZE_THRESHOLD } from 'legacy/constants' import { useCurrency } from 'legacy/hooks/Tokens' -import useENS from 'legacy/hooks/useENS' import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { AppState } from 'legacy/state' import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' import { useGetQuoteAndStatus, useQuote } from 'legacy/state/price/hooks' +import { setRecipient, switchCurrencies, typeInput } from 'legacy/state/swap/actions' import { stringToCurrency, useTradeExactInWithFee, useTradeExactOutWithFee } from 'legacy/state/swap/extension' import TradeGp from 'legacy/state/swap/TradeGp' import { isWrappingTrade } from 'legacy/state/swap/utils' +import { Field } from 'legacy/state/types' import { useIsExpertMode } from 'legacy/state/user/hooks' -import { isAddress } from 'legacy/utils' -import { registerOnWindow } from 'legacy/utils/misc' -import { useSwapSlippage } from 'modules/swap/hooks/useSwapSlippage' import { useCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalance' import { useNavigateOnCurrencySelection } from 'modules/trade/hooks/useNavigateOnCurrencySelection' import { useTradeNavigate } from 'modules/trade/hooks/useTradeNavigate' -import { useWalletInfo } from 'modules/wallet' import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' import { useTokenBySymbolOrAddress } from 'common/hooks/useTokenBySymbolOrAddress' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' -import { formatSymbol } from 'utils/format' -import { Field, setRecipient, switchCurrencies, typeInput } from './actions' +import { useSwapSlippage } from './useSwapSlippage' export const BAD_RECIPIENT_ADDRESSES: { [address: string]: true } = { '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f': true, // v2 factory @@ -282,9 +280,6 @@ export function useDerivedSwapInfo(): DerivedSwapInfo { // TODO: rename v2Trade to just "trade" we dont have versions const v2Trade = isExactIn ? bestTradeExactIn : bestTradeExactOut - registerOnWindow({ trade: v2Trade }) - // -- MOD -- - const currencyBalances = useMemo( () => ({ [Field.INPUT]: relevantTokenBalances[0], diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useTradePricesUpdate.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useTradePricesUpdate.ts index 7d809f81e8..a171af0670 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useTradePricesUpdate.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useTradePricesUpdate.ts @@ -1,8 +1,12 @@ import { useMemo } from 'react' -import { LONG_LOAD_THRESHOLD, SHORT_LOAD_THRESHOLD } from 'legacy/constants' -import useLoadingWithTimeout from 'legacy/hooks/useLoadingWithTimeout' -import { useIsBestQuoteLoading, useIsQuoteLoading, useIsQuoteRefreshing } from 'legacy/state/price/hooks' +import { LONG_LOAD_THRESHOLD, SHORT_LOAD_THRESHOLD } from '@cowprotocol/common-const' +import { useLoadingWithTimeout } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' + +import { useGetQuoteAndStatus, useIsBestQuoteLoading, useIsQuoteLoading } from 'legacy/state/price/hooks' + +import { useSwapState } from './useSwapState' export function useTradePricesUpdate(): boolean { const isRefreshingQuote = useIsQuoteRefreshing() @@ -14,3 +18,12 @@ export function useTradePricesUpdate(): boolean { return useMemo(() => showCowLoader || showQuoteLoader, [showCowLoader, showQuoteLoader]) } + +function useIsQuoteRefreshing(): boolean { + const { chainId } = useWalletInfo() + const { + INPUT: { currencyId }, + } = useSwapState() + const { isRefreshingQuote } = useGetQuoteAndStatus({ token: currencyId, chainId }) + return isRefreshingQuote +} diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.cosmos.tsx index 9d534210a3..4745047b58 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.cosmos.tsx @@ -1,8 +1,7 @@ +import { GpEther } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Token } from '@uniswap/sdk-core' -import { GpEther } from 'legacy/constants/tokens' - import { EthFlowBannerContent, EthFlowBannerContentProps } from '.' const defaultProps: EthFlowBannerContentProps = { diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.tsx index b590076c12..d972e7937d 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/index.tsx @@ -1,13 +1,12 @@ +import savingsIcon from '@cowprotocol/assets/cow-swap/savings.svg' +import { MINIMUM_ETH_FLOW_SLIPPAGE, PERCENTAGE_PRECISION } from '@cowprotocol/common-const' +import { ButtonPrimary } from '@cowprotocol/ui' import { Currency, Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { ChevronDown, ChevronUp } from 'react-feather' import SVG from 'react-inlinesvg' -import savingsIcon from 'legacy/assets/cow-swap/savings.svg' -import { ButtonPrimary } from 'legacy/components/Button' -import { MINIMUM_ETH_FLOW_SLIPPAGE, PERCENTAGE_PRECISION } from 'legacy/constants' - import { EthFlowBannerCallbacks } from 'modules/swap/containers/EthFlow/EthFlowBanner' import * as styledEl from './styleds' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts index b6c635fe47..f96c023a53 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowBanner/styleds.ts @@ -1,8 +1,8 @@ +import { ButtonPrimary } from '@cowprotocol/ui' + import { transparentize } from 'polished' import styled from 'styled-components/macro' -import { ButtonPrimary } from 'legacy/components/Button' - import { UI } from 'common/constants/theme' export const BannerWrapper = styled.div` diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/ActionButton.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/ActionButton.tsx index 7da6af2af4..9a118dcd73 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/ActionButton.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowModalContent/ActionButton.tsx @@ -1,9 +1,8 @@ +import { Loader, ButtonPrimary } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import styled from 'styled-components/macro' -import { ButtonPrimary } from 'legacy/components/Button' -import Loader from 'legacy/components/Loader' - const ButtonWrapper = styled.div` display: flex; flex-flow: row nowrap; diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step1.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step1.tsx index 1041c2d8aa..3916be3635 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step1.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step1.tsx @@ -1,9 +1,9 @@ import React from 'react' -import Checkmark from 'legacy/assets/cow-swap/checkmark.svg' -import Exclamation from 'legacy/assets/cow-swap/exclamation.svg' -import Send from 'legacy/assets/cow-swap/send.svg' -import X from 'legacy/assets/cow-swap/x.svg' +import Checkmark from '@cowprotocol/assets/cow-swap/checkmark.svg' +import Exclamation from '@cowprotocol/assets/cow-swap/exclamation.svg' +import Send from '@cowprotocol/assets/cow-swap/send.svg' +import X from '@cowprotocol/assets/cow-swap/x.svg' import { EthFlowStepperProps, SmartOrderStatus } from '..' import { StatusIconState } from '../StatusIcon' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step2.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step2.tsx index bf5c8137d0..15a3f843f0 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step2.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step2.tsx @@ -1,9 +1,9 @@ import React, { useMemo } from 'react' -import Checkmark from 'legacy/assets/cow-swap/checkmark.svg' -import Exclamation from 'legacy/assets/cow-swap/exclamation.svg' -import Plus from 'legacy/assets/cow-swap/plus.svg' -import X from 'legacy/assets/cow-swap/x.svg' +import Checkmark from '@cowprotocol/assets/cow-swap/checkmark.svg' +import Exclamation from '@cowprotocol/assets/cow-swap/exclamation.svg' +import Plus from '@cowprotocol/assets/cow-swap/plus.svg' +import X from '@cowprotocol/assets/cow-swap/x.svg' import { EthFlowStepperProps, SmartOrderStatus } from '..' import { ExplorerLinkStyled, Step, StepProps } from '../Step' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx index e89d8047e6..61896a3dec 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/steps/Step3.tsx @@ -1,11 +1,11 @@ import React, { useMemo } from 'react' -import styled from 'styled-components/macro' +import Checkmark from '@cowprotocol/assets/cow-swap/checkmark.svg' +import Exclamation from '@cowprotocol/assets/cow-swap/exclamation.svg' +import Finish from '@cowprotocol/assets/cow-swap/finish.svg' +import Refund from '@cowprotocol/assets/cow-swap/refund.svg' -import Checkmark from 'legacy/assets/cow-swap/checkmark.svg' -import Exclamation from 'legacy/assets/cow-swap/exclamation.svg' -import Finish from 'legacy/assets/cow-swap/finish.svg' -import Refund from 'legacy/assets/cow-swap/refund.svg' +import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.cosmos.tsx index 38b74f34ea..5a4bf5c5aa 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.cosmos.tsx @@ -1,8 +1,7 @@ +import { WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount } from '@uniswap/sdk-core' -import { WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens' - import { WrapCard } from 'modules/swap/pure/EthFlow/WrappingPreview/WrapCard' const WrappedEther = WETH[SupportedChainId.GOERLI] diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.tsx index 7c7acc9a2d..ec22db099c 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/WrappingPreview/WrapCard.tsx @@ -1,16 +1,15 @@ +import { CHAIN_INFO, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount, Currency } from '@uniswap/sdk-core' import styled from 'styled-components/macro' -import { CHAIN_INFO } from 'legacy/constants/chainInfo' -import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo' import * as styledEl from 'modules/swap/pure/EthFlow/WrappingPreview/styled' import { CurrencyLogo } from 'common/pure/CurrencyLogo' -import { TokenAmount } from 'common/pure/TokenAmount' const BackupTokenImg = styled.img.attrs((attrs) => ({ ...attrs, width: '24px' }))` filter: invert(1); diff --git a/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmountInfo/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmountInfo/index.tsx index 25cadad0bd..0618a9552f 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmountInfo/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/ReceiveAmountInfo/index.tsx @@ -1,5 +1,6 @@ import React from 'react' +import { TokenSymbol } from '@cowprotocol/ui' import { Currency } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' @@ -9,8 +10,6 @@ import { BalanceAndSubsidy } from 'legacy/hooks/useCowBalanceAndSubsidy' import { ReceiveAmountInfo } from 'modules/swap/helpers/tradeReceiveAmount' import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow' -import { TokenSymbol } from 'common/pure/TokenSymbol' - import * as styledEl from './styled' export interface ReceiveAmountInfoTooltipProps { diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.cosmos.tsx index 70882c2d7d..06633ec398 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.cosmos.tsx @@ -1,4 +1,4 @@ -import { MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from 'legacy/constants' +import { MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from '@cowprotocol/common-const' import { RowDeadlineContent, RowDeadlineProps } from '.' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.tsx index 53d298f009..2fd4e68630 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowDeadline/index.tsx @@ -1,8 +1,8 @@ -import { Trans } from '@lingui/macro' +import { INPUT_OUTPUT_EXPLANATION, MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from '@cowprotocol/common-const' +import { RowFixed } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' -import { RowFixed } from 'legacy/components/Row' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' -import { INPUT_OUTPUT_EXPLANATION, MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from 'legacy/constants' +import { Trans } from '@lingui/macro' import { RowSlippageProps } from 'modules/swap/containers/Row/RowSlippage' import { ClickableText } from 'modules/swap/pure/Row/RowSlippageContent' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.cosmos.tsx index eda944b2f3..e843ec7148 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.cosmos.tsx @@ -1,7 +1,7 @@ +import { COW, GNO } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount, TradeType, Price } from '@uniswap/sdk-core' -import { COW, GNO } from 'legacy/constants/tokens' import TradeGp from 'legacy/state/swap/TradeGp' import { RowFeeProps } from 'modules/swap/containers/Row/RowFee' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.tsx index df06abd7ad..37046508e1 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowFeeContent/index.tsx @@ -1,5 +1,5 @@ -import { RowFixed } from 'legacy/components/Row' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' +import { RowFixed } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' import { StyledRowBetween, TextWrapper } from 'modules/swap/pure/Row/styled' import { RowStyleProps, RowWithShowHelpersProps } from 'modules/swap/pure/Row/types' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.cosmos.tsx index 1e7b790d32..bb9e9357ed 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.cosmos.tsx @@ -1,7 +1,7 @@ +import { COW, GNO } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount, TradeType, Price, Percent } from '@uniswap/sdk-core' -import { COW, GNO } from 'legacy/constants/tokens' import TradeGp from 'legacy/state/swap/TradeGp' import { RowReceivedAfterSlippageProps } from 'modules/swap/containers/Row/RowReceivedAfterSlippage' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.tsx index d1d772eab2..a3d6f5a7f9 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowReceivedAfterSlippageContent/index.tsx @@ -1,17 +1,14 @@ +import { getMinimumReceivedTooltip } from '@cowprotocol/common-utils' +import { TokenAmount, RowFixed } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' import { CurrencyAmount, Currency, TradeType } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' -import { RowFixed } from 'legacy/components/Row' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' -import { getMinimumReceivedTooltip } from 'legacy/utils/tooltips' - import { RowReceivedAfterSlippageProps } from 'modules/swap/containers/Row/RowReceivedAfterSlippage' import { RowStyleProps } from 'modules/swap/pure/Row/types' import { StyledInfoIcon } from 'modules/swap/pure/styled' -import { TokenAmount } from 'common/pure/TokenAmount' - import { StyledRowBetween, TextWrapper } from '../styled' export interface RowReceivedAfterSlippageContentProps extends RowReceivedAfterSlippageProps { diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowSlippageContent/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowSlippageContent/index.tsx index f3245de41e..cae8d10647 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/Row/RowSlippageContent/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/RowSlippageContent/index.tsx @@ -1,10 +1,10 @@ +import { INPUT_OUTPUT_EXPLANATION, MINIMUM_ETH_FLOW_SLIPPAGE, PERCENTAGE_PRECISION } from '@cowprotocol/common-const' +import { RowFixed } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import styled from 'styled-components/macro' -import { RowFixed } from 'legacy/components/Row' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' -import { INPUT_OUTPUT_EXPLANATION, MINIMUM_ETH_FLOW_SLIPPAGE, PERCENTAGE_PRECISION } from 'legacy/constants' - import { RowSlippageProps } from 'modules/swap/containers/Row/RowSlippage' import { StyledRowBetween, TextWrapper } from 'modules/swap/pure/Row/styled' import { RowStyleProps } from 'modules/swap/pure/Row/types' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts b/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts index cdebb05f46..f8fd766a05 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts +++ b/apps/cowswap-frontend/src/modules/swap/pure/Row/styled.ts @@ -1,10 +1,10 @@ +import { RowBetween, RowFixed } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' + import { transparentize } from 'polished' import { Text } from 'rebass' import styled from 'styled-components/macro' -import { RowBetween, RowFixed } from 'legacy/components/Row' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' - import { UI } from 'common/constants/theme' import { RowStyleProps } from './types' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/SwapButton/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/SwapButton/index.tsx index 7720b3b6d0..1436d521a8 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/SwapButton/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/SwapButton/index.tsx @@ -1,5 +1,4 @@ -import { ButtonError } from 'legacy/components/Button' -import { ButtonSize } from 'legacy/theme/enum' +import { ButtonSize, ButtonError } from '@cowprotocol/ui' export interface SwapButtonProps { disabled: boolean diff --git a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.cosmos.tsx index 1ac4344f6a..e38c510c54 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.cosmos.tsx @@ -1,9 +1,9 @@ +import { WETH_GOERLI } from '@cowprotocol/common-const' import { CurrencyAmount } from '@uniswap/sdk-core' import { useSelect } from 'react-cosmos/client' -import { Field } from 'legacy/state/swap/actions' -import { WETH_GOERLI } from 'legacy/utils/goerli/constants' +import { Field } from 'legacy/state/types' import { SwapButtonState } from 'modules/swap/helpers/getSwapButtonState' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx index a225e29457..c1829a6e1b 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx @@ -1,26 +1,23 @@ import React, { ReactNode } from 'react' +import { GpEther } from '@cowprotocol/common-const' +import { genericPropsChecker } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { ButtonSize, TokenSymbol, ButtonError, ButtonPrimary, AutoRow } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { Text } from 'rebass' -import { ButtonError, ButtonPrimary } from 'legacy/components/Button' import { GreyCard } from 'legacy/components/Card' import { AutoColumn } from 'legacy/components/Column' -import { AutoRow } from 'legacy/components/Row' -import { GpEther } from 'legacy/constants/tokens' import { WrapUnwrapCallback } from 'legacy/hooks/useWrapCallback' -import { Field } from 'legacy/state/swap/actions' -import { ButtonSize } from 'legacy/theme/enum' +import { Field } from 'legacy/state/types' import { EthFlowBanner } from 'modules/swap/containers/EthFlow/EthFlowBanner' import { SwapButtonState } from 'modules/swap/helpers/getSwapButtonState' import { TradeApproveButton } from 'common/containers/TradeApprove/TradeApproveButton' -import { TokenSymbol } from 'common/pure/TokenSymbol' -import { genericPropsChecker } from 'utils/genericPropsChecker' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/styled.tsx index b650ca0ec7..67b300bd11 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/styled.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/styled.tsx @@ -1,8 +1,6 @@ -import { Text } from 'rebass' +import { ButtonSize, ButtonError, RowBetween } from '@cowprotocol/ui' -import { ButtonError } from 'legacy/components/Button' -import { RowBetween } from 'legacy/components/Row' -import { ButtonSize } from 'legacy/theme/enum' +import { Text } from 'rebass' import { TradeLoadingButton } from 'common/pure/TradeLoadingButton' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.cosmos.tsx index aa549df0a8..bbf5431c70 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.cosmos.tsx @@ -1,7 +1,7 @@ +import { COW, GNO } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount, TradeType, Price, Percent } from '@uniswap/sdk-core' -import { COW, GNO } from 'legacy/constants/tokens' import TradeGp from 'legacy/state/swap/TradeGp' import { TradeRates, TradeRatesProps } from 'modules/swap/pure/TradeRates/index' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.tsx index efc3ae3ce3..7a29e549f0 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/TradeRates/index.tsx @@ -1,5 +1,6 @@ import React from 'react' +import { genericPropsChecker } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import TradeGp from 'legacy/state/swap/TradeGp' @@ -8,7 +9,6 @@ import { RowDeadline } from 'modules/swap/containers/Row/RowDeadline' import { TradeBasicDetails } from 'modules/swap/containers/TradeBasicDetails' import { RateInfoParams } from 'common/pure/RateInfo' -import { genericPropsChecker } from 'utils/genericPropsChecker' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/TradeSummary/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/TradeSummary/index.cosmos.tsx index 2569881d99..e6029d9b64 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/TradeSummary/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/TradeSummary/index.cosmos.tsx @@ -1,7 +1,7 @@ +import { COW, GNO } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount, TradeType, Price, Percent } from '@uniswap/sdk-core' -import { COW, GNO } from 'legacy/constants/tokens' import TradeGp from 'legacy/state/swap/TradeGp' import { TradeSummaryProps } from 'modules/swap/containers/TradeSummary' diff --git a/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx index 5c7609a74e..1c5c48b49a 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/styled.tsx @@ -1,9 +1,9 @@ +import { RowBetween } from '@cowprotocol/ui' + import { transparentize } from 'polished' import { Info } from 'react-feather' import styled from 'styled-components/macro' -import { RowBetween } from 'legacy/components/Row' - import { UI } from 'common/constants/theme' export const LowerSectionWrapper = styled(RowBetween).attrs((props) => ({ diff --git a/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx b/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx index 87d879fb64..f7720bd985 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/warnings.tsx @@ -1,5 +1,6 @@ import React from 'react' +import { genericPropsChecker } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' @@ -14,7 +15,6 @@ import { TradeUrlParams } from 'modules/trade/types/TradeRawState' import { BundleTxApprovalBanner, BundleTxSafeWcBanner, BundleTxWrapBanner } from 'common/pure/InlineBanner/banners' import { ZeroApprovalWarning } from 'common/pure/ZeroApprovalWarning' -import { genericPropsChecker } from 'utils/genericPropsChecker' import { TwapSuggestionBanner } from './banners/TwapSuggestionBanner' diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/mocks.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/mocks.ts index fcb7ba2530..669903f979 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/mocks.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/mocks.ts @@ -1,8 +1,7 @@ +import { nativeOnChain, WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount } from '@uniswap/sdk-core' -import { nativeOnChain, WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens' - import { EthFlowActions } from 'modules/swap/containers/EthFlow/hooks/useEthFlowActions' import { EthFlowModalContentProps } from 'modules/swap/pure/EthFlow/EthFlowModalContent' import { BalanceChecks } from 'modules/swap/pure/EthFlow/EthFlowModalContent/EthFlowModalTopContent' diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts index c8e71b4c9b..66e05b9d5c 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/calculateUniqueOrderId.ts @@ -1,15 +1,14 @@ +import { CoWSwapEthFlow } from '@cowprotocol/abis' +import { WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' +import { MAX_VALID_TO_EPOCH } from '@cowprotocol/common-utils' import type { Order } from '@cowprotocol/contracts' import { OrderSigningUtils } from '@cowprotocol/cow-sdk' -import { CoWSwapEthFlow } from '@cowswap/abis' import { CurrencyAmount } from '@uniswap/sdk-core' -import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' import { getSignOrderParams, PostOrderParams } from 'legacy/utils/trade' import { logTradeFlow } from 'modules/trade/utils/logger' -import { MAX_VALID_TO_EPOCH } from 'utils/time' - import { EthFlowOrderExistsCallback } from '../../../hooks/useCheckEthFlowOrderExists' export interface UniqueOrderIdResult { diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/signEthFlowOrderStep.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/signEthFlowOrderStep.ts index 1d8f6fa53a..2f905eff00 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/signEthFlowOrderStep.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/steps/signEthFlowOrderStep.ts @@ -1,10 +1,10 @@ +import { CoWSwapEthFlow } from '@cowprotocol/abis' +import { calculateGasMargin } from '@cowprotocol/common-utils' import { OrderClass, UnsignedOrder } from '@cowprotocol/cow-sdk' -import { CoWSwapEthFlow } from '@cowswap/abis' import { ContractTransaction } from '@ethersproject/contracts' import { NativeCurrency } from '@uniswap/sdk-core' import { Order } from 'legacy/state/orders/actions' -import { calculateGasMargin } from 'legacy/utils/calculateGasMargin' import { getSignOrderParams, mapUnsignedOrderToOrder, PostOrderParams } from 'legacy/utils/trade' import { ETHFLOW_GAS_LIMIT_DEFAULT } from 'modules/swap/services/ethFlow/const' diff --git a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/transactionsMocks.ts b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/transactionsMocks.ts index ba49c9e096..aeac0d9705 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/ethFlow/transactionsMocks.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/ethFlow/transactionsMocks.ts @@ -1,4 +1,4 @@ -import store from 'legacy/state' +import { cowSwapStore } from 'legacy/state' import { addTransaction, finalizeTransaction } from 'legacy/state/enhancedTransactions/actions' import { HashType } from 'legacy/state/enhancedTransactions/reducer' @@ -12,7 +12,7 @@ export const ApproveErrorTxHashMock = '0x138b032570b443508a0a102f1d15949401acf2b export function mockEthFlowPendingTxs() { // Wrap transactions - store.dispatch( + cowSwapStore.dispatch( addTransaction({ hash: WrapPendingTxHashMock, hashType: HashType.ETHEREUM_TX, @@ -22,7 +22,7 @@ export function mockEthFlowPendingTxs() { }) ) - store.dispatch( + cowSwapStore.dispatch( addTransaction({ hash: WrapSuccessfulTxHashMock, hashType: HashType.ETHEREUM_TX, @@ -31,7 +31,7 @@ export function mockEthFlowPendingTxs() { summary: 'Wrap 0.02 WETH to Ether', }) ) - store.dispatch( + cowSwapStore.dispatch( finalizeTransaction({ hash: WrapSuccessfulTxHashMock, chainId: 5, @@ -48,7 +48,7 @@ export function mockEthFlowPendingTxs() { }) ) - store.dispatch( + cowSwapStore.dispatch( addTransaction({ hash: WrapErrorTxHashMock, hashType: HashType.ETHEREUM_TX, @@ -57,7 +57,7 @@ export function mockEthFlowPendingTxs() { summary: 'Wrap 0.02 WETH to Ether', }) ) - store.dispatch( + cowSwapStore.dispatch( finalizeTransaction({ hash: WrapErrorTxHashMock, chainId: 5, @@ -75,7 +75,7 @@ export function mockEthFlowPendingTxs() { ) // Approve transactions - store.dispatch( + cowSwapStore.dispatch( addTransaction({ hash: ApprovePendingTxHashMock, hashType: HashType.ETHEREUM_TX, @@ -89,7 +89,7 @@ export function mockEthFlowPendingTxs() { }) ) - store.dispatch( + cowSwapStore.dispatch( addTransaction({ hash: ApproveSuccessfulTxHashMock, hashType: HashType.ETHEREUM_TX, @@ -102,7 +102,7 @@ export function mockEthFlowPendingTxs() { summary: 'Approve GNO', }) ) - store.dispatch( + cowSwapStore.dispatch( finalizeTransaction({ hash: ApproveSuccessfulTxHashMock, chainId: 5, @@ -119,7 +119,7 @@ export function mockEthFlowPendingTxs() { }) ) - store.dispatch( + cowSwapStore.dispatch( addTransaction({ hash: ApproveErrorTxHashMock, hashType: HashType.ETHEREUM_TX, @@ -132,7 +132,7 @@ export function mockEthFlowPendingTxs() { summary: 'Approve GNO', }) ) - store.dispatch( + cowSwapStore.dispatch( finalizeTransaction({ hash: ApproveErrorTxHashMock, chainId: 5, diff --git a/apps/cowswap-frontend/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts b/apps/cowswap-frontend/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts index abcc1d9245..3186cbc225 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/safeBundleFlow/safeBundleEthFlow.ts @@ -1,4 +1,4 @@ -import { Erc20 } from '@cowswap/abis' +import { Erc20 } from '@cowprotocol/abis' import { MetaTransactionData } from '@safe-global/safe-core-sdk-types' import { Percent } from '@uniswap/sdk-core' diff --git a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/steps/presignOrderStep.ts b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/steps/presignOrderStep.ts index 54e4735871..3705c2df45 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/steps/presignOrderStep.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/steps/presignOrderStep.ts @@ -1,9 +1,8 @@ -import { GPv2Settlement } from '@cowswap/abis' +import { GPv2Settlement } from '@cowprotocol/abis' +import { calculateGasMargin } from '@cowprotocol/common-utils' import { BigNumber } from '@ethersproject/bignumber' import { ContractTransaction } from '@ethersproject/contracts' -import { calculateGasMargin } from 'legacy/utils/calculateGasMargin' - import { logTradeFlow, logTradeFlowError } from 'modules/trade/utils/logger' // Use a 150K gas as a fallback if there's issue calculating the gas estimation (fixes some issues with some nodes failing to calculate gas costs for SC wallets) diff --git a/apps/cowswap-frontend/src/modules/swap/services/types.ts b/apps/cowswap-frontend/src/modules/swap/services/types.ts index 4beacef971..0b09b45fe1 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/types.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/types.ts @@ -1,4 +1,5 @@ -import { CoWSwapEthFlow, Erc20, GPv2Settlement, Weth } from '@cowswap/abis' +import { GPv2Settlement, CoWSwapEthFlow } from '@cowprotocol/abis' +import { Erc20, Weth } from '@cowprotocol/abis' import { Web3Provider } from '@ethersproject/providers' import SafeAppsSDK from '@safe-global/safe-apps-sdk' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' diff --git a/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowDeadlineUpdater.tsx b/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowDeadlineUpdater.tsx index d2990c1112..21ba267bc1 100644 --- a/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowDeadlineUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowDeadlineUpdater.tsx @@ -1,12 +1,12 @@ import { useEffect, useRef } from 'react' -import { MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from 'legacy/constants' +import { MINIMUM_ETH_FLOW_DEADLINE_SECONDS } from '@cowprotocol/common-const' +import { loadJsonFromLocalStorage, setJsonToLocalStorage } from '@cowprotocol/common-utils' + import { useUserTransactionTTL } from 'legacy/state/user/hooks' import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow' -import { loadJsonFromLocalStorage, setJsonToLocalStorage } from 'utils/localStorage' - import { DeadlineSettings } from './types' const LOCAL_STORAGE_KEY = 'UserDeadlineSettings' diff --git a/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowSlippageUpdater.tsx b/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowSlippageUpdater.tsx index 3bdfa52fd9..04abefcc9e 100644 --- a/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowSlippageUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/swap/state/EthFlow/updaters/EthFlowSlippageUpdater.tsx @@ -1,14 +1,13 @@ import { useEffect, useRef } from 'react' +import { MINIMUM_ETH_FLOW_SLIPPAGE } from '@cowprotocol/common-const' +import { loadJsonFromLocalStorage, setJsonToLocalStorage } from '@cowprotocol/common-utils' import { Percent } from '@uniswap/sdk-core' -import { MINIMUM_ETH_FLOW_SLIPPAGE } from 'legacy/constants' import { useSetUserSlippageTolerance, useUserSlippageTolerance } from 'legacy/state/user/hooks' import { useIsEoaEthFlow } from 'modules/swap/hooks/useIsEoaEthFlow' -import { loadJsonFromLocalStorage, setJsonToLocalStorage } from 'utils/localStorage' - import { SerializedSlippage, SerializedSlippageSettings, Slippage, SlippageSettings } from './types' const LOCAL_STORAGE_KEY = 'UserSlippageSettings' diff --git a/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts b/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts index 365c0a9dfd..d8adf46643 100644 --- a/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts +++ b/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts @@ -3,8 +3,7 @@ import { useEffect } from 'react' import { OrderKind } from '@cowprotocol/cow-sdk' -import { Field } from 'legacy/state/swap/actions' -import { useDerivedSwapInfo, useSwapState } from 'legacy/state/swap/hooks' +import { Field } from 'legacy/state/types' import { useTradeUsdAmounts } from 'modules/usdAmount' @@ -12,6 +11,8 @@ import { useSafeMemoObject } from 'common/hooks/useSafeMemo' import { SwapDerivedState, swapDerivedStateAtom } from './swapDerivedStateAtom' +import { useDerivedSwapInfo, useSwapState } from '../hooks/useSwapState' + export function useSwapDerivedState(): SwapDerivedState { return useAtomValue(swapDerivedStateAtom) } diff --git a/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts b/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts index dfc031323e..f2a4d6ad19 100644 --- a/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts +++ b/apps/cowswap-frontend/src/modules/tokens/hooks/useCurrencyBalance.ts @@ -2,17 +2,16 @@ import { useMemo } from 'react' +import { nativeOnChain } from '@cowprotocol/common-const' +import { useInterfaceMulticall } from '@cowprotocol/common-hooks' +import { isAddress } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import JSBI from 'jsbi' -import { nativeOnChain } from 'legacy/constants/tokens' -import { useInterfaceMulticall } from 'legacy/hooks/useContract' -import { isAddress } from 'legacy/utils' - import { useOnchainBalances } from 'modules/tokens' import { TokenAmounts } from 'modules/tokens' -import { useWalletInfo } from 'modules/wallet' import { useSingleContractMultipleData } from 'lib/hooks/multicall' diff --git a/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts b/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts index 5e466ff5bd..e3fb3eeb8e 100644 --- a/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts +++ b/apps/cowswap-frontend/src/modules/tokens/hooks/useEnoughBalance.ts @@ -1,8 +1,7 @@ +import { isEnoughAmount, getAddress } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import useNativeCurrency from 'lib/hooks/useNativeCurrency' -import { getAddress } from 'utils/getAddress' -import { isEnoughAmount } from 'utils/isEnoughAmount' import { useBalancesAndAllowances } from './useBalancesAndAllowances' import { useCurrencyBalances } from './useCurrencyBalance' diff --git a/apps/cowswap-frontend/src/modules/tokens/hooks/useOnchainBalances.ts b/apps/cowswap-frontend/src/modules/tokens/hooks/useOnchainBalances.ts index 97b494440f..d754ce35da 100644 --- a/apps/cowswap-frontend/src/modules/tokens/hooks/useOnchainBalances.ts +++ b/apps/cowswap-frontend/src/modules/tokens/hooks/useOnchainBalances.ts @@ -1,14 +1,13 @@ import { useMemo } from 'react' -import { Erc20Interface, Erc20Abi } from '@cowswap/abis' +import { Erc20Interface, Erc20Abi } from '@cowprotocol/abis' +import { isAddress } from '@cowprotocol/common-utils' import { Interface } from '@ethersproject/abi' import { ListenerOptionsWithGas } from '@uniswap/redux-multicall' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import JSBI from 'jsbi' -import { isAddress } from 'legacy/utils' - import { useMultipleContractSingleData } from 'lib/hooks/multicall' import { BalancesAndAllowances, BalancesAndAllowancesParams, TokenAmounts, TokenAmountsResult } from '../types' diff --git a/apps/cowswap-frontend/src/modules/tokensList/utils/getTokensByAddress.ts b/apps/cowswap-frontend/src/modules/tokensList/utils/getTokensByAddress.ts index 1cde518e0a..3895274499 100644 --- a/apps/cowswap-frontend/src/modules/tokensList/utils/getTokensByAddress.ts +++ b/apps/cowswap-frontend/src/modules/tokensList/utils/getTokensByAddress.ts @@ -1,10 +1,8 @@ +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' +import { doesTokenMatchSymbolOrAddress } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Token } from '@uniswap/sdk-core' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' - -import { doesTokenMatchSymbolOrAddress } from 'utils/doesTokenMatchSymbolOrAddress' - import { TokensByAddress } from '../state/tokensListAtom' export function getTokensByAddress( diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/TradeConfirmPendingContent.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/TradeConfirmPendingContent.tsx index ee8bacce8b..82521c3d65 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/TradeConfirmPendingContent.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/TradeConfirmPendingContent.tsx @@ -1,10 +1,10 @@ import React from 'react' -import { useWalletDisplayedAddress } from 'modules/wallet' +import { TokenAmount } from '@cowprotocol/ui' +import { useWalletDisplayedAddress } from '@cowprotocol/wallet' import { useWalletStatusIcon } from 'common/hooks/useWalletStatusIcon' import { ConfirmationPendingContent } from 'common/pure/ConfirmationPendingContent' -import { TokenAmount } from 'common/pure/TokenAmount' import { TradeAmounts } from 'common/types' const description = `Almost there! \n Follow these steps:` diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.cosmos.tsx index 1729f198aa..6266f269f2 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.cosmos.tsx @@ -2,11 +2,10 @@ import { useSetAtom } from 'jotai' import React, { useEffect } from 'react' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { walletInfoAtom } from '@cowprotocol/wallet' import { inputCurrencyInfoMock, outputCurrencyInfoMock, priceImpactMock } from 'mocks/tradeStateMock' -import { walletInfoAtom } from 'modules/wallet/api/state' - import { TradeAmounts } from 'common/types' import { useTradeConfirmActions } from '../../hooks/useTradeConfirmActions' diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx index 76cad91c7c..82857f2357 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx @@ -1,6 +1,6 @@ import { useAtomValue } from 'jotai' -import { useIsSafeWallet, useWalletInfo } from 'modules/wallet' +import { useIsSafeWallet, useWalletInfo } from '@cowprotocol/wallet' import { CowModal } from 'common/pure/Modal' import { OrderSubmittedContent } from 'common/pure/OrderSubmittedContent' diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetModals.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetModals.tsx index 1bd42bf439..930b93fc6b 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetModals.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetModals.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { useWalletInfo } from 'modules/wallet' +import { useWalletInfo } from '@cowprotocol/wallet' import { ImportTokenModal } from 'common/containers/ImportTokenModal' import { TradeApproveModal } from 'common/containers/TradeApprove' diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx index 2eb4d26b48..bb5f1d3dcc 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx @@ -1,9 +1,11 @@ import { ReactNode, useEffect } from 'react' +import { maxAmountSpend } from '@cowprotocol/common-utils' +import { useIsSafeWallet, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' + import { t } from '@lingui/macro' import { PriceImpact } from 'legacy/hooks/usePriceImpact' -import { maxAmountSpend } from 'legacy/utils/maxAmountSpend' import { TradeWidgetLinks } from 'modules/application/containers/TradeWidgetLinks' import { SetRecipientProps } from 'modules/swap/containers/SetRecipient' @@ -11,7 +13,6 @@ import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap' import { RecipientAddressUpdater } from 'modules/trade/updaters/RecipientAddressUpdater' import { TradeFormValidationUpdater } from 'modules/tradeFormValidation' import { TradeQuoteUpdater } from 'modules/tradeQuote' -import { useIsSafeWallet, useWalletDetails, useWalletInfo } from 'modules/wallet' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' import { useThrottleFn } from 'common/hooks/useThrottleFn' diff --git a/apps/cowswap-frontend/src/modules/trade/containers/WrapNativeModal/index.tsx b/apps/cowswap-frontend/src/modules/trade/containers/WrapNativeModal/index.tsx index 402668a682..cdafbb4479 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/WrapNativeModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/WrapNativeModal/index.tsx @@ -1,13 +1,12 @@ import { useAtom } from 'jotai' import { useCallback } from 'react' -import { useWalletDisplayedAddress } from 'modules/wallet' +import { TokenAmount, TokenSymbol } from '@cowprotocol/ui' +import { useWalletDisplayedAddress } from '@cowprotocol/wallet' import { useWalletStatusIcon } from 'common/hooks/useWalletStatusIcon' import { ConfirmationPendingContent } from 'common/pure/ConfirmationPendingContent' import { CowModal } from 'common/pure/Modal' -import { TokenAmount } from 'common/pure/TokenAmount' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { useDerivedTradeState } from '../../hooks/useDerivedTradeState' import { wrapNativeStateAtom } from '../../state/wrapNativeStateAtom' diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useResetStateWithSymbolDuplication.ts b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useResetStateWithSymbolDuplication.ts index b2267c9076..db2c485178 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useResetStateWithSymbolDuplication.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useResetStateWithSymbolDuplication.ts @@ -1,8 +1,8 @@ import { useEffect } from 'react' -import { t } from '@lingui/macro' +import { useWalletInfo } from '@cowprotocol/wallet' -import { useWalletInfo } from 'modules/wallet' +import { t } from '@lingui/macro' import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol' diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts index 8f16f85ad7..7ada7d4922 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts @@ -1,14 +1,12 @@ import { useEffect, useState } from 'react' +import { usePrevious } from '@cowprotocol/common-hooks' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo, switchChain } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' -import usePrevious from 'legacy/hooks/usePrevious' - import { useTradeNavigate } from 'modules/trade/hooks/useTradeNavigate' import { getDefaultTradeRawState, TradeRawState } from 'modules/trade/types/TradeRawState' -import { useWalletInfo } from 'modules/wallet' -import { switchChain } from 'modules/wallet/web3-react/hooks/switchChain' import { useResetStateWithSymbolDuplication } from './useResetStateWithSymbolDuplication' import { useTradeStateFromUrl } from './useTradeStateFromUrl' diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts index 286bc6e12b..27140cdd8d 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useBuildTradeDerivedState.ts @@ -1,13 +1,14 @@ import { Atom, useAtomValue } from 'jotai' +import { tryParseFractionalAmount } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' + import useCurrencyBalance from 'modules/tokens/hooks/useCurrencyBalance' import { ExtendedTradeRawState } from 'modules/trade/types/TradeRawState' import { useTradeUsdAmounts } from 'modules/usdAmount' -import { useWalletInfo } from 'modules/wallet' import { useSafeMemoObject } from 'common/hooks/useSafeMemo' import { useTokenBySymbolOrAddress } from 'common/hooks/useTokenBySymbolOrAddress' -import { tryParseFractionalAmount } from 'utils/tryParseFractionalAmount' export function useBuildTradeDerivedState(stateAtom: Atom) { const { account } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useDisableNativeTokenSelling.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useDisableNativeTokenSelling.ts index 3c7e8417d6..610faa95ac 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useDisableNativeTokenSelling.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useDisableNativeTokenSelling.ts @@ -1,9 +1,8 @@ import { useEffect } from 'react' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' -import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' - -import { useWalletInfo } from 'modules/wallet' +import { WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' import { useTradeNavigate } from './useTradeNavigate' import { useTradeState } from './useTradeState' diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useIsNativeInOrOut.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useIsNativeInOrOut.ts index 57bf3b6efe..1deb924e48 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useIsNativeInOrOut.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useIsNativeInOrOut.ts @@ -1,8 +1,7 @@ import { useMemo } from 'react' -import { useWalletInfo } from 'modules/wallet' - -import { getIsNativeToken } from 'utils/getIsNativeToken' +import { getIsNativeToken } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { useTradeState } from './useTradeState' diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrapOrUnwrap.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrapOrUnwrap.ts index 1949f6db02..ede54d04b3 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrapOrUnwrap.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrapOrUnwrap.ts @@ -1,9 +1,9 @@ import { useMemo } from 'react' -import { useTradeState } from 'modules/trade/hooks/useTradeState' -import { useWalletInfo } from 'modules/wallet' +import { getIsWrapOrUnwrap } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' -import { getIsWrapOrUnwrap } from 'utils/getIsWrapOrUnwrap' +import { useTradeState } from 'modules/trade/hooks/useTradeState' export function useIsWrapOrUnwrap(): boolean { const { chainId } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrappedInOrOut.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrappedInOrOut.ts index ce62913a0c..ef4a07e9eb 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrappedInOrOut.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useIsWrappedInOrOut.ts @@ -1,12 +1,9 @@ import { useMemo } from 'react' +import { WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' +import { doesTokenMatchSymbolOrAddress } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' - -import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' - -import { useWalletInfo } from 'modules/wallet' - -import { doesTokenMatchSymbolOrAddress } from 'utils/doesTokenMatchSymbolOrAddress' +import { useWalletInfo } from '@cowprotocol/wallet' import { useTradeState } from './useTradeState' diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts index 2616b476ad..1df5d47bd7 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useNavigateOnCurrencySelection.ts @@ -1,12 +1,12 @@ import { useCallback } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, Token } from '@uniswap/sdk-core' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { useTradeNavigate } from 'modules/trade/hooks/useTradeNavigate' import { useTradeState } from 'modules/trade/hooks/useTradeState' -import { useWalletInfo } from 'modules/wallet' import { useAreThereTokensWithSameSymbol } from 'common/hooks/useAreThereTokensWithSameSymbol' diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useOnCurrencySelection.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useOnCurrencySelection.ts index 4d80ea1d35..872793f7a4 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useOnCurrencySelection.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useOnCurrencySelection.ts @@ -1,15 +1,15 @@ import { useSetAtom } from 'jotai' import { useCallback } from 'react' +import { FractionUtils } from '@cowprotocol/common-utils' import { Currency } from '@uniswap/sdk-core' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { updateLimitOrdersRawStateAtom } from 'modules/limitOrders' import { useLimitOrdersDerivedState } from 'modules/limitOrders/hooks/useLimitOrdersDerivedState' import { useNavigateOnCurrencySelection } from 'modules/trade/hooks/useNavigateOnCurrencySelection' -import { FractionUtils } from 'utils/fractionUtils' import { convertAmountToCurrency } from 'utils/orderUtils/calculateExecutionPrice' export function useOnCurrencySelection(): (field: Field, currency: Currency | null) => void { diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts index a303893490..c46a42d864 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useSwitchTokensPlaces.ts @@ -1,10 +1,8 @@ import { useCallback } from 'react' -import { switchTokensAnalytics } from 'legacy/components/analytics' - -import { useWalletInfo } from 'modules/wallet' - -import { FractionUtils } from 'utils/fractionUtils' +import { switchTokensAnalytics } from '@cowprotocol/analytics' +import { FractionUtils } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { useDerivedTradeState } from './useDerivedTradeState' import { useIsWrapOrUnwrap } from './useIsWrapOrUnwrap' diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useUpdateCurrencyAmount.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useUpdateCurrencyAmount.ts index eda576ba17..c8b6d98cd6 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useUpdateCurrencyAmount.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useUpdateCurrencyAmount.ts @@ -1,14 +1,12 @@ import { useCallback } from 'react' +import { FractionUtils, tryParseCurrencyAmount } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { useTradeState } from 'modules/trade/hooks/useTradeState' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' -import { FractionUtils } from 'utils/fractionUtils' - type AmountType = { value: string isTyped: boolean diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useWrapNativeFlow.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useWrapNativeFlow.ts index 09a15df475..620af0c833 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useWrapNativeFlow.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useWrapNativeFlow.ts @@ -1,11 +1,12 @@ import { useSetAtom } from 'jotai' import { useCallback } from 'react' +import { useWETHContract } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { useWETHContract } from 'legacy/hooks/useContract' import { wrapUnwrapCallback, WrapUnwrapCallback, @@ -14,8 +15,6 @@ import { } from 'legacy/hooks/useWrapCallback' import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' -import { useWalletInfo } from 'modules/wallet' - import { useDerivedTradeState } from './useDerivedTradeState' import { useTradeState } from './useTradeState' diff --git a/apps/cowswap-frontend/src/modules/trade/pure/CompatibilityIssuesWarning/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/CompatibilityIssuesWarning/index.tsx index ed91bf1955..c9e417f562 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/CompatibilityIssuesWarning/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/CompatibilityIssuesWarning/index.tsx @@ -1,13 +1,12 @@ import React from 'react' +import { genericPropsChecker } from '@cowprotocol/common-utils' import { Currency } from '@uniswap/sdk-core' import { HashLink } from 'react-router-hash-link' import UnsupportedCurrencyFooter from 'legacy/components/swap/UnsupportedCurrencyFooter' -import { genericPropsChecker } from 'utils/genericPropsChecker' - export interface CompatibilityIssuesWarningProps { currencyIn: Currency currencyOut: Currency diff --git a/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/index.tsx index 7b408b6ff8..e54f111a7e 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/ConfirmDetailsItem/index.tsx @@ -1,9 +1,10 @@ import { ReactNode } from 'react' +import { RowFixed } from '@cowprotocol/ui' + import { CornerDownRight } from 'react-feather' import { InfoIcon } from 'legacy/components/InfoIcon' -import { RowFixed } from 'legacy/components/Row' import { TextWrapper } from 'modules/swap/pure/Row/styled' diff --git a/apps/cowswap-frontend/src/modules/trade/pure/ReviewOrderModalAmountRow/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/ReviewOrderModalAmountRow/index.tsx index b5abb13d58..14fe26e8bf 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/ReviewOrderModalAmountRow/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/ReviewOrderModalAmountRow/index.tsx @@ -1,12 +1,10 @@ import { ReactNode } from 'react' +import { FiatAmount, TokenAmount } from '@cowprotocol/ui' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { FiatAmount } from 'common/pure/FiatAmount' -import { TokenAmount } from 'common/pure/TokenAmount' - import { ConfirmDetailsItem } from '../ConfirmDetailsItem' export type ReviewOrderAmountRowProps = { diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx index 8458312344..9e315575bb 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx @@ -1,11 +1,11 @@ import React, { useCallback, useEffect, useRef, useState } from 'react' +import { ButtonSize, ButtonPrimary } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' -import { ButtonPrimary } from 'legacy/components/Button' import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { CloseIcon } from 'legacy/theme' -import { ButtonSize } from 'legacy/theme/enum' import { CurrencyArrowSeparator } from 'common/pure/CurrencyArrowSeparator' import { CurrencyAmountPreview, CurrencyPreviewInfo } from 'common/pure/CurrencyInputPanel' diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx index cacd356cc6..ac9a5f722b 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx @@ -1,10 +1,10 @@ import { useCallback, useEffect, useState } from 'react' +import carretDown from '@cowprotocol/assets/cow-swap/carret-down.svg' + import BigNumberJs from 'bignumber.js' import SVG from 'react-inlinesvg' -import carretDown from 'legacy/assets/cow-swap/carret-down.svg' - import { TradeWidgetField, TradeWidgetFieldProps } from 'modules/trade/pure/TradeWidgetField' import { ArrowsWrapper, InputWrapper, NumericalInput, Suffix } from './styled' diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeWidgetField/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeWidgetField/index.tsx index 4705d10da8..26e4a3788e 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/TradeWidgetField/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeWidgetField/index.tsx @@ -1,9 +1,10 @@ import React from 'react' +import { renderTooltip } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import QuestionHelper from 'legacy/components/QuestionHelper' -import { renderTooltip } from 'legacy/components/Tooltip' import { Content, ErrorText, TradeWidgetFieldBox, TradeWidgetFieldLabel } from './styled' diff --git a/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx index 0cdc3c2799..9fe3f30b3c 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx @@ -1,8 +1,8 @@ -import SVG from 'react-inlinesvg' +import iconCompleted from '@cowprotocol/assets/cow-swap/check.svg' +import { ButtonPrimary } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' -import iconCompleted from 'legacy/assets/cow-swap/check.svg' -import { ButtonPrimary } from 'legacy/components/Button' -import { ExternalLink } from 'legacy/theme' +import SVG from 'react-inlinesvg' import * as styledEl from './styled' diff --git a/apps/cowswap-frontend/src/modules/trade/types/TradeRawState.ts b/apps/cowswap-frontend/src/modules/trade/types/TradeRawState.ts index bfbd00e7d8..8403f3b0dc 100644 --- a/apps/cowswap-frontend/src/modules/trade/types/TradeRawState.ts +++ b/apps/cowswap-frontend/src/modules/trade/types/TradeRawState.ts @@ -1,7 +1,6 @@ +import { WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const' import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' -import { WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens' - export interface TradeUrlParams { readonly chainId: string | undefined readonly inputCurrencyId: string | undefined diff --git a/apps/cowswap-frontend/src/modules/trade/updaters/RecipientAddressUpdater.tsx b/apps/cowswap-frontend/src/modules/trade/updaters/RecipientAddressUpdater.tsx index 9322be5251..7e46c45981 100644 --- a/apps/cowswap-frontend/src/modules/trade/updaters/RecipientAddressUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/trade/updaters/RecipientAddressUpdater.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react' -import useENSAddress from 'legacy/hooks/useENSAddress' +import { useENSAddress } from '@cowprotocol/ens' import { useTradeState } from '../hooks/useTradeState' diff --git a/apps/cowswap-frontend/src/modules/trade/utils/analytics.ts b/apps/cowswap-frontend/src/modules/trade/utils/analytics.ts index 7ebf50ffe0..f84ebaa76f 100644 --- a/apps/cowswap-frontend/src/modules/trade/utils/analytics.ts +++ b/apps/cowswap-frontend/src/modules/trade/utils/analytics.ts @@ -1,5 +1,5 @@ -import { signTradeAnalytics, tradeAnalytics } from 'legacy/components/analytics' -import { AnalyticsOrderType } from 'legacy/components/analytics/types' +import { signTradeAnalytics, tradeAnalytics } from '@cowprotocol/analytics' +import { AnalyticsOrderType } from '@cowprotocol/analytics' import { USER_SWAP_REJECTED_ERROR } from 'modules/trade/utils/swapErrorHelper' diff --git a/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts b/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts index aeae1e97ae..9e9e4df301 100644 --- a/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts +++ b/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts @@ -1,4 +1,4 @@ -import { getProviderErrorMessage, isRejectRequestProviderError } from 'legacy/utils/misc' +import { getProviderErrorMessage, isRejectRequestProviderError } from '@cowprotocol/common-utils' export const USER_SWAP_REJECTED_ERROR = 'User rejected signing the order' diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useGetTradeFormValidation.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useGetTradeFormValidation.ts index 04c2cb7275..43a1fa6dc3 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useGetTradeFormValidation.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useGetTradeFormValidation.ts @@ -1,6 +1,6 @@ import { useAtomValue } from 'jotai' -import useDebounce from 'legacy/hooks/useDebounce' +import { useDebounce } from '@cowprotocol/common-hooks' import { tradeFormValidationAtom } from '../state/tradeFormValidationAtom' import { TradeFormValidation } from '../types' diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts index f39622e706..c69bfe49d0 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormButtonContext.ts @@ -1,11 +1,12 @@ import { useMemo } from 'react' +import { useWalletDetails } from '@cowprotocol/wallet' + import { useToggleWalletModal } from 'legacy/state/application/hooks' import { useWrapNativeFlow } from 'modules/trade' import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' import { useTradeQuote } from 'modules/tradeQuote' -import { useWalletDetails } from 'modules/wallet' import { TradeFormButtonContext } from '../types' diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts index 674a1d5e62..a558e0c4b2 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts @@ -1,13 +1,14 @@ import { useMemo } from 'react' -import useENSAddress from 'legacy/hooks/useENSAddress' +import { useENSAddress } from '@cowprotocol/ens' +import { useGnosisSafeInfo, useIsBundlingSupported, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' + import { useIsTradeUnsupported } from 'legacy/state/lists/hooks' import { isUnsupportedTokenInQuote } from 'modules/limitOrders/utils/isUnsupportedTokenInQuote' import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap' import { useTradeQuote } from 'modules/tradeQuote' -import { useGnosisSafeInfo, useIsBundlingSupported, useWalletDetails, useWalletInfo } from 'modules/wallet' import { useTradeApproveState } from 'common/containers/TradeApprove' diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx b/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx index fac973ae41..af472af4f5 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx @@ -1,5 +1,7 @@ import React from 'react' +import { TokenSymbol } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import styled from 'styled-components/macro' @@ -7,7 +9,6 @@ import { CompatibilityIssuesWarning } from 'modules/trade/pure/CompatibilityIssu import { GpQuoteErrorCodes } from 'api/gnosisProtocol/errors/QuoteError' import { TradeApproveButton } from 'common/containers/TradeApprove' -import { TokenSymbol } from 'common/pure/TokenSymbol' import { TradeLoadingButton } from 'common/pure/TradeLoadingButton' import { TradeFormButtonContext, TradeFormValidation } from '../../types' diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts index c5eb269c37..c47501c73c 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts @@ -1,7 +1,7 @@ -import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' -import { isAddress } from 'legacy/utils' +import { isFractionFalsy } from '@cowprotocol/common-utils' +import { isAddress } from '@cowprotocol/common-utils' -import { isFractionFalsy } from 'utils/isFractionFalsy' +import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' import { TradeFormValidation, TradeFormValidationContext } from '../types' diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts index 9d297e3d6d..6bd3d9a61e 100644 --- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts +++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useProcessUnsupportedTokenError.ts @@ -1,11 +1,11 @@ import { useCallback } from 'react' -import { useAddGpUnsupportedToken } from 'legacy/state/lists/hooks' +import { getQuoteUnsupportedToken } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' -import { useWalletInfo } from 'modules/wallet' +import { useAddGpUnsupportedToken } from 'legacy/state/lists/hooks' import GpQuoteError from 'api/gnosisProtocol/errors/QuoteError' -import { getQuoteUnsupportedToken } from 'utils/getQuoteUnsupportedToken' export function useProcessUnsupportedTokenError() { const { chainId } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts index 4b0e02eac7..bec2b7f889 100644 --- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts +++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useQuoteParams.ts @@ -1,18 +1,18 @@ import { useMemo } from 'react' +import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' +import { getAddress } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount } from '@uniswap/sdk-core' -import { NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants' +import { LegacyFeeQuoteParams } from 'legacy/state/price/types' import { useAppData } from 'modules/appData' import { useEnoughBalanceAndAllowance } from 'modules/tokens' import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' -import { useWalletInfo } from 'modules/wallet' import { getPriceQuality } from 'api/gnosisProtocol/api' -import { LegacyFeeQuoteParams } from 'api/gnosisProtocol/legacy/types' import { useVerifiedQuotesEnabled } from 'common/hooks/featureFlags/useVerifiedQuotesEnabled' -import { getAddress } from 'utils/getAddress' export function useQuoteParams(amount: string | null): LegacyFeeQuoteParams | undefined { const { chainId, account } = useWalletInfo() diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.test.tsx b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.test.tsx index ec84d265dd..4961fa1015 100644 --- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.test.tsx +++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.test.tsx @@ -1,27 +1,24 @@ import { ReactNode } from 'react' +import { COW, ZERO_ADDRESS } from '@cowprotocol/common-const' +import { WETH_GOERLI } from '@cowprotocol/common-const' +import { WalletInfo, walletInfoAtom } from '@cowprotocol/wallet' import { CurrencyAmount } from '@uniswap/sdk-core' import { renderHook } from '@testing-library/react-hooks' import { orderBookApi } from 'cowSdk' import { JotaiTestProvider, WithMockedWeb3 } from 'test-utils' -import { ZERO_ADDRESS } from 'legacy/constants/misc' -import { COW } from 'legacy/constants/tokens' -import { WETH_GOERLI } from 'legacy/utils/goerli/constants' - import { LimitOrdersDerivedState, limitOrdersDerivedStateAtom } from 'modules/limitOrders/state/limitOrdersRawStateAtom' import * as tokensModule from 'modules/tokens' import { DEFAULT_TRADE_DERIVED_STATE } from 'modules/trade' -import { WalletInfo } from 'modules/wallet' import { useTradeQuotePolling } from './useTradeQuotePolling' -import { walletInfoAtom } from '../../wallet/api/state' import { tradeQuoteParamsAtom } from '../state/tradeQuoteParamsAtom' jest.mock('common/hooks/useShouldZeroApprove/useShouldZeroApprove') -jest.mock('legacy/components/analytics/hooks/useGetMarketDimension') +jest.mock('common/hooks/useGetMarketDimension') const getQuoteMock = jest.spyOn(orderBookApi, 'getQuote') const useEnoughBalanceAndAllowanceMock = jest.spyOn(tokensModule, 'useEnoughBalanceAndAllowance') diff --git a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts index 93bceec339..baf4ce96e2 100644 --- a/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts +++ b/apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuotePolling.ts @@ -1,13 +1,13 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useLayoutEffect, useMemo } from 'react' +import { useDebounce } from '@cowprotocol/common-hooks' +import { onlyResolvesLast } from '@cowprotocol/common-utils' import { OrderQuoteResponse } from '@cowprotocol/cow-sdk' import ms from 'ms.macro' -import useDebounce from 'legacy/hooks/useDebounce' import { useIsUnsupportedTokens } from 'legacy/state/lists/hooks' -import { onlyResolvesLast } from 'legacy/utils/async' import { useUpdateCurrencyAmount } from 'modules/trade/hooks/useUpdateCurrencyAmount' import { updateTradeQuoteAtom } from 'modules/tradeQuote/state/tradeQuoteAtom' diff --git a/apps/cowswap-frontend/src/modules/twap/const.ts b/apps/cowswap-frontend/src/modules/twap/const.ts index 0acd222869..6689eba082 100644 --- a/apps/cowswap-frontend/src/modules/twap/const.ts +++ b/apps/cowswap-frontend/src/modules/twap/const.ts @@ -1,10 +1,9 @@ +import { USDC } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import ms from 'ms.macro' -import { USDC } from 'legacy/constants/tokens' - import { TwapOrderExecutionInfo, TwapOrderStatus } from './types' export const DEFAULT_TWAP_SLIPPAGE = new Percent(10, 100) // 10% diff --git a/apps/cowswap-frontend/src/modules/twap/containers/ActionButtons/index.tsx b/apps/cowswap-frontend/src/modules/twap/containers/ActionButtons/index.tsx index ee126bb1cc..7dce3c832c 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/ActionButtons/index.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/ActionButtons/index.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { twapConversionAnalytics } from 'legacy/components/analytics/events/twapEvents' +import { twapConversionAnalytics } from '@cowprotocol/analytics' import { useTradeConfirmActions } from 'modules/trade' import { TradeFormButtons, TradeFormValidation } from 'modules/tradeFormValidation' diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapConfirmModal/TwapConfirmDetails.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapConfirmModal/TwapConfirmDetails.tsx index bb8c04f232..85d0bc2f78 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapConfirmModal/TwapConfirmDetails.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapConfirmModal/TwapConfirmDetails.tsx @@ -1,14 +1,14 @@ import React from 'react' +import { shortenAddress } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' + import { isAddress } from 'ethers/lib/utils' import styled from 'styled-components/macro' -import { shortenAddress } from 'legacy/utils' - import { useAdvancedOrdersDerivedState } from 'modules/advancedOrders' import { ConfirmDetailsItem } from 'modules/trade/pure/ConfirmDetailsItem' import { ReviewOrderModalAmountRow } from 'modules/trade/pure/ReviewOrderModalAmountRow' -import { useWalletInfo } from 'modules/wallet' import { PartsState } from '../../state/partsStateAtom' import { deadlinePartsDisplay } from '../../utils/deadlinePartsDisplay' diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx index ac50ad1191..a3cd2a9c25 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx @@ -2,12 +2,12 @@ import { useAtomValue } from 'jotai' import { useSetAtom } from 'jotai' import { useCallback } from 'react' -import { modifySafeHandlerAnalytics } from 'legacy/components/analytics/events/twapEvents' +import { modifySafeHandlerAnalytics } from '@cowprotocol/analytics' +import { useIsSafeViaWc, useWalletInfo } from '@cowprotocol/wallet' import { useTradeRouteContext } from 'modules/trade/hooks/useTradeRouteContext' import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning' import { useTradeQuoteFeeFiatAmount } from 'modules/tradeQuote' -import { useIsSafeViaWc, useWalletInfo } from 'modules/wallet' import { useShouldZeroApprove } from 'common/hooks/useShouldZeroApprove' import { BundleTxApprovalBanner } from 'common/pure/InlineBanner/banners' diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx index 3c1f277f4e..586715bfbd 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx @@ -1,6 +1,6 @@ -import styled from 'styled-components/macro' +import { ExternalLink } from '@cowprotocol/ui' -import { ExternalLink } from 'legacy/theme' +import styled from 'styled-components/macro' import { UNSUPPORTED_SAFE_LINK } from 'modules/twap/const' diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SmallPartVolumeWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SmallPartVolumeWarning.tsx index 1d6483ef9f..a72afcfb3b 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SmallPartVolumeWarning.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SmallPartVolumeWarning.tsx @@ -1,7 +1,7 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { TokenAmount } from '@cowprotocol/ui' import { InlineBanner } from 'common/pure/InlineBanner' -import { TokenAmount } from 'common/pure/TokenAmount' import { MINIMUM_PART_SELL_AMOUNT_FIAT } from '../../../const' diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx index 22887727a2..addfd9a348 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx @@ -1,3 +1,4 @@ +import { FiatAmount, TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { NavLink } from 'react-router-dom' @@ -7,9 +8,7 @@ import { TradeUrlParams } from 'modules/trade/types/TradeRawState' import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute' import { Routes } from 'common/constants/routes' -import { FiatAmount } from 'common/pure/FiatAmount' import { InlineBanner } from 'common/pure/InlineBanner' -import { TokenAmount } from 'common/pure/TokenAmount' import { SwapAmountDifference } from '../../../state/swapAmountDifferenceAtom' diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx index 98bcc29203..73da882db0 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx @@ -1,4 +1,4 @@ -import { ExternalLink } from 'legacy/theme' +import { ExternalLink } from '@cowprotocol/ui' import { UNSUPPORTED_WALLET_LINK } from 'modules/twap/const' diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx index 7dbd251409..bfbca0f4ea 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/index.tsx @@ -1,11 +1,9 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useEffect, useState } from 'react' -import { - openAdvancedOrdersTabAnalytics, - twapWalletCompatibilityAnalytics, -} from 'legacy/components/analytics/events/twapEvents' -import { renderTooltip } from 'legacy/components/Tooltip' +import { openAdvancedOrdersTabAnalytics, twapWalletCompatibilityAnalytics } from '@cowprotocol/analytics' +import { renderTooltip } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { useAdvancedOrdersDerivedState, useAdvancedOrdersRawState } from 'modules/advancedOrders' import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap' @@ -14,7 +12,6 @@ import { TradeNumberInput } from 'modules/trade/pure/TradeNumberInput' import { TradeTextBox } from 'modules/trade/pure/TradeTextBox' import { useGetTradeFormValidation } from 'modules/tradeFormValidation' import { TwapFormState } from 'modules/twap/pure/PrimaryActionButton/getTwapFormState' -import { useWalletInfo } from 'modules/wallet' import { usePrice } from 'common/hooks/usePrice' import { useRateInfoParams } from 'common/hooks/useRateInfoParams' diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx index cb4e86ae99..2568b2652f 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx @@ -1,8 +1,8 @@ +import ShieldImage from '@cowprotocol/assets/cow-swap/protection.svg' + import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import ShieldImage from 'legacy/assets/cow-swap/protection.svg' - import { deadlinePartsDisplay } from 'modules/twap/utils/deadlinePartsDisplay' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useAllEmulatedOrders.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useAllEmulatedOrders.ts index f8401d28e8..b02315f559 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useAllEmulatedOrders.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useAllEmulatedOrders.ts @@ -1,12 +1,11 @@ import { useMemo } from 'react' import { OrderClass } from '@cowprotocol/cow-sdk' +import { useIsSafeApp, useWalletInfo } from '@cowprotocol/wallet' import { Order } from 'legacy/state/orders/actions' import { useOrders } from 'legacy/state/orders/hooks' -import { useIsSafeApp, useWalletInfo } from 'modules/wallet' - import { useEmulatedPartOrders } from './useEmulatedPartOrders' import { useEmulatedTwapOrders } from './useEmulatedTwapOrders' import { useTwapOrdersTokens } from './useTwapOrdersTokens' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useCancelTwapOrder.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useCancelTwapOrder.ts index a9ff3801e8..155f6288b0 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useCancelTwapOrder.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useCancelTwapOrder.ts @@ -1,11 +1,12 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useCallback } from 'react' -import { useGP2SettlementContract } from 'legacy/hooks/useContract' +import { useGP2SettlementContract } from '@cowprotocol/common-hooks' +import { useSafeAppsSdk } from '@cowprotocol/wallet' + import { Order } from 'legacy/state/orders/actions' import { useComposableCowContract } from 'modules/advancedOrders/hooks/useComposableCowContract' -import { useSafeAppsSdk } from 'modules/wallet/web3-react/hooks/useSafeAppsSdk' import type { OnChainCancellation } from 'common/hooks/useCancelOrder/onChainCancellation' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts index 28ee879221..72eb4716fb 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts @@ -2,23 +2,22 @@ import { useAtomValue } from 'jotai' import { useSetAtom } from 'jotai' import { useCallback } from 'react' +import { twapConversionAnalytics } from '@cowprotocol/analytics' +import { getCowSoundSend } from '@cowprotocol/common-utils' import { OrderClass, OrderKind } from '@cowprotocol/cow-sdk' +import { useWalletInfo, useSafeAppsSdk } from '@cowprotocol/wallet' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { twapConversionAnalytics } from 'legacy/components/analytics/events/twapEvents' -import store from 'legacy/state' +import { cowSwapStore } from 'legacy/state' import { dispatchPresignedOrderPosted } from 'legacy/state/orders/middleware/updateOrderPopup' -import { getCowSoundSend } from 'legacy/utils/sound' import { getOrderSubmitSummary } from 'legacy/utils/trade' import { updateAdvancedOrdersAtom, useAdvancedOrdersDerivedState } from 'modules/advancedOrders' import { useAppData, useUploadAppData } from 'modules/appData' import { useTradeConfirmActions, useTradePriceImpact } from 'modules/trade' import { SwapFlowAnalyticsContext, tradeFlowAnalytics } from 'modules/trade/utils/analytics' -import { useWalletInfo } from 'modules/wallet' -import { useSafeAppsSdk } from 'modules/wallet/web3-react/hooks/useSafeAppsSdk' import { useConfirmPriceImpactWithoutFee } from 'common/hooks/useConfirmPriceImpactWithoutFee' @@ -125,7 +124,7 @@ export function useCreateTwapOrder() { feeAmount: undefined, }) getCowSoundSend().play() - dispatchPresignedOrderPosted(store, safeTxHash, summary, OrderClass.LIMIT, 'composable-order') + dispatchPresignedOrderPosted(cowSwapStore, safeTxHash, summary, OrderClass.LIMIT, 'composable-order') uploadAppData({ chainId, orderId, appData: appDataInfo }) updateAdvancedOrdersState({ recipient: null, recipientAddress: null }) diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts index 9b905e89bb..a8736ee5f8 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedPartOrders.ts @@ -1,9 +1,10 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' +import { useMachineTimeMs } from '@cowprotocol/common-hooks' + import ms from 'ms.macro' -import useMachineTimeMs from 'legacy/hooks/useMachineTime' import { Order } from 'legacy/state/orders/actions' import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts index 5227eb682d..f3f1d78bb6 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts @@ -1,13 +1,14 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' +import { useMachineTimeMs } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' + import ms from 'ms.macro' -import useMachineTimeMs from 'legacy/hooks/useMachineTime' import { Order } from 'legacy/state/orders/actions' import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' -import { useWalletInfo } from 'modules/wallet' import { twapOrdersListAtom } from '../state/twapOrdersListAtom' import { mapTwapOrderToStoreOrder } from '../utils/mapTwapOrderToStoreOrder' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useExtensibleFallbackContext.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useExtensibleFallbackContext.ts index e4891ad27b..1d5fccb200 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useExtensibleFallbackContext.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useExtensibleFallbackContext.ts @@ -1,12 +1,10 @@ +import { GPv2Settlement } from '@cowprotocol/abis' +import { useGP2SettlementContract } from '@cowprotocol/common-hooks' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { GPv2Settlement } from '@cowswap/abis' +import { useWalletInfo } from '@cowprotocol/wallet' import { Web3Provider } from '@ethersproject/providers' import { useWeb3React } from '@web3-react/core' -import { useGP2SettlementContract } from 'legacy/hooks/useContract' - -import { useWalletInfo } from 'modules/wallet' - export interface ExtensibleFallbackContext { safeAddress: string chainId: SupportedChainId diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useFallbackHandlerVerification.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useFallbackHandlerVerification.ts index 6c4ab260e4..a849e84a1c 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useFallbackHandlerVerification.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useFallbackHandlerVerification.ts @@ -1,6 +1,6 @@ import { useAtomValue } from 'jotai' -import { useWalletInfo } from 'modules/wallet' +import { useWalletInfo } from '@cowprotocol/wallet' import { ExtensibleFallbackVerification } from '../services/verifyExtensibleFallback' import { fallbackHandlerVerificationAtom } from '../state/fallbackHandlerVerificationAtom' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts index 7903898d73..e003d79c2b 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useFetchTwapOrdersFromSafe.ts @@ -1,10 +1,10 @@ import { useEffect, useState } from 'react' -import { ComposableCoW } from '@cowswap/abis' +import { ComposableCoW } from '@cowprotocol/abis' import ms from 'ms.macro' -import { useSafeApiKit } from 'api/gnosisSafe/hooks/useSafeApiKit' +import { useSafeApiKit } from 'common/hooks/useSafeApiKit' import { fetchTwapOrdersFromSafe } from '../services/fetchTwapOrdersFromSafe' import { TwapOrdersSafeData } from '../types' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useSetupTwapAmountsFromUrls.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useSetupTwapAmountsFromUrls.ts index 5b4d408c4a..613568ffc4 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useSetupTwapAmountsFromUrls.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useSetupTwapAmountsFromUrls.ts @@ -1,13 +1,13 @@ import { useCallback, useLayoutEffect, useMemo } from 'react' +import { getIntOrFloat } from '@cowprotocol/common-utils' + import { useLocation, useNavigate } from 'react-router-dom' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { TRADE_URL_BUY_AMOUNT_KEY, TRADE_URL_SELL_AMOUNT_KEY } from 'modules/trade/const/tradeUrl' -import { getIntOrFloat } from 'utils/getIntOrFloat' - import { useAdvancedOrdersActions } from '../../advancedOrders/hooks/useAdvancedOrdersActions' // TODO: unify into a single thing for all forms diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapFormState.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapFormState.ts index 360378d170..f6a693c42c 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapFormState.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapFormState.ts @@ -1,7 +1,7 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' -import { useIsSafeApp, useWalletInfo } from 'modules/wallet' +import { useIsSafeApp, useWalletInfo } from '@cowprotocol/wallet' import { useFallbackHandlerVerification } from './useFallbackHandlerVerification' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrderCreationContext.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrderCreationContext.ts index d23df78b79..377502dac3 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrderCreationContext.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrderCreationContext.ts @@ -1,13 +1,12 @@ -import { ComposableCoW, Erc20 } from '@cowswap/abis' +import { ComposableCoW, Erc20 } from '@cowprotocol/abis' +import { useTokenContract } from '@cowprotocol/common-hooks' +import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { useTokenContract } from 'legacy/hooks/useContract' - import { CURRENT_BLOCK_FACTORY_ADDRESS } from 'modules/advancedOrders' import { useComposableCowContract } from 'modules/advancedOrders/hooks/useComposableCowContract' -import { useWalletInfo } from 'modules/wallet' import { useNeedsApproval } from 'common/hooks/useNeedsApproval' import { useNeedsZeroApproval } from 'common/hooks/useNeedsZeroApproval' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersAuthMulticall.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersAuthMulticall.ts index 508d091c98..4f39c7570a 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersAuthMulticall.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersAuthMulticall.ts @@ -1,6 +1,6 @@ import { useMemo } from 'react' -import { ComposableCoW } from '@cowswap/abis' +import { ComposableCoW } from '@cowprotocol/abis' import { ListenerOptionsWithGas } from '@uniswap/redux-multicall' import { useSingleContractMultipleData } from 'lib/hooks/multicall' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersExecutions.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersExecutions.ts index 5792ce6dd6..f258eb030f 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersExecutions.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersExecutions.ts @@ -1,11 +1,11 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' + import { Order, OrderInfoApi } from 'legacy/state/orders/actions' import { useOrdersById } from 'legacy/state/orders/hooks' -import { useWalletInfo } from 'modules/wallet' - import { getIsFinalizedOrder } from 'utils/orderUtils/getIsFinalizedOrder' import { DEFAULT_TWAP_EXECUTION_INFO } from '../const' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTradeableMulticall.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTradeableMulticall.ts index 0b759dc5fa..458b109c44 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTradeableMulticall.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapOrdersTradeableMulticall.ts @@ -1,6 +1,6 @@ import { useMemo } from 'react' -import { ComposableCoW, GPv2Order } from '@cowswap/abis' +import { ComposableCoW, GPv2Order } from '@cowprotocol/abis' import { ListenerOptionsWithGas } from '@uniswap/redux-multicall' import { useSingleContractMultipleData } from 'lib/hooks/multicall' diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapWarningsContext.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapWarningsContext.ts index 6b1d38ac00..b02275864d 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useTwapWarningsContext.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useTwapWarningsContext.ts @@ -1,8 +1,9 @@ import { useMemo } from 'react' +import { useWalletInfo } from '@cowprotocol/wallet' + import { useTradePriceImpact } from 'modules/trade' import { TradeFormValidation, useGetTradeFormValidation } from 'modules/tradeFormValidation' -import { useWalletInfo } from 'modules/wallet' const NOT_BLOCKING_VALIDATIONS = [ TradeFormValidation.ExpertApproveAndSwap, diff --git a/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/index.tsx b/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/index.tsx index 0a779625b8..282d52ed9c 100644 --- a/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/index.tsx +++ b/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/index.tsx @@ -1,12 +1,12 @@ import React, { ReactNode } from 'react' +import { renderTooltip } from '@cowprotocol/ui' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { Nullish } from 'types' import QuestionHelper from 'legacy/components/QuestionHelper' -import { renderTooltip } from 'legacy/components/Tooltip' import { LabelTooltipItems } from 'modules/twap' diff --git a/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/styled.tsx b/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/styled.tsx index e753097f32..f27a19a309 100644 --- a/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/styled.tsx +++ b/apps/cowswap-frontend/src/modules/twap/pure/AmountParts/styled.tsx @@ -1,3 +1,5 @@ +import { FiatAmount, TokenAmount } from '@cowprotocol/ui' + import { transparentize } from 'polished' import styled from 'styled-components/macro' @@ -5,9 +7,6 @@ import { QuestionWrapper } from 'legacy/components/QuestionHelper' import { TradeWidgetFieldBox, TradeWidgetFieldLabel } from 'modules/trade/pure/TradeWidgetField/styled' -import { FiatAmount } from 'common/pure/FiatAmount' -import { TokenAmount } from 'common/pure/TokenAmount' - export const Wrapper = styled.div` display: flex; grid-gap: 8px; diff --git a/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx b/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx index dac48a0d12..244e0441c4 100644 --- a/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx +++ b/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/index.tsx @@ -1,10 +1,10 @@ import { useCallback, useEffect, useState } from 'react' +import { ButtonPrimary } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import ms from 'ms' -import { ButtonPrimary } from 'legacy/components/Button' - import { TradeNumberInput } from 'modules/trade/pure/TradeNumberInput' import { CowModal as Modal } from 'common/pure/Modal' diff --git a/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx b/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx index f1cf057e60..7579d35386 100644 --- a/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx +++ b/apps/cowswap-frontend/src/modules/twap/pure/CustomDeadlineSelector/styled.tsx @@ -1,8 +1,8 @@ +import { ButtonSecondary } from '@cowprotocol/ui' + import { X } from 'react-feather' import styled from 'styled-components/macro' -import { ButtonSecondary } from 'legacy/components/Button' - import { NumericalInput } from 'modules/trade/pure/TradeNumberInput/styled' import { TradeWidgetFieldBox } from 'modules/trade/pure/TradeWidgetField/styled' diff --git a/apps/cowswap-frontend/src/modules/twap/pure/DeadlineSelector/index.tsx b/apps/cowswap-frontend/src/modules/twap/pure/DeadlineSelector/index.tsx index 36260920b4..7ae76f2cf3 100644 --- a/apps/cowswap-frontend/src/modules/twap/pure/DeadlineSelector/index.tsx +++ b/apps/cowswap-frontend/src/modules/twap/pure/DeadlineSelector/index.tsx @@ -1,8 +1,8 @@ import React, { useCallback, useMemo, useState } from 'react' -import styled from 'styled-components/macro' +import { renderTooltip } from '@cowprotocol/ui' -import { renderTooltip } from 'legacy/components/Tooltip' +import styled from 'styled-components/macro' import { TradeSelect, TradeSelectItem } from 'modules/trade/pure/TradeSelect' import { Content } from 'modules/trade/pure/TradeWidgetField/styled' diff --git a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.test.ts b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.test.ts index 64747a4f5e..18a51eb043 100644 --- a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.test.ts +++ b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.test.ts @@ -1,8 +1,7 @@ +import { COW } from '@cowprotocol/common-const' +import { WETH_GOERLI } from '@cowprotocol/common-const' import { CurrencyAmount } from '@uniswap/sdk-core' -import { COW } from 'legacy/constants/tokens' -import { WETH_GOERLI } from 'legacy/utils/goerli/constants' - import { getTwapFormState, TwapFormState } from './getTwapFormState' import { ExtensibleFallbackVerification } from '../../services/verifyExtensibleFallback' diff --git a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.tsx b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.tsx index 99e058b2ab..0d3e73c5b7 100644 --- a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.tsx +++ b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/getTwapFormState.tsx @@ -1,10 +1,9 @@ +import { isFractionFalsy } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' -import { isFractionFalsy } from 'utils/isFractionFalsy' - import { ExtensibleFallbackVerification } from '../../services/verifyExtensibleFallback' import { TWAPOrder } from '../../types' import { isPartTimeIntervalTooShort } from '../../utils/isPartTimeIntervalTooShort' diff --git a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/index.tsx b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/index.tsx index f7072b0064..1be765d11e 100644 --- a/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/index.tsx +++ b/apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/index.tsx @@ -1,7 +1,6 @@ import React from 'react' -import { ButtonPrimary } from 'legacy/components/Button' -import { ButtonSize } from 'legacy/theme/enum' +import { ButtonSize, ButtonPrimary } from '@cowprotocol/ui' import { TwapFormState } from './getTwapFormState' diff --git a/apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts b/apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts index a0ce440609..b7ae0ca152 100644 --- a/apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts +++ b/apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts @@ -1,4 +1,4 @@ -import { ComposableCoW, GPv2Settlement } from '@cowswap/abis' +import { ComposableCoW, GPv2Settlement } from '@cowprotocol/abis' import { BigNumber } from '@ethersproject/bignumber' import { MetaTransactionData } from '@safe-global/safe-core-sdk-types' diff --git a/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts b/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts index 24c24db14b..7ee4b6c52f 100644 --- a/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts +++ b/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts @@ -1,9 +1,8 @@ +import { COW } from '@cowprotocol/common-const' +import { WETH_GOERLI } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount } from '@uniswap/sdk-core' -import { COW } from 'legacy/constants/tokens' -import { WETH_GOERLI } from 'legacy/utils/goerli/constants' - import { COMPOSABLE_COW_ADDRESS, CURRENT_BLOCK_FACTORY_ADDRESS } from 'modules/advancedOrders' import { getAppData } from 'modules/appData' diff --git a/apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts b/apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts index b4e2b04805..17c721c6ba 100644 --- a/apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts +++ b/apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts @@ -1,12 +1,11 @@ -import { ComposableCoW } from '@cowswap/abis' +import { ComposableCoW } from '@cowprotocol/abis' +import { delay, isTruthy } from '@cowprotocol/common-utils' import type SafeApiKit from '@safe-global/api-kit' import type { AllTransactionsListResponse } from '@safe-global/api-kit' import type { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types' import ms from 'ms.macro' -import { delay, isTruthy } from 'legacy/utils/misc' - import { SafeTransactionParams } from 'common/types' import { ConditionalOrderParams, TwapOrdersSafeData } from '../types' diff --git a/apps/cowswap-frontend/src/modules/twap/services/getSignatureVerifierContract.ts b/apps/cowswap-frontend/src/modules/twap/services/getSignatureVerifierContract.ts index a67d80ff0a..d75e61d9f9 100644 --- a/apps/cowswap-frontend/src/modules/twap/services/getSignatureVerifierContract.ts +++ b/apps/cowswap-frontend/src/modules/twap/services/getSignatureVerifierContract.ts @@ -1,4 +1,4 @@ -import { SignatureVerifierMuxerAbi, SignatureVerifierMuxer } from '@cowswap/abis' +import { SignatureVerifierMuxerAbi, SignatureVerifierMuxer } from '@cowprotocol/abis' import { Contract } from '@ethersproject/contracts' import { ExtensibleFallbackContext } from '../hooks/useExtensibleFallbackContext' diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/composableOrdersPopupMiddleware.ts b/apps/cowswap-frontend/src/modules/twap/state/composableOrdersPopupMiddleware.ts similarity index 64% rename from apps/cowswap-frontend/src/legacy/state/orders/middleware/composableOrdersPopupMiddleware.ts rename to apps/cowswap-frontend/src/modules/twap/state/composableOrdersPopupMiddleware.ts index 80e9f25e42..eb9c3673ea 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/composableOrdersPopupMiddleware.ts +++ b/apps/cowswap-frontend/src/modules/twap/state/composableOrdersPopupMiddleware.ts @@ -1,18 +1,18 @@ +import { isTruthy } from '@cowprotocol/common-utils' +import { jotaiStore } from '@cowprotocol/core' + import { isAnyOf } from '@reduxjs/toolkit' -import { jotaiStore } from 'jotaiStore' import { Middleware } from 'redux' -import { isTruthy } from 'legacy/utils/misc' - -import { tokensByAddressAtom } from 'modules/tokensList/state/tokensListAtom' -import { setTwapOrderStatusAtom, twapOrdersAtom } from 'modules/twap/state/twapOrdersListAtom' -import { TwapOrderStatus } from 'modules/twap/types' -import { mapTwapOrderToStoreOrder } from 'modules/twap/utils/mapTwapOrderToStoreOrder' +import { AppState } from 'legacy/state' +import { cancelOrdersBatch } from 'legacy/state/orders/actions' +import { batchCancelOrdersPopup } from 'legacy/state/orders/middleware/batchCancelOrdersPopup' -import { batchCancelOrdersPopup } from './batchCancelOrdersPopup' +import { setTwapOrderStatusAtom, twapOrdersAtom } from './twapOrdersListAtom' -import { AppState } from '../../index' -import { cancelOrdersBatch } from '../actions' +import { tokensByAddressAtom } from '../../tokensList/state/tokensListAtom' +import { TwapOrderStatus } from '../types' +import { mapTwapOrderToStoreOrder } from '../utils/mapTwapOrderToStoreOrder' const isCancelOrdersBatch = isAnyOf(cancelOrdersBatch) diff --git a/apps/cowswap-frontend/src/modules/twap/state/fallbackHandlerVerificationAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/fallbackHandlerVerificationAtom.ts index eee1e16545..50733c8c1a 100644 --- a/apps/cowswap-frontend/src/modules/twap/state/fallbackHandlerVerificationAtom.ts +++ b/apps/cowswap-frontend/src/modules/twap/state/fallbackHandlerVerificationAtom.ts @@ -1,6 +1,6 @@ import { atomWithStorage } from 'jotai/utils' -import { atomWithPartialUpdate } from 'utils/jotai/atomWithPartialUpdate' +import { atomWithPartialUpdate } from '@cowprotocol/common-utils' import { ExtensibleFallbackVerification } from '../services/verifyExtensibleFallback' diff --git a/apps/cowswap-frontend/src/modules/twap/state/swapAmountDifferenceAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/swapAmountDifferenceAtom.ts index ea71c92d27..29ef390c9a 100644 --- a/apps/cowswap-frontend/src/modules/twap/state/swapAmountDifferenceAtom.ts +++ b/apps/cowswap-frontend/src/modules/twap/state/swapAmountDifferenceAtom.ts @@ -1,9 +1,8 @@ import { atom } from 'jotai' +import { isFractionFalsy } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' -import { isFractionFalsy } from 'utils/isFractionFalsy' - import { fullAmountQuoteAtom } from './fullAmountQuoteAtom' import { partsStateAtom } from './partsStateAtom' diff --git a/apps/cowswap-frontend/src/modules/twap/state/twapOrderAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/twapOrderAtom.ts index 490c60da70..5c8a389f26 100644 --- a/apps/cowswap-frontend/src/modules/twap/state/twapOrderAtom.ts +++ b/apps/cowswap-frontend/src/modules/twap/state/twapOrderAtom.ts @@ -1,11 +1,11 @@ import { atom } from 'jotai' +import { walletInfoAtom } from '@cowprotocol/wallet' import { CurrencyAmount, Token } from '@uniswap/sdk-core' import { advancedOrdersDerivedStateAtom } from 'modules/advancedOrders' import { getAppData } from 'modules/appData' import { appDataInfoAtom } from 'modules/appData/state/atoms' -import { walletInfoAtom } from 'modules/wallet/api/state' import { twapOrderSlippageAtom, twapOrdersSettingsAtom } from './twapOrdersSettingsAtom' diff --git a/apps/cowswap-frontend/src/modules/twap/state/twapOrdersListAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/twapOrdersListAtom.ts index 76d7ae9e15..3899fa26bd 100644 --- a/apps/cowswap-frontend/src/modules/twap/state/twapOrdersListAtom.ts +++ b/apps/cowswap-frontend/src/modules/twap/state/twapOrdersListAtom.ts @@ -1,15 +1,13 @@ import { atom } from 'jotai' import { atomWithStorage } from 'jotai/utils' -import { getJotaiIsolatedStorage } from 'jotaiStore' +import { deepEqual } from '@cowprotocol/common-utils' +import { getJotaiIsolatedStorage } from '@cowprotocol/core' +import { walletInfoAtom } from '@cowprotocol/wallet' -import store from 'legacy/state' +import { cowSwapStore } from 'legacy/state' import { deleteOrders } from 'legacy/state/orders/actions' -import { walletInfoAtom } from 'modules/wallet/api/state' - -import { deepEqual } from 'utils/deepEqual' - import { TWAP_FINAL_STATUSES } from '../const' import { TwapOrderItem, TwapOrderStatus } from '../types' import { updateTwapOrdersList } from '../utils/updateTwapOrdersList' @@ -55,7 +53,7 @@ export const deleteTwapOrdersFromListAtom = atom(null, (get, set, ids: string[]) delete currentState[id] }) - store.dispatch(deleteOrders({ chainId, ids })) + cowSwapStore.dispatch(deleteOrders({ chainId, ids })) set(twapOrdersAtom, currentState) }) diff --git a/apps/cowswap-frontend/src/modules/twap/state/twapOrdersSettingsAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/twapOrdersSettingsAtom.ts index 694c0e4042..faaecd4b8d 100644 --- a/apps/cowswap-frontend/src/modules/twap/state/twapOrdersSettingsAtom.ts +++ b/apps/cowswap-frontend/src/modules/twap/state/twapOrdersSettingsAtom.ts @@ -1,9 +1,9 @@ import { atom } from 'jotai' import { atomWithStorage } from 'jotai/utils' +import { getJotaiIsolatedStorage } from '@cowprotocol/core' import { Percent } from '@uniswap/sdk-core' -import { getJotaiIsolatedStorage } from 'jotaiStore' import { Milliseconds } from 'types' import { DEFAULT_NUM_OF_PARTS, DEFAULT_ORDER_DEADLINE, DEFAULT_TWAP_SLIPPAGE } from '../const' diff --git a/apps/cowswap-frontend/src/modules/twap/state/twapPartOrdersAtom.ts b/apps/cowswap-frontend/src/modules/twap/state/twapPartOrdersAtom.ts index 0e345fd116..d7423130c7 100644 --- a/apps/cowswap-frontend/src/modules/twap/state/twapPartOrdersAtom.ts +++ b/apps/cowswap-frontend/src/modules/twap/state/twapPartOrdersAtom.ts @@ -1,13 +1,10 @@ import { atom } from 'jotai' import { atomWithStorage } from 'jotai/utils' +import { deepEqual } from '@cowprotocol/common-utils' +import { getJotaiIsolatedStorage } from '@cowprotocol/core' import { OrderParameters, SupportedChainId } from '@cowprotocol/cow-sdk' - -import { getJotaiIsolatedStorage } from 'jotaiStore' - -import { walletInfoAtom } from 'modules/wallet/api/state' - -import { deepEqual } from 'utils/deepEqual' +import { walletInfoAtom } from '@cowprotocol/wallet' export interface TwapPartOrderItem { uid: string diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/CreatedInOrderBookOrdersUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/CreatedInOrderBookOrdersUpdater.tsx index b721894cbf..2317c59b22 100644 --- a/apps/cowswap-frontend/src/modules/twap/updaters/CreatedInOrderBookOrdersUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/twap/updaters/CreatedInOrderBookOrdersUpdater.tsx @@ -3,13 +3,13 @@ import { useSetAtom } from 'jotai' import { useEffect, useMemo } from 'react' import { EnrichedOrder } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { useAsyncMemo } from 'use-async-memo' import { useAddOrUpdateOrders } from 'legacy/state/orders/hooks' import { useTokensForOrdersList, getTokensListFromOrders, useSWRProdOrders } from 'modules/orders' -import { useWalletInfo } from 'modules/wallet' import { twapOrdersAtom } from '../state/twapOrdersListAtom' import { TwapPartOrderItem, twapPartOrdersListAtom, updatePartOrdersAtom } from '../state/twapPartOrdersAtom' diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/FallbackHandlerVerificationUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/FallbackHandlerVerificationUpdater.tsx index a6fe2a9f09..8ec9e6244d 100644 --- a/apps/cowswap-frontend/src/modules/twap/updaters/FallbackHandlerVerificationUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/twap/updaters/FallbackHandlerVerificationUpdater.tsx @@ -1,9 +1,9 @@ import { useSetAtom } from 'jotai' import { useEffect } from 'react' -import { useAsyncMemo } from 'use-async-memo' +import { useWalletInfo } from '@cowprotocol/wallet' -import { useWalletInfo } from 'modules/wallet' +import { useAsyncMemo } from 'use-async-memo' import { useExtensibleFallbackContext } from '../hooks/useExtensibleFallbackContext' import { useFallbackHandlerVerification } from '../hooks/useFallbackHandlerVerification' diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/FullAmountQuoteUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/FullAmountQuoteUpdater.tsx index 20f81b6f1c..361826f498 100644 --- a/apps/cowswap-frontend/src/modules/twap/updaters/FullAmountQuoteUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/twap/updaters/FullAmountQuoteUpdater.tsx @@ -1,10 +1,9 @@ import { useSetAtom } from 'jotai' import { useEffect } from 'react' +import { onlyResolvesLast } from '@cowprotocol/common-utils' import { OrderQuoteResponse } from '@cowprotocol/cow-sdk' -import { onlyResolvesLast } from 'legacy/utils/async' - import { useAdvancedOrdersDerivedState } from 'modules/advancedOrders' import { useTradeQuote, useQuoteParams } from 'modules/tradeQuote' diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/PartOrdersUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/PartOrdersUpdater.tsx index 0e3ddbb3df..bf0baa2519 100644 --- a/apps/cowswap-frontend/src/modules/twap/updaters/PartOrdersUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/twap/updaters/PartOrdersUpdater.tsx @@ -1,12 +1,10 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useEffect } from 'react' +import { isTruthy } from '@cowprotocol/common-utils' import { Order } from '@cowprotocol/contracts' import { OrderParameters, SupportedChainId } from '@cowprotocol/cow-sdk' - -import { isTruthy } from 'legacy/utils/misc' - -import { useWalletInfo } from 'modules/wallet' +import { useWalletInfo } from '@cowprotocol/wallet' import { computeOrderUid } from 'utils/orderUtils/computeOrderUid' diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/QuoteObserverUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/QuoteObserverUpdater.tsx index 203c37c703..e7b395f051 100644 --- a/apps/cowswap-frontend/src/modules/twap/updaters/QuoteObserverUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/twap/updaters/QuoteObserverUpdater.tsx @@ -1,10 +1,10 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' +import { usePrevious } from '@cowprotocol/common-hooks' import { CurrencyAmount } from '@uniswap/sdk-core' -import usePrevious from 'legacy/hooks/usePrevious' -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' import { useUpdateCurrencyAmount } from 'modules/trade/hooks/useUpdateCurrencyAmount' diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx index 8c1e6c9bd0..8e54615510 100644 --- a/apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx +++ b/apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx @@ -1,13 +1,12 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useEffect, useMemo, useRef } from 'react' +import { ComposableCoW } from '@cowprotocol/abis' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { ComposableCoW } from '@cowswap/abis' +import { useGnosisSafeInfo } from '@cowprotocol/wallet' import ms from 'ms.macro' -import { useGnosisSafeInfo } from 'modules/wallet' - import { TWAP_PENDING_STATUSES } from '../const' import { useFetchTwapOrdersFromSafe } from '../hooks/useFetchTwapOrdersFromSafe' import { useTwapOrdersAuthMulticall } from '../hooks/useTwapOrdersAuthMulticall' diff --git a/apps/cowswap-frontend/src/modules/twap/updaters/index.tsx b/apps/cowswap-frontend/src/modules/twap/updaters/index.tsx index e9220f64e4..671048db15 100644 --- a/apps/cowswap-frontend/src/modules/twap/updaters/index.tsx +++ b/apps/cowswap-frontend/src/modules/twap/updaters/index.tsx @@ -1,8 +1,9 @@ import { useAtomValue } from 'jotai' +import { useIsSafeApp, useWalletInfo } from '@cowprotocol/wallet' + import { useComposableCowContract } from 'modules/advancedOrders/hooks/useComposableCowContract' import { AppDataUpdater } from 'modules/appData' -import { useIsSafeApp, useWalletInfo } from 'modules/wallet' import { CreatedInOrderBookOrdersUpdater } from './CreatedInOrderBookOrdersUpdater' import { FallbackHandlerVerificationUpdater } from './FallbackHandlerVerificationUpdater' diff --git a/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts b/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts index 6c5902970e..3cfbea976b 100644 --- a/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts +++ b/apps/cowswap-frontend/src/modules/twap/utils/mapPartOrderToStoreOrder.ts @@ -1,11 +1,12 @@ import { EnrichedOrder } from '@cowprotocol/cow-sdk' import { Order } from 'legacy/state/orders/actions' -import { computeOrderSummary } from 'legacy/state/orders/updaters/utils' import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' import { getTokensByAddress } from 'modules/tokensList/utils/getTokensByAddress' +import { computeOrderSummary } from 'common/updaters/orders/utils' + import { getIsLastPartOrder } from './getIsLastPartOrder' import { getPartOrderStatus } from './getPartOrderStatus' diff --git a/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts b/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts index 8336dc2c94..76f943c32e 100644 --- a/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts +++ b/apps/cowswap-frontend/src/modules/twap/utils/mapTwapOrderToStoreOrder.ts @@ -1,9 +1,10 @@ import { Order, OrderStatus } from 'legacy/state/orders/actions' -import { computeOrderSummary } from 'legacy/state/orders/updaters/utils' import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' import { getTokensByAddress } from 'modules/tokensList/utils/getTokensByAddress' +import { computeOrderSummary } from 'common/updaters/orders/utils' + import { emulateTwapAsOrder } from './emulateTwapAsOrder' import { TwapOrderItem, TwapOrderStatus } from '../types' diff --git a/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts b/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts index b9bf124d15..8e33c2ed95 100644 --- a/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts +++ b/apps/cowswap-frontend/src/modules/twap/utils/twapOrderToStruct.ts @@ -1,4 +1,4 @@ -import { NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants' +import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' import { TWAPOrder, TWAPOrderStruct } from '../types' diff --git a/apps/cowswap-frontend/src/modules/twap/utils/updateTwapOrdersList.ts b/apps/cowswap-frontend/src/modules/twap/utils/updateTwapOrdersList.ts index 825cffd8f7..6cd69a281c 100644 --- a/apps/cowswap-frontend/src/modules/twap/utils/updateTwapOrdersList.ts +++ b/apps/cowswap-frontend/src/modules/twap/utils/updateTwapOrdersList.ts @@ -1,4 +1,4 @@ -import { deepEqual } from 'utils/deepEqual' +import { deepEqual } from '@cowprotocol/common-utils' import { TWAP_FINAL_STATUSES } from '../const' import { TwapOrdersList } from '../state/twapOrdersListAtom' diff --git a/apps/cowswap-frontend/src/modules/usdAmount/apis/getCoingeckoUsdPrice.ts b/apps/cowswap-frontend/src/modules/usdAmount/apis/getCoingeckoUsdPrice.ts index bb9b98eae9..cb792c9aa1 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/apis/getCoingeckoUsdPrice.ts +++ b/apps/cowswap-frontend/src/modules/usdAmount/apis/getCoingeckoUsdPrice.ts @@ -1,10 +1,10 @@ +import { FractionUtils } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Fraction, Token } from '@uniswap/sdk-core' import ms from 'ms.macro' import { fetchWithRateLimit } from 'common/utils/fetch' -import { FractionUtils } from 'utils/fractionUtils' export interface CoinGeckoUsdQuote { [address: string]: { diff --git a/apps/cowswap-frontend/src/modules/usdAmount/apis/getCowProtocolUsdPrice.ts b/apps/cowswap-frontend/src/modules/usdAmount/apis/getCowProtocolUsdPrice.ts index 881ecf61f2..f28c2ab114 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/apis/getCowProtocolUsdPrice.ts +++ b/apps/cowswap-frontend/src/modules/usdAmount/apis/getCowProtocolUsdPrice.ts @@ -1,10 +1,8 @@ +import { USDC } from '@cowprotocol/common-const' +import { FractionUtils } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Fraction, Token } from '@uniswap/sdk-core' -import { USDC } from 'legacy/constants/tokens' - -import { FractionUtils } from 'utils/fractionUtils' - import { getCowProtocolNativePrice } from './getCowProtocolNativePrice' export async function getCowProtocolUsdPrice( diff --git a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useTradeUsdAmounts.ts b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useTradeUsdAmounts.ts index 14e20c7384..00e56dbf84 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useTradeUsdAmounts.ts +++ b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useTradeUsdAmounts.ts @@ -1,11 +1,10 @@ +import { isFractionFalsy } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Nullish } from 'types' import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap' -import { isFractionFalsy } from 'utils/isFractionFalsy' - import { UsdAmountInfo, useUsdAmount } from './useUsdAmount' export interface TradeUSDAmounts { diff --git a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.test.tsx b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.test.tsx index 1b72d18fbf..c8f6aaa188 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.test.tsx +++ b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.test.tsx @@ -1,13 +1,12 @@ import { createStore } from 'jotai/vanilla' import { ReactNode } from 'react' +import { WETH_GNOSIS_CHAIN } from '@cowprotocol/common-const' import { CurrencyAmount, Fraction } from '@uniswap/sdk-core' import { renderHook } from '@testing-library/react-hooks' import { JotaiTestProvider } from 'test-utils' -import { WETH_GNOSIS_CHAIN } from 'legacy/utils/gnosis_chain/constants' - import { useUsdAmount } from './useUsdAmount' import { usdRawPricesAtom, UsdRawPriceState } from '../state/usdRawPricesAtom' diff --git a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.ts b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.ts index b6a227bdd5..13a29fee0f 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.ts +++ b/apps/cowswap-frontend/src/modules/usdAmount/hooks/useUsdAmount.ts @@ -1,9 +1,9 @@ +import { currencyAmountToTokenAmount } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { Nullish } from 'types' import { useSafeMemo } from 'common/hooks/useSafeMemo' -import { currencyAmountToTokenAmount } from 'utils/currencyAmountToTokenAmount' import { useUsdPrice } from './useUsdPrice' diff --git a/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts b/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts index 4c40b0dd76..af2afd8f02 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts +++ b/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts @@ -1,9 +1,8 @@ import { atom } from 'jotai' +import { deepEqual } from '@cowprotocol/common-utils' import { Fraction, Token } from '@uniswap/sdk-core' -import { deepEqual } from 'utils/deepEqual' - export interface UsdRawPriceState { updatedAt?: number price: Fraction | null diff --git a/apps/cowswap-frontend/src/modules/usdAmount/state/usdTokenPricesAtom.ts b/apps/cowswap-frontend/src/modules/usdAmount/state/usdTokenPricesAtom.ts index bf63574d40..543eace08a 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/state/usdTokenPricesAtom.ts +++ b/apps/cowswap-frontend/src/modules/usdAmount/state/usdTokenPricesAtom.ts @@ -1,12 +1,10 @@ import { atom } from 'jotai' +import { USDC } from '@cowprotocol/common-const' +import { tryParseCurrencyAmount } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Fraction, Price, Token } from '@uniswap/sdk-core' -import { USDC } from 'legacy/constants/tokens' - -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' - import { usdRawPricesAtom, UsdRawPriceState } from './usdRawPricesAtom' export interface UsdPriceState extends Omit { diff --git a/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.test.tsx b/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.test.tsx index e299ec6e94..e1a2f188d4 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.test.tsx +++ b/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.test.tsx @@ -1,6 +1,7 @@ import { createStore } from 'jotai/vanilla' import { ReactNode } from 'react' +import { COW as COWS, USDC_MAINNET } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Token } from '@uniswap/sdk-core' @@ -8,8 +9,6 @@ import { act, render, waitFor } from '@testing-library/react' import { SWRConfig } from 'swr' import { JotaiTestProvider } from 'test-utils' -import { COW as COWS, USDC_MAINNET } from 'legacy/constants/tokens' - import { UsdPricesUpdater } from './UsdPricesUpdater' import * as coingeckoApi from '../apis/getCoingeckoUsdPrice' diff --git a/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts b/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts index 8c0c04f046..52e4d2a657 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts +++ b/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts @@ -1,19 +1,16 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useEffect, useMemo } from 'react' +import { USDC } from '@cowprotocol/common-const' +import { useDebounce } from '@cowprotocol/common-hooks' +import { FractionUtils } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { Fraction, Token } from '@uniswap/sdk-core' import ms from 'ms.macro' import useSWR, { SWRConfiguration } from 'swr' -import { USDC } from 'legacy/constants/tokens' -import useDebounce from 'legacy/hooks/useDebounce' - -import { useWalletInfo } from 'modules/wallet' - -import { FractionUtils } from 'utils/fractionUtils' - import { getCowProtocolNativePrice } from '../apis/getCowProtocolNativePrice' import { fetchCurrencyUsdPrice } from '../services/fetchCurrencyUsdPrice' import { diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/formatic.png b/apps/cowswap-frontend/src/modules/wallet/api/assets/formatic.png deleted file mode 100644 index 414bab299ba0466be0655c060537538a4a5ae0e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2047 zcmcJQdpy(oAIHC&VVm2K>si{6W!vzlwgpZiwt2< zxf*UwJL7mv6D+|DaSj@<;x&>^$0__k{8O4GEh>lTGT#J!=Tx*QlTHl2$^?a8O^fai zlq+%P_6)ZK%x=XE6<0^M+~qz^9!VLr9b6jxklfPT%uO6U@)z@w50!HK*H-^0eQ{&5IL|Vjbn`Z+i7L^;&(id4A0u?h~Q3&kvmw4vNuQ_~1sAu;}6a zlP$ZE6H7;FV;k5o+h$JpD2diG%!B#wo6#l^h7`& zM;~*m)ZN+~z3M+R|IphG!l{Z92CYkX*DL!}?hZbZtK#e4LJO`q)7F~Dd#p*r{Pz(| zR6&HdcaGnBFs`v-U<#M22hT0CJ8wjw%_kgM_30g18%5#^9A0pl=Iz6j5LQSq@8~OM zcA=6iSaHSgFb+bn00rhb>jWka#g)iw*`Cc4s=f})%YuUWRg#JbK7`g3iRFAtGw>~g zH?HmH-R+`7nGxV-+1v>2N3@6uF195u-sqPc?ZaI6B`3vB;iWB9mcyaz2{0|_{5*H+ z;xdhw{7G2#{tnf4tUIBFy_a#Imvc{9yP(f{ufk(s+$LK?NA0LE*2mnJeG0SNo~Wos zG>iniiU9=R1@TdYgAh&*Dv=rp(c-`rBgdesimDv?y!%M#QjdxDqL ze~z>Nfx2r{=4hpFUEXKIC&(UG)8zC6GjPf+1+O&_#9B^k$anH9eI9wlx8qFh^M&49s=Sxxd1l>zNw6TndkVYw~a zhJa+iLV+w4>Zrbi2?TTsuaSm^LY2D#S)9Yqo>IY3aL2FqW1*Dd%1H%QvL40X(J5A) z&~s$nzEl^aVzDg?f{3#a2)!bZIz7#V{a+Gee-CF)Y!ypuHJl$^v{>?OY4Cr1!=FRA ziH-pNDa$bXU((F8yKeCFe>X-dW5ecJ7xvY^+>+;1{I3?n*`IS7-ClZ1@s%cD zCjurzub0ojI43#k7i%&FJ3(3jrO0B-CEGsheR``i17WoiUNx&3r-b0viyscbwB6L- zvrR22pZKWmpUBBC;JZo#T3Q}S0vJKdWRuao`A3rRhC-!f`c%V4u31!jYXgDCsx_S( zvG0>Bv9>w=HdbyiGCP}5lNQPG?Z>9SBY@ZyZ~3)&r^gX zYLd};7At#nU70%2KP^h}NXqO%ViCdxu|UCOVg#Mu1^Vbb)X2b(aO&;CN|YBKiMwC< zZqGDP#{7oip9vjzldSxx63IWnNB5G5?2d@l{QQ*MGMznNAUk*@O!uG< z6XBx20^7{QC=rj{L7?+IXO)*_sJaEWJ<)h1yYs-5+B6YGV&gL~_(G31V_u=dWqc-- znxTC&Er_XeQ8yE=I1P2O2el$xz$CbeHcv4-37kU3GKhk16@TQobIfu;cC<=K$zi#P z&Y1GCXXK@`Ln7xG1S5E5PU8XZ`7n?BqBq$w?n7`+oT%3l{hU9SwVO5II`h$^4c%H_ z7KGf~D{id;XFTqRxmKEv0T<-Itzh?z$@b!r{P4SPfZPhF6!c=}JCeBq)uP8fI_BCY zo|W?S^yTjlNn~QC$-V>pz}cSRmkidvS5uPL>)mJa`TNeRahh_=Hr^aU{miEQ3{83RzF%LNG z&%9;Oj#%%>@o?-h%rK6>n;4Q7k#HvamFUF^_L0#p0H)cM2||`GeBHt%Co-W1A58xn DE2n-N diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/index.tsx b/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/index.tsx deleted file mode 100644 index 2bf8e37418..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/index.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Trans } from '@lingui/macro' - -import { ExternalLink } from 'legacy/theme' - -import { default as ZengoImage } from 'modules/wallet/api/assets/zengo.svg' - -import * as styled from './styled' - -const GET_ZENGO_LINK = 'https://zengo.com/' -const HOW_TO_USE_ZENGO = 'https://help.zengo.com/en/collections/1646183-how-to-guides' - -export function ZengoBanner() { - return ( - - - - - - -

- Need a crypto wallet? -

-

- Download ZenGo: The most secure crypto wallet. -

-
- - - - - Get ZenGo - - - - - How to use ZenGo - - -
- ) -} diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts b/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts deleted file mode 100644 index c8d278734d..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/ZengoBanner/styled.ts +++ /dev/null @@ -1,72 +0,0 @@ -import styled from 'styled-components/macro' - -import { ButtonPrimary } from 'legacy/components/Button' -import { ExternalLink } from 'legacy/theme/components' - -import { UI } from 'common/constants/theme' - -export const Wrapper = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - flex-wrap: wrap; - width: 100%; - ${({ theme }) => theme.mediaWidth.upToExtraSmall` - flex-direction: column; - justify-content: center; - `}; -` - -export const Icon = styled.div` - max-width: 50px; - img { - max-width: 100%; - } -` - -export const Content = styled.div` - flex: 1; - padding: 0 1rem; - color: var(${UI.COLOR_TEXT1}); - h4 { - margin-bottom: 5px; - font-size: 1.1rem; - } - p { - margin: 0; - font-size: 0.8rem; - } - ${({ theme }) => theme.mediaWidth.upToExtraSmall` - margin-top: 5px; - text-align: center; - `}; -` - -export const Actions = styled.div` - ${({ theme }) => theme.mediaWidth.upToExtraSmall` - margin-top: 10px; - display: flex; - justify-content: center; - flex-direction: column; - `}; -` - -export const GetZengoButton = styled(ButtonPrimary)` - font-size: 12px; - border-radius: 8px; - padding: 8px; - min-height: auto; - a { - color: ${({ theme }) => theme.white}; - &:hover { - text-decoration: none; - } - } -` - -export const HowToUse = styled(ExternalLink)` - font-size: 0.8rem; - margin-top: 5px; - color: var(${UI.COLOR_TEXT1}); - cursor: pointer; -` diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx similarity index 87% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/index.tsx rename to apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx index 8ac22e48b3..f344109ca0 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/index.tsx @@ -1,7 +1,16 @@ import { useAtom, useAtomValue, useSetAtom } from 'jotai' import React, { useCallback, useEffect, useMemo, useState } from 'react' -import { useAddSnackbar } from '@cowswap/snackbars' +import { useAddSnackbar } from '@cowprotocol/snackbars' +import { + accountsLoaders, + hwAccountIndexAtom, + getConnectionIcon, + getConnectionName, + AccountIndexSelect, + HardWareWallet, + getWeb3ReactConnection, +} from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { Trans } from '@lingui/macro' @@ -10,15 +19,9 @@ import { useNativeCurrencyBalances } from 'modules/tokens/hooks/useCurrencyBalan import { CowModal } from 'common/pure/Modal' -import { accountsLoaders } from './accountsLoaders' import { accountSelectorModalAtom, toggleAccountSelectorModalAtom } from './state' import * as styledEl from './styled' -import { hwAccountIndexAtom } from '../../../api/state' -import { getConnectionIcon, getConnectionName } from '../../../api/utils/connection' -import { getWeb3ReactConnection, HardWareWallet } from '../../connection' -import { AccountIndexSelect } from '../../pure/AccountIndexSelect' - export function AccountSelectorModal() { const { isOpen } = useAtomValue(accountSelectorModalAtom) const closeModal = useSetAtom(toggleAccountSelectorModalAtom) diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/state.ts b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/state.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/state.ts rename to apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/state.ts diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/styled.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/styled.tsx similarity index 89% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/styled.tsx rename to apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/styled.tsx index b7f2d1a520..14af67bb69 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/styled.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/AccountSelectorModal/styled.tsx @@ -1,6 +1,6 @@ -import styled from 'styled-components/macro' +import { ReactComponent as Close } from '@cowprotocol/assets/images/x.svg' -import { ReactComponent as Close } from 'legacy/assets/images/x.svg' +import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AddToMetamask/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/AddToMetamask/index.tsx similarity index 66% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AddToMetamask/index.tsx rename to apps/cowswap-frontend/src/modules/wallet/containers/AddToMetamask/index.tsx index 0c543789d0..fc8aa550e9 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AddToMetamask/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/AddToMetamask/index.tsx @@ -1,24 +1,22 @@ import React, { useCallback, useState } from 'react' +import { addTokenToMetamaskAnalytics } from '@cowprotocol/analytics' +import { getIsMetaMask } from '@cowprotocol/wallet' import { Currency } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' -import { Nullish } from 'types' - -import { addTokenToMetamaskAnalytics } from 'legacy/components/analytics' - -import { AddToMetamask as AddToMetamaskPure } from 'modules/wallet/api/pure/AddToMetamask' -import { getIsMetaMask } from 'modules/wallet/api/utils/connection' - import useCurrencyLogoURIs from 'common/pure/CurrencyLogo/hooks/useCurrencyLogoURIs' +import { AddToMetamask as AddToMetamaskPure } from '../../pure/AddToMetamask' + export type AddToMetamaskProps = { - currency: Nullish + currency: Currency | null | undefined shortLabel?: boolean + className?: string } -export default function AddToMetamask(props: AddToMetamaskProps) { - const { currency, shortLabel } = props +export function AddToMetamask(props: AddToMetamaskProps) { + const { currency, shortLabel, className } = props const { connector } = useWeb3React() const isMetamask = getIsMetaMask() @@ -50,5 +48,13 @@ export default function AddToMetamask(props: AddToMetamaskProps) { return null } - return + return ( + + ) } diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx new file mode 100644 index 0000000000..40f225c6a5 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx @@ -0,0 +1,98 @@ +import { useTheme } from '@cowprotocol/common-hooks' +import { isMobile } from '@cowprotocol/common-utils' +import { + AlphaOption, + AmbireOption, + CoinbaseWalletOption, + InjectedOption, + InstallMetaMaskOption, + MetaMaskOption, + OpenMetaMaskMobileOption, + InstallKeystoneOption, + KeystoneOption, + LedgerOption, + TrezorOption, + TrustWalletOption, + WalletConnectOption, + WalletConnectV2Option, + getIsCoinbaseWallet, + getIsInjected, + getIsMetaMask, +} from '@cowprotocol/wallet' +import { Connector } from '@web3-react/types' + +import { useSelectedWallet } from 'legacy/state/user/hooks' + +import { FeatureGuard } from 'common/containers/FeatureGuard' + +export type TryActivation = (connector: Connector) => void + +export function ConnectWalletOptions({ tryActivation }: { tryActivation: TryActivation }) { + const isInjected = getIsInjected() + const isMetaMask = getIsMetaMask() + const isCoinbaseWallet = getIsCoinbaseWallet() + const selectedWallet = useSelectedWallet() + const { darkMode } = useTheme() + + const isCoinbaseWalletBrowser = isMobile && isCoinbaseWallet + const isMetaMaskBrowser = isMobile && isMetaMask + const isInjectedMobileBrowser = isCoinbaseWalletBrowser || isMetaMaskBrowser + // const isChromeMobile = isMobile && isChrome + const showKeystone = !isInjectedMobileBrowser && !isMobile && window.ethereum?.isMetaMask + + const connectionProps = { darkMode, selectedWallet, tryActivation } + + // Show Tally option only in Chrome (includes Brave too), but not on mobile or as an injected browser + // const showTally = !isInjectedMobileBrowser && isChrome && !isChromeMobile + + let injectedOption + if (!isInjected) { + if (!isMobile) { + injectedOption = + } else { + injectedOption = + } + } else { + if (isMetaMask) { + injectedOption = + } else { + injectedOption = + } + } + + const coinbaseWalletOption = + + const walletConnectionOption = (!isInjectedMobileBrowser && ) ?? null + + const walletConnectionV2Option = (!isInjectedMobileBrowser && ) ?? null + + // Wallet-connect based + // const zengoOption = (!isInjectedMobileBrowser && ) ?? null + const ambireOption = (!isInjectedMobileBrowser && ) ?? null + const alphaOption = (!isInjectedMobileBrowser && ) ?? null + const ledgerOption = (!isInjectedMobileBrowser && !isMobile && ) ?? null + const trezorOption = (!isInjectedMobileBrowser && !isMobile && ) ?? null + const keystoneOption = + (showKeystone && ) || (!isMobile && ) + + // Injected + // const tallyOption = (showTally && ) ?? null + const trustOption = (!isInjectedMobileBrowser && ) ?? null + + return ( + <> + {injectedOption} + {walletConnectionOption} + {walletConnectionV2Option} + {coinbaseWalletOption} + {ledgerOption} + {trezorOption} + {/*{zengoOption}*/} + {ambireOption} + {alphaOption} + {/* {tallyOption} */} + {trustOption} + {keystoneOption} + + ) +} diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx similarity index 97% rename from apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx rename to apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx index 8f5d1c36f6..54b6852023 100644 --- a/apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/FollowPendingTxPopupUI.tsx @@ -1,11 +1,12 @@ import React from 'react' +import { Tooltip, TooltipProps } from '@cowprotocol/ui' + import { Text } from 'rebass' import styled from 'styled-components/macro' import { AutoColumn } from 'legacy/components/Column' import { StyledClose as IconClose } from 'legacy/components/Popups/styled' -import Tooltip, { TooltipProps } from 'legacy/components/Tooltip' interface PopupContentProps { onCheck: () => void diff --git a/apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/index.tsx similarity index 91% rename from apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/index.tsx rename to apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/index.tsx index 42666204ab..5f2270a7d9 100644 --- a/apps/cowswap-frontend/src/legacy/components/Popups/FollowPendingTxPopup/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/FollowPendingTxPopup/index.tsx @@ -3,19 +3,18 @@ import { selectAtom } from 'jotai/utils' import React, { useEffect, useMemo, useCallback, useRef, PropsWithChildren } from 'react' import { useRecentActivityLastPendingOrder } from 'legacy/hooks/useRecentActivity' +import { Order } from 'legacy/state/orders/actions' +import { useIsExpertMode } from 'legacy/state/user/hooks' + +import { FollowPendingTxPopupUI } from './FollowPendingTxPopupUI' + import { handleFollowPendingTxPopupAtom, handleHidePopupPermanentlyAtom, showFollowTxPopupAtom, followPendingTxPopupAtom, handleCloseOrderPopupAtom, -} from 'legacy/state/application/atoms' -import { Order } from 'legacy/state/orders/actions' -import { useIsExpertMode } from 'legacy/state/user/hooks' - -import { OrderID } from 'api/gnosisProtocol' - -import { FollowPendingTxPopupUI } from './FollowPendingTxPopupUI' +} from '../../state/followPendingTxPopupAtom' export function useLastPendingOrder(): { lastPendingOrder: Order | null; onClose: () => void } { const setShowFollowPendingTxPopup = useSetAtom(handleFollowPendingTxPopupAtom) @@ -45,7 +44,7 @@ export function useCloseFollowTxPopupIfNotPendingOrder() { }, [lastPendingOrder, onClose, showingPopup]) } -const useShowingPopupFirstTime = (orderId: OrderID | undefined) => { +const useShowingPopupFirstTime = (orderId: string | undefined) => { const showingPopup = useAtomValue(showFollowTxPopupAtom) const _firstTimePopupOrderAppears = useMemo( () => @@ -62,7 +61,7 @@ const useShowingPopupFirstTime = (orderId: OrderID | undefined) => { return { showPopup: firstTimePopupOrderAppears && showingPopup, firstTimePopupOrderAppears } } -const FollowPendingTxPopup: React.FC = ({ children }): JSX.Element => { +export const FollowPendingTxPopup: React.FC = ({ children }): JSX.Element => { const setShowFollowPendingTxPopup = useSetAtom(handleFollowPendingTxPopupAtom) const setHidePendingTxPopupPermanently = useSetAtom(handleHidePopupPermanentlyAtom) const isExpertMode = useIsExpertMode() @@ -87,5 +86,3 @@ const FollowPendingTxPopup: React.FC = ({ children }): JSX.El ) } - -export default FollowPendingTxPopup diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/WalletModal/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx similarity index 86% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/WalletModal/index.tsx rename to apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx index b70e80dfbf..93dc61ddfe 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/WalletModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx @@ -1,22 +1,21 @@ import { useSetAtom } from 'jotai' import { useCallback, useEffect, useState } from 'react' +import { changeWalletAnalytics } from '@cowprotocol/analytics' +import { usePrevious } from '@cowprotocol/common-hooks' +import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' +import { useWalletInfo, ConnectionType, getIsHardWareWallet, getWeb3ReactConnection } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { Connector } from '@web3-react/types' -import { changeWalletAnalytics } from 'legacy/components/analytics' -import usePrevious from 'legacy/hooks/usePrevious' import { useModalIsOpen, useToggleWalletModal } from 'legacy/state/application/hooks' import { ApplicationModal } from 'legacy/state/application/reducer' import { updateConnectionError } from 'legacy/state/connection/reducer' import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' import { updateSelectedWallet } from 'legacy/state/user/reducer' -import { ConnectionType, toggleAccountSelectorModalAtom, useWalletInfo } from 'modules/wallet' -import { WalletModal as WalletModalPure, WalletModalView } from 'modules/wallet/api/pure/WalletModal' -import { getIsHardWareWallet, getWeb3ReactConnection } from 'modules/wallet/web3-react/connection' - -import { getCurrentChainIdFromUrl } from 'utils/getCurrentChainIdFromUrl' +import { WalletModal as WalletModalPure, WalletModalView } from '../../pure/WalletModal' +import { toggleAccountSelectorModalAtom } from '../AccountSelectorModal/state' export function WalletModal() { const dispatch = useAppDispatch() @@ -85,12 +84,6 @@ export function WalletModal() { changeWalletAnalytics('Todo: wallet name') try { - // Fortmatic opens it's own modal on activation to log in. This modal has a tabIndex - // collision into the WalletModal, so we special case by closing the modal. - if (connectionType === ConnectionType.FORTMATIC) { - toggleWalletModal() - } - setPendingConnector(connector) setWalletView('pending') dispatch(updateConnectionError({ connectionType, error: undefined })) @@ -131,7 +124,7 @@ export function WalletModal() { ) } }, - [chainId, dispatch, toggleWalletModal, toggleAccountSelectorModal] + [chainId, dispatch, toggleAccountSelectorModal] ) return ( diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/Web3Status/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/Web3Status/index.tsx similarity index 59% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/Web3Status/index.tsx rename to apps/cowswap-frontend/src/modules/wallet/containers/Web3Status/index.tsx index 29915da1e3..98d9318854 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/Web3Status/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/Web3Status/index.tsx @@ -1,18 +1,17 @@ +import { STORAGE_KEY_LAST_PROVIDER } from '@cowprotocol/common-const' +import { useWalletDetails, useWalletInfo, getWeb3ReactConnection } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' -import { useCloseFollowTxPopupIfNotPendingOrder } from 'legacy/components/Popups/FollowPendingTxPopup' -import { STORAGE_KEY_LAST_PROVIDER } from 'legacy/constants' import { useToggleWalletModal } from 'legacy/state/application/hooks' import { useAppSelector } from 'legacy/state/hooks' -import { useWalletDetails, useWalletInfo, WalletModal, AccountSelectorModal } from 'modules/wallet' -import { Web3StatusInner } from 'modules/wallet/api/pure/Web3StatusInner' -import { Wrapper } from 'modules/wallet/api/pure/Web3StatusInner/styled' -import { getWeb3ReactConnection } from 'modules/wallet/web3-react/connection' +import { Web3StatusInner } from '../../pure/Web3StatusInner' +import { Wrapper } from '../../pure/Web3StatusInner/styled' +import { AccountSelectorModal } from '../AccountSelectorModal' +import { useCloseFollowTxPopupIfNotPendingOrder } from '../FollowPendingTxPopup' +import { WalletModal } from '../WalletModal' -import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity' - -export function Web3Status() { +export function Web3Status({ pendingActivities }: { pendingActivities: string[] }) { const { connector } = useWeb3React() const { account, active, chainId } = useWalletInfo() const { ensName } = useWalletDetails() @@ -27,8 +26,6 @@ export function Web3Status() { const latestProvider = localStorage.getItem(STORAGE_KEY_LAST_PROVIDER) - const { pendingActivity } = useCategorizeRecentActivity() - if (!active && !latestProvider) { return null } @@ -36,7 +33,7 @@ export function Web3Status() { return ( theme.border2}; - color: var(${UI.COLOR_TEXT1}); + color: var(--cow-color-text1); background: transparent; outline: 0; padding: 8px 16px; @@ -63,14 +58,15 @@ export type AddToMetamaskProps = { shortLabel?: boolean addToken: () => void success?: boolean + className?: string } export function AddToMetamask(props: AddToMetamaskProps) { - const { currency, shortLabel, addToken, success } = props + const { className, currency, shortLabel, addToken, success } = props const theme = useContext(ThemeContext) return ( - + {!success ? ( {' '} diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/PendingView/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/PendingView/index.tsx similarity index 96% rename from apps/cowswap-frontend/src/modules/wallet/api/pure/PendingView/index.tsx rename to apps/cowswap-frontend/src/modules/wallet/pure/PendingView/index.tsx index 17bd20276a..bcf5a9ec59 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/PendingView/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/pure/PendingView/index.tsx @@ -1,9 +1,9 @@ +import { ButtonEmpty, ButtonPrimary, Loader } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import { transparentize } from 'polished' import styled from 'styled-components/macro' -import { ButtonEmpty, ButtonPrimary } from 'legacy/components/Button' -import Loader from 'legacy/components/Loader' import { ThemedText } from 'legacy/theme' const PendingSection = styled.div` diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/StatusIcon/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx similarity index 64% rename from apps/cowswap-frontend/src/modules/wallet/api/pure/StatusIcon/index.tsx rename to apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx index e4976c9f50..6b37269109 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/StatusIcon/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx @@ -1,10 +1,7 @@ -import styled from 'styled-components/macro' +import { Identicon, ConnectionType } from '@cowprotocol/wallet' +import { CoinbaseWalletIcon, WalletConnectIcon } from '@cowprotocol/wallet' -import { ConnectionType } from 'modules/wallet' -import CoinbaseWalletIcon from 'modules/wallet/api/assets/coinbase.svg' -import FortmaticIcon from 'modules/wallet/api/assets/formatic.png' -import WalletConnectIcon from 'modules/wallet/api/assets/walletConnectIcon.svg' -import { Identicon } from 'modules/wallet/api/container/Identicon' +import styled from 'styled-components/macro' const IconWrapper = styled.div<{ size?: number }>` ${({ theme }) => theme.flexColumnNoWrap}; @@ -25,7 +22,7 @@ export interface StatusIconProps { connectionType: ConnectionType } -export default function StatusIcon({ connectionType }: StatusIconProps) { +export function StatusIcon({ connectionType }: StatusIconProps) { let image switch (connectionType) { case ConnectionType.INJECTED: @@ -37,9 +34,6 @@ export default function StatusIcon({ connectionType }: StatusIconProps) { case ConnectionType.COINBASE_WALLET: image = Coinbase Wallet break - case ConnectionType.FORTMATIC: - image = Fortmatic - break } return {image} diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/index.tsx similarity index 93% rename from apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/index.tsx rename to apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/index.tsx index 98493699f0..ad4be408f5 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/index.tsx @@ -1,21 +1,21 @@ +import { AutoRow } from '@cowprotocol/ui' import { Connector } from '@web3-react/types' import { Trans } from '@lingui/macro' import { LightCard } from 'legacy/components/Card' import { AutoColumn } from 'legacy/components/Column' -import { AutoRow } from 'legacy/components/Row' import { ThemedText } from 'legacy/theme' import { StyledInternalLink } from 'legacy/theme/components' -import { PendingView } from 'modules/wallet/api/pure/PendingView' -import { ConnectWalletOptions, TryActivation } from 'modules/wallet/web3-react/connection' - import { Routes } from 'common/constants/routes' import { CloseIcon, ContentWrapper, CowModal, HeaderRow, HoverText } from 'common/pure/Modal' import { CloseColor, OptionGrid, TermsWrapper, UpperSection, Wrapper } from './styled' +import { ConnectWalletOptions, TryActivation } from '../../containers/ConnectWalletOptions' +import { PendingView } from '../PendingView' + export type WalletModalView = 'options' | 'account' | 'pending' interface WalletModalProps { diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/styled.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/styled.tsx similarity index 93% rename from apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/styled.tsx rename to apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/styled.tsx index 581ed5c91d..2c2de9c91e 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/WalletModal/styled.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/pure/WalletModal/styled.tsx @@ -1,7 +1,7 @@ -import styled from 'styled-components/macro' +import { ReactComponent as Close } from '@cowprotocol/assets/images/x.svg' +import { ExternalLink } from '@cowprotocol/ui' -import { ReactComponent as Close } from 'legacy/assets/images/x.svg' -import { ExternalLink } from 'legacy/theme' +import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx similarity index 82% rename from apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/index.tsx rename to apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx index ba324b17c1..0a8a9affdc 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx @@ -1,15 +1,14 @@ -import { Trans } from '@lingui/macro' - -import Loader from 'legacy/components/Loader' -import FollowPendingTxPopup from 'legacy/components/Popups/FollowPendingTxPopup' -import { RowBetween } from 'legacy/components/Row' -import { shortenAddress } from 'legacy/utils' +import { shortenAddress } from '@cowprotocol/common-utils' +import { Loader, RowBetween } from '@cowprotocol/ui' +import { ConnectionType } from '@cowprotocol/wallet' -import StatusIcon from 'modules/wallet/api/pure/StatusIcon' -import { ConnectionType } from 'modules/wallet/api/types' +import { Trans } from '@lingui/macro' import { NetworkIcon, Text, Web3StatusConnect, Web3StatusConnected, Web3StatusError } from './styled' +import { FollowPendingTxPopup } from '../../containers/FollowPendingTxPopup' +import { StatusIcon } from '../StatusIcon' + export interface Web3StatusInnerProps { account?: string | null chainId?: number diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/styled.ts b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/styled.ts similarity index 96% rename from apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/styled.ts rename to apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/styled.ts index be29ea94b8..35738b87d3 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/Web3StatusInner/styled.ts +++ b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/styled.ts @@ -1,9 +1,9 @@ +import { ButtonSecondary } from '@cowprotocol/ui' + import { darken } from 'polished' import { Activity } from 'react-feather' import styled, { css } from 'styled-components/macro' -import { ButtonSecondary } from 'legacy/components/Button' - import { UI } from 'common/constants/theme' export const Web3StatusGeneric = styled(ButtonSecondary)`` @@ -94,7 +94,7 @@ export const Wrapper = styled.div` ${({ theme }) => theme.mediaWidth.upToMedium` width: auto; height: 100%; - margin: 0 0 0 auto; + margin: 0 auto; `}; button { diff --git a/apps/cowswap-frontend/src/legacy/state/application/atoms.ts b/apps/cowswap-frontend/src/modules/wallet/state/followPendingTxPopupAtom.ts similarity index 96% rename from apps/cowswap-frontend/src/legacy/state/application/atoms.ts rename to apps/cowswap-frontend/src/modules/wallet/state/followPendingTxPopupAtom.ts index e64a6f5469..58be234eb6 100644 --- a/apps/cowswap-frontend/src/legacy/state/application/atoms.ts +++ b/apps/cowswap-frontend/src/modules/wallet/state/followPendingTxPopupAtom.ts @@ -5,7 +5,7 @@ import { OrderID } from 'api/gnosisProtocol' type FollowPendingTxPopup = { showPopup: boolean - lastOrderPopupClosed: OrderID | undefined + lastOrderPopupClosed: string | undefined hidePopupPermanently: boolean } diff --git a/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts b/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts index 58cc084f2d..126cb31acb 100644 --- a/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts +++ b/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts @@ -1,3 +1,4 @@ +import { getContract } from '@cowprotocol/common-utils' import { defaultAbiCoder, ParamType } from '@ethersproject/abi' import { TypedDataField } from '@ethersproject/abstract-signer' import type { Web3Provider } from '@ethersproject/providers' @@ -6,8 +7,6 @@ import { Wallet } from '@ethersproject/wallet' import { AbiItem, EIP712TypedData, ProviderConnector } from '@1inch/permit-signed-approvals-utils' import { AbiInput } from 'web3-utils' -import { getContract } from 'legacy/utils' - export class PermitProviderConnector implements ProviderConnector { constructor(private provider: Web3Provider, private walletSigner?: Wallet | undefined) {} diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/formatic.tsx b/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/formatic.tsx deleted file mode 100644 index 704082274d..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/formatic.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { initializeConnector } from '@web3-react/core' - -import { useIsActiveWallet } from 'legacy/hooks/useIsActiveWallet' - -import { ConnectionType } from 'modules/wallet' -import { default as FormaticImage } from 'modules/wallet/api/assets/formatic.png' -import { ConnectWalletOption } from 'modules/wallet/api/pure/ConnectWalletOption' -import { getConnectionName } from 'modules/wallet/api/utils/connection' - -import { AsyncConnector } from './asyncConnector' - -import { Web3ReactConnection } from '../types' - -import { TryActivation } from '.' - -const [web3Fortmatic, web3FortmaticHooks] = initializeConnector( - (actions) => - new AsyncConnector( - () => - Promise.all([import('@web3-react/eip1193'), import('fortmatic')]).then(([{ EIP1193 }, m]) => { - const Fortmatic = m.default - return new EIP1193({ actions, provider: new Fortmatic(process.env.REACT_APP_FORTMATIC_KEY).getProvider() }) - }), - actions - ) -) -export const fortmaticConnection: Web3ReactConnection = { - connector: web3Fortmatic, - hooks: web3FortmaticHooks, - type: ConnectionType.FORTMATIC, -} - -export const formaticOption = { - color: '#6748FF', - icon: FormaticImage, - id: 'fortmatic', -} - -export function FortmaticOption({ tryActivation }: { tryActivation: TryActivation }) { - const isActive = useIsActiveWallet(fortmaticConnection) - - return ( - tryActivation(fortmaticConnection.connector)} - header={getConnectionName(ConnectionType.FORTMATIC)} - /> - ) -} diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/index.tsx b/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/index.tsx deleted file mode 100644 index ddd5c5c003..0000000000 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/index.tsx +++ /dev/null @@ -1,174 +0,0 @@ -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { Connector } from '@web3-react/types' - -import { ALL_SUPPORTED_CHAIN_IDS } from 'legacy/constants/chains' -import { isMobile } from 'legacy/utils/userAgent' - -import { getIsCoinbaseWallet, getIsInjected, getIsMetaMask } from 'modules/wallet/api/utils/connection' - -import { FeatureGuard } from 'common/containers/FeatureGuard' - -import { AlphaOption } from './alpha' -import { AmbireOption } from './ambire' -import { coinbaseWalletConnection, CoinbaseWalletOption } from './coinbase' -import { fortmaticConnection } from './formatic' -import { - injectedConnection, - InjectedOption, - InstallMetaMaskOption, - MetaMaskOption, - OpenMetaMaskMobileOption, -} from './injected' -import { injectedWidgetConnection } from './injectedWidget' -import { InstallKeystoneOption, keystoneConnection, KeystoneOption } from './keystone' -import { ledgerConnection, LedgerOption } from './ledger' -import { networkConnection } from './network' -import { gnosisSafeConnection } from './safe' -import { tallyWalletConnection } from './tally' -import { trezorConnection, TrezorOption } from './trezor' -import { trustWalletConnection, TrustWalletOption } from './trust' -import { walletConnectConnection, WalletConnectOption } from './walletConnect' -import { walletConnectConnectionV2, WalletConnectV2Option } from './walletConnectV2' - -import { ConnectionType } from '../../api/types' -import { Web3ReactConnection } from '../types' - -const allowedChainsByWallet: Record = { - [ConnectionType.FORTMATIC]: [SupportedChainId.MAINNET], - [ConnectionType.INJECTED]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.INJECTED_WIDGET]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.COINBASE_WALLET]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.WALLET_CONNECT]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.WALLET_CONNECT_V2]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.NETWORK]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.GNOSIS_SAFE]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.TALLY]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.TRUST]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.LEDGER]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.TREZOR]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.KEYSTONE]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.ALPHA]: [], - [ConnectionType.AMBIRE]: [], - [ConnectionType.ZENGO]: [], -} - -export function isChainAllowed(connector: Connector, chainId: number): boolean { - const connection = getWeb3ReactConnection(connector) - - return allowedChainsByWallet[connection.type].includes(chainId) -} - -const connectionTypeToConnection: Record = { - [ConnectionType.INJECTED]: injectedConnection, - [ConnectionType.COINBASE_WALLET]: coinbaseWalletConnection, - [ConnectionType.WALLET_CONNECT]: walletConnectConnection, - [ConnectionType.WALLET_CONNECT_V2]: walletConnectConnectionV2, - [ConnectionType.ZENGO]: walletConnectConnection, - [ConnectionType.FORTMATIC]: fortmaticConnection, - [ConnectionType.NETWORK]: networkConnection, - [ConnectionType.GNOSIS_SAFE]: gnosisSafeConnection, - [ConnectionType.AMBIRE]: walletConnectConnection, - [ConnectionType.ALPHA]: walletConnectConnection, - [ConnectionType.TALLY]: tallyWalletConnection, - [ConnectionType.TRUST]: trustWalletConnection, - [ConnectionType.LEDGER]: ledgerConnection, - [ConnectionType.KEYSTONE]: keystoneConnection, - [ConnectionType.INJECTED_WIDGET]: injectedWidgetConnection, - [ConnectionType.TREZOR]: trezorConnection, -} - -const CONNECTIONS: Web3ReactConnection[] = Object.values(connectionTypeToConnection) - -// TODO: add others -export const HARDWARE_WALLETS = [ConnectionType.TREZOR] as const - -export type HardWareWallet = (typeof HARDWARE_WALLETS)[number] - -export const getIsHardWareWallet = (connectionType: ConnectionType) => - HARDWARE_WALLETS.includes(connectionType as HardWareWallet) - -export function getWeb3ReactConnection(c: Connector | ConnectionType): Web3ReactConnection { - if (c instanceof Connector) { - const connection = CONNECTIONS.find((connection) => connection.connector === c) - if (!connection) { - throw Error('unsupported connector') - } - return connection - } - - return connectionTypeToConnection[c] -} - -export type TryActivation = (connector: Connector) => void - -export function ConnectWalletOptions({ tryActivation }: { tryActivation: TryActivation }) { - const isInjected = getIsInjected() - const isMetaMask = getIsMetaMask() - const isCoinbaseWallet = getIsCoinbaseWallet() - - const isCoinbaseWalletBrowser = isMobile && isCoinbaseWallet - const isMetaMaskBrowser = isMobile && isMetaMask - const isInjectedMobileBrowser = isCoinbaseWalletBrowser || isMetaMaskBrowser - // const isChromeMobile = isMobile && isChrome - const showKeystone = !isInjectedMobileBrowser && !isMobile && window.ethereum?.isMetaMask - - // Show Tally option only in Chrome (includes Brave too), but not on mobile or as an injected browser - // const showTally = !isInjectedMobileBrowser && isChrome && !isChromeMobile - - let injectedOption - if (!isInjected) { - if (!isMobile) { - injectedOption = - } else { - injectedOption = - } - } else { - if (isMetaMask) { - injectedOption = - } else { - injectedOption = - } - } - - const coinbaseWalletOption = - - const walletConnectionOption = - (!isInjectedMobileBrowser && ) ?? null - - const walletConnectionV2Option = - (!isInjectedMobileBrowser && ) ?? null - - // Wallet-connect based - // const zengoOption = (!isInjectedMobileBrowser && ) ?? null - const ambireOption = (!isInjectedMobileBrowser && ) ?? null - const alphaOption = (!isInjectedMobileBrowser && ) ?? null - const ledgerOption = (!isInjectedMobileBrowser && !isMobile && ) ?? null - const trezorOption = (!isInjectedMobileBrowser && !isMobile && ) ?? null - const keystoneOption = - (showKeystone && ) || (!isMobile && ) - - // Injected - // const tallyOption = (showTally && ) ?? null - const trustOption = (!isInjectedMobileBrowser && ) ?? null - - return ( - <> - {injectedOption} - {walletConnectionOption} - {walletConnectionV2Option} - {coinbaseWalletOption} - {ledgerOption} - {trezorOption} - {/*{zengoOption}*/} - {ambireOption} - {alphaOption} - {/* {tallyOption} */} - {trustOption} - {keystoneOption} - - ) -} - -export function onError(error: Error) { - console.debug(`[web3-react] Error: ${error}`) -} diff --git a/apps/cowswap-frontend/src/pages/About/index.tsx b/apps/cowswap-frontend/src/pages/About/index.tsx index 0cca13a89f..1e92bc226e 100644 --- a/apps/cowswap-frontend/src/pages/About/index.tsx +++ b/apps/cowswap-frontend/src/pages/About/index.tsx @@ -1,14 +1,14 @@ -// Assets +import diagramIMG from '@cowprotocol/assets/cow-swap/cowswap-diagram.png' +import gaslessIMG from '@cowprotocol/assets/cow-swap/gasless.png' +import mevIMG from '@cowprotocol/assets/cow-swap/mev.png' +import { MEV_TOTAL, FLASHBOTS_LINK } from '@cowprotocol/common-const' +import { ExternalLink as ExternalLinkTheme } from '@cowprotocol/ui' + import { Link } from 'react-router-dom' import styled from 'styled-components/macro' -import diagramIMG from 'legacy/assets/cow-swap/cowswap-diagram.png' -import gaslessIMG from 'legacy/assets/cow-swap/gasless.png' -import mevIMG from 'legacy/assets/cow-swap/mev.png' import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' -import { MEV_TOTAL, FLASHBOTS_LINK } from 'legacy/constants' -import { ExternalLink as ExternalLinkTheme } from 'legacy/theme' import { PageTitle } from 'modules/application/containers/PageTitle' import { Page, Title, Content, GdocsListStyle } from 'modules/application/pure/Page' diff --git a/apps/cowswap-frontend/src/pages/Account/Balances.tsx b/apps/cowswap-frontend/src/pages/Account/Balances.tsx index d889b18846..63b4991a21 100644 --- a/apps/cowswap-frontend/src/pages/Account/Balances.tsx +++ b/apps/cowswap-frontend/src/pages/Account/Balances.tsx @@ -1,5 +1,15 @@ import { useCallback, useEffect, useMemo, useState } from 'react' +import ArrowIcon from '@cowprotocol/assets/cow-swap/arrow.svg' +import CowImage from '@cowprotocol/assets/cow-swap/cow_v2.svg' +import vCOWImage from '@cowprotocol/assets/cow-swap/vCOW.png' +import { COW, COW_CONTRACT_ADDRESS, V_COW, V_COW_CONTRACT_ADDRESS } from '@cowprotocol/common-const' +import { usePrevious } from '@cowprotocol/common-hooks' +import { useBlockNumber } from '@cowprotocol/common-hooks' +import { getBlockExplorerUrl, getProviderErrorMessage } from '@cowprotocol/common-utils' +import { TokenAmount, ButtonPrimary } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' import { MetaMask } from '@web3-react/metamask' @@ -8,31 +18,17 @@ import { Trans } from '@lingui/macro' import SVG from 'react-inlinesvg' import { Link } from 'react-router-dom' -import ArrowIcon from 'legacy/assets/cow-swap/arrow.svg' -import CowImage from 'legacy/assets/cow-swap/cow_v2.svg' -import vCOWImage from 'legacy/assets/cow-swap/vCOW.png' -import { ButtonPrimary } from 'legacy/components/Button' import CopyHelper from 'legacy/components/Copy' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' -import { V_COW_CONTRACT_ADDRESS, COW_CONTRACT_ADDRESS } from 'legacy/constants' -import { COW, V_COW } from 'legacy/constants/tokens' import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal' -import usePrevious from 'legacy/hooks/usePrevious' import useTransactionConfirmationModal from 'legacy/hooks/useTransactionConfirmationModal' import { SwapVCowStatus } from 'legacy/state/cowToken/actions' import { useVCowData, useSwapVCowCallback, useSetSwapVCowStatus, useSwapVCowStatus } from 'legacy/state/cowToken/hooks' -import { getBlockExplorerUrl } from 'legacy/utils' -import { getProviderErrorMessage } from 'legacy/utils/misc' +import { ConfirmOperationType } from 'legacy/state/types' import { useTokenBalance } from 'modules/tokens/hooks/useCurrencyBalance' -import { useWalletInfo } from 'modules/wallet' -import AddToMetamask from 'modules/wallet/web3-react/containers/AddToMetamask' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' import { HelpCircle } from 'common/pure/HelpCircle' -import { TokenAmount } from 'common/pure/TokenAmount' -import useBlockNumber from 'lib/hooks/useBlockNumber' import { useCowFromLockedGnoBalances } from 'pages/Account/LockedGnoVesting/hooks' import { ExtLink, @@ -43,6 +39,7 @@ import { VestingBreakdown, CardsLoader, CardsSpinner, + StyledAddToMetamask, } from 'pages/Account/styled' import LockedGnoVesting from './LockedGnoVesting' @@ -285,7 +282,7 @@ export default function Profile() { View contract ↗ - {isMetaMask && !isProviderNetworkUnsupported && } + {isMetaMask && !isProviderNetworkUnsupported && } {!isMetaMask && ( diff --git a/apps/cowswap-frontend/src/pages/Account/Governance.tsx b/apps/cowswap-frontend/src/pages/Account/Governance.tsx index 5ea6b8832f..5d20432fe4 100644 --- a/apps/cowswap-frontend/src/pages/Account/Governance.tsx +++ b/apps/cowswap-frontend/src/pages/Account/Governance.tsx @@ -1,4 +1,4 @@ -import CowProtocolImage from 'legacy/assets/cow-swap/cowprotocol.svg' +import CowProtocolImage from '@cowprotocol/assets/cow-swap/cowprotocol.svg' import { ExtLink, BannerCard, BannerCardContent, BannerCardSvg, CardActions } from './styled' diff --git a/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/hooks.ts b/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/hooks.ts index 84438a7dae..c0810359fb 100644 --- a/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/hooks.ts +++ b/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/hooks.ts @@ -1,32 +1,35 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { MerkleDrop, TokenDistro, MerkleDropAbi, TokenDistroAbi } from '@cowprotocol/abis' +import { + COW, + LOCKED_GNO_VESTING_DURATION, + LOCKED_GNO_VESTING_START_TIME, + MERKLE_DROP_CONTRACT_ADDRESSES, + TOKEN_DISTRO_CONTRACT_ADDRESSES, +} from '@cowprotocol/common-const' +import { useContract } from '@cowprotocol/common-hooks' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { MerkleDrop, TokenDistro, MerkleDropAbi, TokenDistroAbi } from '@cowswap/abis' +import { useWalletInfo } from '@cowprotocol/wallet' import { ContractTransaction } from '@ethersproject/contracts' import { CurrencyAmount, Token } from '@uniswap/sdk-core' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' -import { LOCKED_GNO_VESTING_START_TIME, LOCKED_GNO_VESTING_DURATION } from 'legacy/constants' -import { COW as COW_TOKENS } from 'legacy/constants/tokens' -import { MERKLE_DROP_CONTRACT_ADDRESSES, TOKEN_DISTRO_CONTRACT_ADDRESSES } from 'legacy/constants/tokens' -import { useContract } from 'legacy/hooks/useContract' import { useTransactionAdder } from 'legacy/state/enhancedTransactions/hooks' - -import { useWalletInfo } from 'modules/wallet' +import { ConfirmOperationType } from 'legacy/state/types' import { useSingleCallResult } from 'lib/hooks/multicall' import { fetchClaim } from './claimData' // We just generally use the mainnet version. We don't read from the contract anyways so the address doesn't matter -const COW = COW_TOKENS[SupportedChainId.MAINNET] +const _COW = COW[SupportedChainId.MAINNET] const useMerkleDropContract = () => useContract(MERKLE_DROP_CONTRACT_ADDRESSES, MerkleDropAbi, true) const useTokenDistroContract = () => useContract(TOKEN_DISTRO_CONTRACT_ADDRESSES, TokenDistroAbi, true) export const useAllocation = (): CurrencyAmount => { const { chainId, account } = useWalletInfo() - const initialAllocation = useRef(CurrencyAmount.fromRawAmount(COW, 0)) + const initialAllocation = useRef(CurrencyAmount.fromRawAmount(_COW, 0)) const [allocation, setAllocation] = useState(initialAllocation.current) useEffect(() => { @@ -34,7 +37,7 @@ export const useAllocation = (): CurrencyAmount => { if (account && chainId) { fetchClaim(account, chainId).then((claim) => { if (!canceled) { - setAllocation(CurrencyAmount.fromRawAmount(COW, claim?.amount ?? 0)) + setAllocation(CurrencyAmount.fromRawAmount(_COW, claim?.amount ?? 0)) } }) } else { @@ -59,7 +62,7 @@ export const useCowFromLockedGnoBalances = () => { const { result, loading } = useSingleCallResult(allocated.greaterThan(0) ? tokenDistro : null, 'balances', [ account ?? undefined, ]) - const claimed = useMemo(() => CurrencyAmount.fromRawAmount(COW, result ? result.claimed.toString() : 0), [result]) + const claimed = useMemo(() => CurrencyAmount.fromRawAmount(_COW, result ? result.claimed.toString() : 0), [result]) return { allocated, diff --git a/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx b/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx index bcd3ad354f..372e71f18f 100644 --- a/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx +++ b/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx @@ -1,32 +1,35 @@ import { useCallback, useState, useEffect } from 'react' +import { claimAnalytics } from '@cowprotocol/analytics' +import ArrowIcon from '@cowprotocol/assets/cow-swap/arrow.svg' +import cowImage from '@cowprotocol/assets/cow-swap/cow_v2.svg' +import { + LOCKED_GNO_VESTING_START_DATE, + MERKLE_DROP_CONTRACT_ADDRESSES, + TOKEN_DISTRO_CONTRACT_ADDRESSES, +} from '@cowprotocol/common-const' +import { usePrevious } from '@cowprotocol/common-hooks' +import { + formatDateWithTimezone, + getBlockExplorerUrl, + getProviderErrorMessage, + isRejectRequestProviderError, +} from '@cowprotocol/common-utils' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' +import { ButtonSize, TokenAmount, ButtonPrimary } from '@cowprotocol/ui' +import { MouseoverTooltipContent } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount, Currency } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import SVG from 'react-inlinesvg' -import ArrowIcon from 'legacy/assets/cow-swap/arrow.svg' -import cowImage from 'legacy/assets/cow-swap/cow_v2.svg' -import { claimAnalytics } from 'legacy/components/analytics' -import { ButtonPrimary } from 'legacy/components/Button' import CopyHelper from 'legacy/components/Copy' -import { MouseoverTooltipContent } from 'legacy/components/Tooltip' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' -import { LOCKED_GNO_VESTING_START_DATE } from 'legacy/constants' -import { MERKLE_DROP_CONTRACT_ADDRESSES, TOKEN_DISTRO_CONTRACT_ADDRESSES } from 'legacy/constants/tokens' import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal' -import usePrevious from 'legacy/hooks/usePrevious' -import { ButtonSize } from 'legacy/theme/enum' -import { getBlockExplorerUrl } from 'legacy/utils' -import { getProviderErrorMessage, isRejectRequestProviderError } from 'legacy/utils/misc' - -import { useWalletInfo } from 'modules/wallet' +import { ConfirmOperationType } from 'legacy/state/types' import { HelpCircle } from 'common/pure/HelpCircle' -import { TokenAmount } from 'common/pure/TokenAmount' import { Card, BalanceDisplay, ConvertWrapper, VestingBreakdown, CardActions, ExtLink } from 'pages/Account/styled' -import { formatDateWithTimezone } from 'utils/time' import { useClaimCowFromLockedGnoCallback } from './hooks' diff --git a/apps/cowswap-frontend/src/pages/Account/Menu.tsx b/apps/cowswap-frontend/src/pages/Account/Menu.tsx index c38569b496..c358e6f6f4 100644 --- a/apps/cowswap-frontend/src/pages/Account/Menu.tsx +++ b/apps/cowswap-frontend/src/pages/Account/Menu.tsx @@ -1,7 +1,8 @@ +import { ACCOUNT_MENU_LINKS } from '@cowprotocol/common-const' + import { NavLink } from 'react-router-dom' import { SideMenu } from 'legacy/components/SideMenu' -import { ACCOUNT_MENU_LINKS } from 'legacy/constants' export function AccountMenu() { return ( diff --git a/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx b/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx index e68d39aa4e..5df883e2b6 100644 --- a/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx +++ b/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx @@ -1,5 +1,8 @@ import { useEffect, useMemo, useState, useCallback, useRef, ChangeEventHandler } from 'react' +import { useDebounce, useOnClickOutside, usePrevious, useTheme } from '@cowprotocol/common-hooks' +import { isAddress, isTruthy } from '@cowprotocol/common-utils' +import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' import { useWeb3React } from '@web3-react/core' @@ -11,19 +14,11 @@ import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { ContentWrapper as SearchInputFormatter } from 'legacy/components/SearchModal/CurrencySearch' import { TokenSearchInput } from 'legacy/components/Tokens/styled' import TokensTable from 'legacy/components/Tokens/TokensTable' -import { useAllTokens } from 'legacy/hooks/Tokens' -import useDebounce from 'legacy/hooks/useDebounce' -import { useOnClickOutside } from 'legacy/hooks/useOnClickOutside' -import usePrevious from 'legacy/hooks/usePrevious' -import useTheme from 'legacy/hooks/useTheme' -import { useAllTokenBalances } from 'legacy/state/connection/hooks' +import { useAllTokenBalances, useAllTokens } from 'legacy/hooks/Tokens' import { useFavouriteTokens, useRemoveAllFavouriteTokens, useInitFavouriteTokens } from 'legacy/state/user/hooks' import { CloseIcon } from 'legacy/theme' -import { isAddress } from 'legacy/utils' -import { isTruthy } from 'legacy/utils/misc' import { PageTitle } from 'modules/application/containers/PageTitle' -import { useWalletInfo } from 'modules/wallet' import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' diff --git a/apps/cowswap-frontend/src/pages/Account/styled.tsx b/apps/cowswap-frontend/src/pages/Account/styled.tsx index 1a831b8101..ab2e53a4d2 100644 --- a/apps/cowswap-frontend/src/pages/Account/styled.tsx +++ b/apps/cowswap-frontend/src/pages/Account/styled.tsx @@ -1,17 +1,15 @@ -import * as CSS from 'csstype' +import { Loader as SpinnerLoader, ButtonPrimary } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' + import { transparentize } from 'polished' import SVG from 'react-inlinesvg' import styled, { css } from 'styled-components/macro' -import { ButtonPrimary } from 'legacy/components/Button' import { CopyIcon as ClickToCopy } from 'legacy/components/Copy' -import SpinnerLoader from 'legacy/components/Loader' -import { ExternalLink } from 'legacy/theme' import { Page, GdocsListStyle } from 'modules/application/pure/Page' -import { ButtonCustom as AddToMetaMask } from 'modules/wallet/api/pure/AddToMetamask' +import { AddToMetamask } from 'modules/wallet/containers/AddToMetamask' -import { UI } from 'common/constants/theme' import { BannerExplainer } from 'pages/Claim/styled' export const Container = styled.div` @@ -30,7 +28,7 @@ export const Wrapper = styled(Page)` justify-content: flex-end; flex-flow: column wrap; margin: 0; - background: var(${UI.COLOR_CONTAINER_BG_01}); + background: ${({ theme }) => theme.bg1}; box-shadow: ${({ theme }) => theme.boxShadow1}; border: none; @@ -56,138 +54,59 @@ export const ExtLink = styled(ExternalLink)` } ` -export const ChildWrapper = styled.div` +const linkMixin = css` + font-size: 13px; + height: 100%; + font-weight: 500; + border-radius: 0; + min-height: initial; + margin: 0; + padding: 0; + line-height: 1; + color: ${({ theme }) => transparentize(0.3, theme.text1)}; display: flex; - flex-direction: column; align-items: center; - flex-grow: 1; - justify-content: center; - border-radius: 21px; - padding: 20px; - background-color: var(${UI.COLOR_GREY}); + text-decoration: underline; + text-decoration-color: transparent; + transition: text-decoration-color 0.2s ease-in-out, color 0.2s ease-in-out; - ${({ theme }) => theme.mediaWidth.upToSmall` - grid-column-start: 1; - grid-column-end: 2; - width: 100%; - padding: 14px; - `} + ${({ theme }) => theme.mediaWidth.upToMedium` + font-size: 15px; + margin: 0 auto; + `}; - > .item { - width: 100%; + &:hover { + text-decoration-color: ${({ theme }) => theme.text1}; + color: ${({ theme }) => theme.text1}; } ` -export const GridWrap = styled.div>` - display: grid; - grid-column-gap: 22px; - grid-row-gap: 22px; - grid-template-columns: ${(props) => (props.horizontal ? '1fr 1fr' : '1fr')}; +export const StyledAddToMetamask = styled(AddToMetamask)` + border: 0; + min-height: initial; + border-radius: initial; - ${({ theme }) => theme.mediaWidth.upToSmall` - grid-template-columns: 1fr; - grid-column-gap: 0; - > :first-child, - > :nth-child(2) { - grid-column-start: 1; - grid-column-end: 2; - } - `} + &:hover { + background: transparent; - @supports (-webkit-touch-callout: none) { - /* CSS specific to iOS devices */ - display: flex; - flex-direction: column; + > div { + text-decoration: underline; + } } -` - -export const CardHead = styled.div` - display: flex; - flex-grow: 1; - flex-direction: column; -` -export const StyledTime = styled.p` - margin: 0; -` - -export const ItemTitle = styled.h3` - display: flex; - align-items: center; - margin: 0 0 16px 0; - font-size: 18px; - line-height: 1.21; - color: var(${UI.COLOR_TEXT1}); - gap: 4px; - - ${({ theme }) => theme.mediaWidth.upToSmall` - margin: 0 0 10px 0; - font-size: 16px; - `} -` - -export const FlexWrap = styled.div` - display: flex; - flex-grow: 1; - align-items: center; - flex-direction: row; - justify-content: center; - - > div { + > div > img, + > div > svg { + height: 13px; width: auto; + object-fit: contain; + margin: 0 6px 0 0; } - button { - max-width: 180px; - } - - ${({ theme }) => theme.mediaWidth.upToSmall` - flex-wrap: wrap; - > div { - width: 50%; - } - button { - max-width: 100%; - } - `} + ${linkMixin} ` -export const StyledContainer = styled.div` - display: flex; - flex: 1; - align-items: center; - justify-content: space-between; - - ${({ theme }) => theme.mediaWidth.upToSmall` - flex-wrap: wrap; - flex-direction: column; - `} -` - -export const FlexCol = styled.div` - display: flex; - flex-grow: 1; - align-items: center; - flex-direction: column; - justify-content: center; - - strong { - font-size: 21px; - margin-top: 6px; - - ${({ theme }) => theme.mediaWidth.upToSmall` - font-size: 14px; - `} - } - - span:not([role='img']) { - font-size: 14px; - color: ${({ theme }) => transparentize(0.3, theme.text1)}; - text-align: center; - display: flex; - align-items: center; - padding: 8px 0 0 0; - } +export const StyledTime = styled.p` + margin: 0; ` export const Loader = styled.div<{ isLoading: boolean }>` @@ -213,29 +132,6 @@ export const Loader = styled.div<{ isLoading: boolean }>` `} ` -export const ProfileGridWrap = styled(GridWrap)` - grid-template-columns: 1fr auto; - justify-content: space-between; - align-items: center; - - ${({ theme }) => theme.mediaWidth.upToSmall` - > :first-child, - > :nth-child(2) { - grid-column-start: auto; - grid-column-end: auto; - } - `}; - - ${({ theme }) => theme.mediaWidth.upToVerySmall` - > :first-child, - > :nth-child(2) { - grid-column-start: 1; - grid-column-end: 1; - } - grid-row-gap: 0px; - `}; -` - export const CardsWrapper = styled.div` display: flex; flex-flow: row wrap; @@ -272,7 +168,7 @@ export const Card = styled.div<{ showLoader?: boolean }>` flex: 1; min-height: 192px; margin: 0; - background: var(${UI.COLOR_CONTAINER_BG_01}); + background: ${({ theme }) => theme.bg1}; box-shadow: none; padding: 24px; gap: 24px 0; @@ -327,7 +223,7 @@ export const Card = styled.div<{ showLoader?: boolean }>` export const BannerCard = styled(BannerExplainer)` min-height: 192px; border-radius: 16px; - background: var(${UI.COLOR_CONTAINER_BG_01}); + background: ${({ theme }) => theme.bg1}; border: none; padding: 0 100px 0 24px; flex: 1; @@ -347,7 +243,7 @@ export const BannerCard = styled(BannerExplainer)` justify-content: space-between; height: 100%; padding: 24px 0; - color: var(${UI.COLOR_TEXT1}); + color: ${({ theme }) => theme.text1}; ${({ theme }) => theme.mediaWidth.upToSmall` padding: 0; @@ -363,7 +259,7 @@ export const BannerCard = styled(BannerExplainer)` } @supports not (-webkit-background-clip: text) { - color: var(${UI.COLOR_TEXT1}); + color: ${({ theme }) => theme.text1}; } ${({ theme }) => theme.mediaWidth.upToSmall` @@ -373,7 +269,7 @@ export const BannerCard = styled(BannerExplainer)` } > small { - color: var(${UI.COLOR_TEXT1}); + color: ${({ theme }) => theme.text1}; font-size: 14px; line-height: 1.5; text-align: left; @@ -403,7 +299,7 @@ export const BannerCard = styled(BannerExplainer)` > span > a, > span > a:link { font-size: 15px; - color: var(${UI.COLOR_TEXT1}); + color: ${({ theme }) => theme.text1}; &:hover { color: ${({ theme }) => theme.text3}; @@ -421,14 +317,14 @@ export const BannerCard = styled(BannerExplainer)` > svg { .stop1 { - stop-color: var(${UI.COLOR_TEXT1}); + stop-color: ${({ theme }) => theme.text1}; } .stop2 { - stop-color: var(${UI.COLOR_TEXT1}); + stop-color: ${({ theme }) => theme.text1}; stop-opacity: 0.8; } .stop3 { - stop-color: var(${UI.COLOR_TEXT1}); + stop-color: ${({ theme }) => theme.text1}; stop-opacity: 0; } } @@ -456,53 +352,8 @@ export const CardActions = styled.div<{ justify?: string; content?: string }>` `}; > a, - ${AddToMetaMask}, > ${ClickToCopy} { - font-size: 13px; - height: 100%; - font-weight: 500; - border-radius: 0; - min-height: initial; - margin: 0; - padding: 0; - line-height: 1; - color: ${({ theme }) => transparentize(0.3, theme.text1)}; - display: flex; - align-items: center; - text-decoration: underline; - text-decoration-color: transparent; - transition: text-decoration-color 0.2s ease-in-out, color 0.2s ease-in-out; - - ${({ theme }) => theme.mediaWidth.upToMedium` - font-size: 15px; - margin: 0 auto; - `}; - - &:hover { - text-decoration-color: var(${UI.COLOR_TEXT1}); - color: var(${UI.COLOR_TEXT1}); - } - } - - ${AddToMetaMask} { - border: 0; - min-height: initial; - border-radius: initial; - - &:hover { - background: transparent; - - > div { - text-decoration: underline; - } - } - - > div > img, - > div > svg { - height: 13px; - width: auto; - object-fit: contain; - margin: 0 6px 0 0; - } + > ${ClickToCopy} { + ${linkMixin} } > ${ClickToCopy} svg { @@ -589,7 +440,7 @@ export const ConvertWrapper = styled.div` display: grid; grid-template-columns: 1fr 200px; align-items: center; - background: var(${UI.COLOR_GREY}); + background: ${({ theme }) => theme.grey1}; border-radius: 16px; padding: 16px; width: 100%; @@ -630,7 +481,7 @@ export const VestingBreakdown = styled.div` } > span:last-of-type > p { - color: var(${UI.COLOR_TEXT1}); + color: ${({ theme }) => theme.text1}; } ` @@ -667,34 +518,6 @@ export const CardsSpinner = styled(SpinnerLoader)` margin: auto; & path { - stroke: var(${UI.COLOR_TEXT1}); + stroke: ${({ theme }) => theme.text1}; } ` - -interface TimeProps { - date: string | undefined -} - -export const TimeFormatted = ({ date }: TimeProps) => { - if (!date) return null - - const months = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', - ] - const _date = new Date(date) - const monthName = months[_date.getMonth()] - const hours = _date.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) - - return {`${_date.getDate()} ${monthName} ${_date.getFullYear()} - ${hours}`} -} diff --git a/apps/cowswap-frontend/src/pages/Claim/CanUserClaimMessage.tsx b/apps/cowswap-frontend/src/pages/Claim/CanUserClaimMessage.tsx index 09a1c14838..7605a44820 100644 --- a/apps/cowswap-frontend/src/pages/Claim/CanUserClaimMessage.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/CanUserClaimMessage.tsx @@ -1,17 +1,17 @@ +import CowProtocolImage from '@cowprotocol/assets/cow-swap/cowprotocol.svg' +import { useNetworkName } from '@cowprotocol/common-hooks' +import { formatDateWithTimezone } from '@cowprotocol/common-utils' +import { ButtonSecondary } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' import SVG from 'react-inlinesvg' -import CowProtocolImage from 'legacy/assets/cow-swap/cowprotocol.svg' -import { ButtonSecondary } from 'legacy/components/Button' -import useNetworkName from 'legacy/hooks/useNetworkName' import { ClaimStatus } from 'legacy/state/claim/actions' import { useClaimState, useClaimTimeInfo, useClaimLinks } from 'legacy/state/claim/hooks' -import { ExternalLink } from 'legacy/theme' - -import { formatDateWithTimezone } from 'utils/time' +import { ClaimCommonTypes } from 'legacy/state/claim/types' import { IntroDescription, BannerExplainer } from './styled' -import { ClaimCommonTypes } from './types' type ClaimIntroductionProps = Pick< ClaimCommonTypes, diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimAddress.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimAddress.tsx index cf029380e2..54401255a2 100644 --- a/apps/cowswap-frontend/src/pages/Claim/ClaimAddress.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/ClaimAddress.tsx @@ -1,16 +1,17 @@ import { useMemo } from 'react' +import Circle from '@cowprotocol/assets/images/blue-loader.svg' +import { useENS } from '@cowprotocol/ens' +import { ButtonSecondary } from '@cowprotocol/ui' + import { Trans } from '@lingui/macro' -import Circle from 'legacy/assets/images/blue-loader.svg' -import { ButtonSecondary } from 'legacy/components/Button' -import useENS from 'legacy/hooks/useENS' import { ClaimStatus } from 'legacy/state/claim/actions' import { useClaimDispatchers, useClaimState } from 'legacy/state/claim/hooks' +import { ClaimCommonTypes } from 'legacy/state/claim/types' import { CustomLightSpinner, ThemedText } from 'legacy/theme' import { CheckAddress, InputField, InputFieldTitle, InputErrorText } from './styled' -import { ClaimCommonTypes } from './types' export type ClaimAddressProps = Pick & { toggleWalletModal: () => void diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimBanner.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimBanner.tsx index 5de79e8536..15aa79456e 100644 --- a/apps/cowswap-frontend/src/pages/Claim/ClaimBanner.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/ClaimBanner.tsx @@ -1,12 +1,12 @@ +import CheckCircle from '@cowprotocol/assets/cow-swap/check.svg' +import { useNetworkName } from '@cowprotocol/common-hooks' + import { Trans } from '@lingui/macro' import SVG from 'react-inlinesvg' -import CheckCircle from 'legacy/assets/cow-swap/check.svg' -import useNetworkName from 'legacy/hooks/useNetworkName' import { ClaimStatus } from 'legacy/state/claim/actions' import { useClaimState } from 'legacy/state/claim/hooks' - -import { ClaimCommonTypes } from 'pages/Claim/types' +import { ClaimCommonTypes } from 'legacy/state/claim/types' import { ClaimBanner as ClaimBannerWrapper } from './styled' diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimNav.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimNav.tsx index 8079e2bdbc..356e317e2f 100644 --- a/apps/cowswap-frontend/src/pages/Claim/ClaimNav.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/ClaimNav.tsx @@ -1,13 +1,13 @@ -import { ButtonSecondary } from 'legacy/components/Button' +import { shortenAddress } from '@cowprotocol/common-utils' +import { ButtonSecondary } from '@cowprotocol/ui' +import { Identicon } from '@cowprotocol/wallet' + import CopyHelper from 'legacy/components/Copy' import { ClaimStatus } from 'legacy/state/claim/actions' import { useClaimDispatchers, useClaimState } from 'legacy/state/claim/hooks' -import { shortenAddress } from 'legacy/utils' - -import { Identicon } from 'modules/wallet/api/container/Identicon' +import { ClaimCommonTypes } from 'legacy/state/claim/types' import { TopNav, ClaimAccount, ClaimAccountButtons } from './styled' -import { ClaimCommonTypes } from './types' type ClaimNavProps = Pick diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimSummary.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimSummary.tsx index b29f27c32b..e0590b6155 100644 --- a/apps/cowswap-frontend/src/pages/Claim/ClaimSummary.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/ClaimSummary.tsx @@ -1,20 +1,19 @@ +import { V_COW } from '@cowprotocol/common-const' +import { TokenAmount } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount, Currency, Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import JSBI from 'jsbi' import CowProtocolLogo from 'legacy/components/CowProtocolLogo' -import { V_COW } from 'legacy/constants/tokens' import { ClaimStatus } from 'legacy/state/claim/actions' import { useClaimState } from 'legacy/state/claim/hooks' +import { ClaimCommonTypes } from 'legacy/state/claim/types' import { useTokenBalance } from 'modules/tokens/hooks/useCurrencyBalance' -import { useWalletInfo } from 'modules/wallet' - -import { TokenAmount } from 'common/pure/TokenAmount' import { ClaimSummary as ClaimSummaryWrapper, ClaimSummaryTitle, ClaimTotal } from './styled' -import { ClaimCommonTypes } from './types' type ClaimSummaryProps = Pick & { unclaimedAmount: ClaimCommonTypes['tokenCurrencyAmount'] | undefined diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimingStatus.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimingStatus.tsx index 984f7dfcb3..35b1c9692a 100644 --- a/apps/cowswap-frontend/src/pages/Claim/ClaimingStatus.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/ClaimingStatus.tsx @@ -1,31 +1,31 @@ import { useMemo } from 'react' +import CowProtocolIcon from '@cowprotocol/assets/cow-swap/cowprotocol.svg' +import discordImage from '@cowprotocol/assets/cow-swap/discord.svg' +import twitterImage from '@cowprotocol/assets/cow-swap/twitter.svg' +import { V_COW } from '@cowprotocol/common-const' +import { shortenAddress } from '@cowprotocol/common-utils' +import { TokenAmount, ButtonSecondary } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import SVG from 'react-inlinesvg' import { Link } from 'react-router-dom' -import CowProtocolIcon from 'legacy/assets/cow-swap/cowprotocol.svg' -import discordImage from 'legacy/assets/cow-swap/discord.svg' -import twitterImage from 'legacy/assets/cow-swap/twitter.svg' -import { ButtonSecondary } from 'legacy/components/Button' import CopyHelper from 'legacy/components/Copy' import CowProtocolLogo from 'legacy/components/CowProtocolLogo' import { EnhancedTransactionLink } from 'legacy/components/EnhancedTransactionLink' import { ExplorerLink } from 'legacy/components/ExplorerLink' -import { V_COW } from 'legacy/constants/tokens' import { ClaimStatus } from 'legacy/state/claim/actions' import { useClaimDispatchers, useClaimState } from 'legacy/state/claim/hooks' +import { ClaimCommonTypes } from 'legacy/state/claim/types' import { useAllClaimingTransactions } from 'legacy/state/enhancedTransactions/hooks' -import { ExternalLink } from 'legacy/theme' -import { shortenAddress } from 'legacy/utils' -import { useWalletInfo } from 'modules/wallet' -import AddToMetamask from 'modules/wallet/web3-react/containers/AddToMetamask' +import { AddToMetamask } from 'modules/wallet/containers/AddToMetamask' import { Routes } from 'common/constants/routes' -import { TokenAmount } from 'common/pure/TokenAmount' import { ConfirmOrLoadingWrapper, ConfirmedIcon, @@ -35,8 +35,6 @@ import { SuccessBanner, } from 'pages/Claim/styled' -import { ClaimCommonTypes } from './types' - const COW_TWEET_TEMPLATE = 'I just joined the 🐮 CoWmunity @CoWSwap and claimed my first vCOW tokens! Join me at https://swap.cow.fi/' diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimsOnOtherChainsBanner.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimsOnOtherChainsBanner.tsx index a2dde0130d..db278cd3ae 100644 --- a/apps/cowswap-frontend/src/pages/Claim/ClaimsOnOtherChainsBanner.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/ClaimsOnOtherChainsBanner.tsx @@ -1,6 +1,7 @@ import { useMemo } from 'react' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { AlertTriangle } from 'react-feather' import styled from 'styled-components/macro' @@ -9,8 +10,6 @@ import NotificationBanner from 'legacy/components/NotificationBanner' import { useClaimState } from 'legacy/state/claim/hooks' import { ClaimInfo } from 'legacy/state/claim/reducer' -import { useWalletInfo } from 'modules/wallet' - // const ChainSpan = styled.span`` const Wrapper = styled.div` display: flex; diff --git a/apps/cowswap-frontend/src/pages/Claim/ClaimsTable.tsx b/apps/cowswap-frontend/src/pages/Claim/ClaimsTable.tsx index 789dd7d340..3f0eba9c31 100644 --- a/apps/cowswap-frontend/src/pages/Claim/ClaimsTable.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/ClaimsTable.tsx @@ -1,30 +1,25 @@ import { useEffect } from 'react' +import CowProtocolImage from '@cowprotocol/assets/cow-swap/cowprotocol.svg' +import Circle from '@cowprotocol/assets/images/blue-loader.svg' +import { TokenAmount } from '@cowprotocol/ui' +import { ExternalLink } from '@cowprotocol/ui' + import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import CowProtocolImage from 'legacy/assets/cow-swap/cowprotocol.svg' -import Circle from 'legacy/assets/images/blue-loader.svg' import CowProtocolLogo from 'legacy/components/CowProtocolLogo' import { ClaimStatus } from 'legacy/state/claim/actions' -import { - ClaimType, - useClaimDispatchers, - useClaimState, - useClaimTimeInfo, - useClaimLinks, -} from 'legacy/state/claim/hooks' +import { useClaimDispatchers, useClaimState, useClaimTimeInfo, useClaimLinks } from 'legacy/state/claim/hooks' +import { ClaimType } from 'legacy/state/claim/hooks/types' import { getPaidClaims, getIndexes } from 'legacy/state/claim/hooks/utils' +import { ClaimCommonTypes, EnhancedUserClaimData } from 'legacy/state/claim/types' import { useAllClaimingTransactionIndices } from 'legacy/state/enhancedTransactions/hooks' import { CustomLightSpinner } from 'legacy/theme' -import { ExternalLink } from 'legacy/theme' -import { TokenAmount } from 'common/pure/TokenAmount' import { Countdown } from 'pages/Claim/Countdown' import { ClaimTable, ClaimBreakdown, TokenLogo, BannerExplainer } from 'pages/Claim/styled' -import { ClaimCommonTypes, EnhancedUserClaimData } from './types' - export type ClaimsTableProps = Pick // TODO: fix in other pr diff --git a/apps/cowswap-frontend/src/pages/Claim/FooterNavButtons.tsx b/apps/cowswap-frontend/src/pages/Claim/FooterNavButtons.tsx index 6cb6feb30a..2f679a05c7 100644 --- a/apps/cowswap-frontend/src/pages/Claim/FooterNavButtons.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/FooterNavButtons.tsx @@ -1,10 +1,11 @@ import { ReactNode, useEffect, useRef } from 'react' +import { ButtonPrimary, ButtonSecondary } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { isAddress } from '@ethersproject/address' import { Trans } from '@lingui/macro' -import { ButtonPrimary, ButtonSecondary } from 'legacy/components/Button' import { ClaimStatus } from 'legacy/state/claim/actions' import { useClaimDispatchers, @@ -12,10 +13,7 @@ import { useHasClaimInvestmentFlowError, useHasZeroInvested, } from 'legacy/state/claim/hooks' - -import { useWalletInfo } from 'modules/wallet' - -import { ClaimCommonTypes } from 'pages/Claim/types' +import { ClaimCommonTypes } from 'legacy/state/claim/types' import { ClaimAddressProps } from './ClaimAddress' import { FooterNavButtons as FooterNavButtonsWrapper } from './styled' diff --git a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx index 15ce851919..aba0b53bd0 100644 --- a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestOption.tsx @@ -1,40 +1,36 @@ import { useCallback, useEffect, useMemo, useState } from 'react' +import CheckCircle from '@cowprotocol/assets/cow-swap/check.svg' +import ImportantIcon from '@cowprotocol/assets/cow-swap/important.svg' +import { AVG_APPROVE_COST_GWEI, ONE_HUNDRED_PERCENT } from '@cowprotocol/common-const' +import { + calculateGasMargin, + getProviderErrorMessage, + tryParseCurrencyAmount, + formatTokenAmount, + formatSymbol, +} from '@cowprotocol/common-utils' +import { Loader, loadingOpacityMixin, ButtonSize, TokenAmount, ButtonConfirmed, Row } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { BigNumber } from '@ethersproject/bignumber' import { CurrencyAmount } from '@uniswap/sdk-core' import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import CheckCircle from 'legacy/assets/cow-swap/check.svg' -import ImportantIcon from 'legacy/assets/cow-swap/important.svg' -import { ButtonConfirmed } from 'legacy/components/Button' import CowProtocolLogo from 'legacy/components/CowProtocolLogo' -import Loader from 'legacy/components/Loader' -import { loadingOpacityMixin } from 'legacy/components/Loader/styled' import { Input as NumericalInput } from 'legacy/components/NumericalInput' -import Row from 'legacy/components/Row' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' -import { AVG_APPROVE_COST_GWEI } from 'legacy/constants' -import { ONE_HUNDRED_PERCENT } from 'legacy/constants/misc' import { useApproveCallbackFromClaim } from 'legacy/hooks/useApproveCallback' +import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal' import { useClaimDispatchers, useClaimState } from 'legacy/state/claim/hooks' import { calculateInvestmentAmounts, calculatePercentage } from 'legacy/state/claim/hooks/utils' +import { EnhancedUserClaimData } from 'legacy/state/claim/types' import { useGasPrices } from 'legacy/state/gas/hooks' -import { ButtonSize } from 'legacy/theme/enum' -import { calculateGasMargin } from 'legacy/utils/calculateGasMargin' -import { getProviderErrorMessage } from 'legacy/utils/misc' +import { ConfirmOperationType } from 'legacy/state/types' import useCurrencyBalance from 'modules/tokens/hooks/useCurrencyBalance' -import { useWalletInfo } from 'modules/wallet' -import { TokenAmount } from 'common/pure/TokenAmount' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' -import { formatTokenAmount } from 'utils/amountFormat' -import { formatSymbol } from 'utils/format' - -import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' import { IS_TESTING_ENV } from '../const' import { InvestAvailableBar, @@ -46,7 +42,6 @@ import { UserMessage, WarningWrapper, } from '../styled' -import { EnhancedUserClaimData } from '../types' import { InvestmentFlowProps } from '.' diff --git a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestSummaryRow.tsx b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestSummaryRow.tsx index 05f7a6dadb..1cc4743f68 100644 --- a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestSummaryRow.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/InvestSummaryRow.tsx @@ -1,14 +1,15 @@ +import ImportantIcon from '@cowprotocol/assets/cow-swap/important.svg' +import { ONE_HUNDRED_PERCENT } from '@cowprotocol/common-const' +import { TokenAmount } from '@cowprotocol/ui' + import SVG from 'react-inlinesvg' -import ImportantIcon from 'legacy/assets/cow-swap/important.svg' import CowProtocolLogo from 'legacy/components/CowProtocolLogo' -import { ONE_HUNDRED_PERCENT } from 'legacy/constants/misc' -import { ClaimType } from 'legacy/state/claim/hooks' +import { ClaimType } from 'legacy/state/claim/hooks/types' import { calculatePercentage } from 'legacy/state/claim/hooks/utils' +import { ClaimWithInvestmentData } from 'legacy/state/claim/types' -import { TokenAmount } from 'common/pure/TokenAmount' import { TokenLogo, InvestAvailableBar, UserMessage } from 'pages/Claim/styled' -import { ClaimWithInvestmentData } from 'pages/Claim/types' export type Props = { claim: ClaimWithInvestmentData } diff --git a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx index ab5a2758f9..0b48baa463 100644 --- a/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/InvestmentFlow/index.tsx @@ -1,18 +1,19 @@ import { useEffect, useMemo } from 'react' +import CowProtocolImage from '@cowprotocol/assets/cow-swap/cowprotocol.svg' +import ImportantIcon from '@cowprotocol/assets/cow-swap/important.svg' +import RoundArrow from '@cowprotocol/assets/cow-swap/round-arrow.svg' import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { ExternalLink } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' import { CurrencyAmount } from '@uniswap/sdk-core' import SVG from 'react-inlinesvg' -import CowProtocolImage from 'legacy/assets/cow-swap/cowprotocol.svg' -import ImportantIcon from 'legacy/assets/cow-swap/important.svg' -import RoundArrow from 'legacy/assets/cow-swap/round-arrow.svg' import { BadgeVariant } from 'legacy/components/Badge' import { ExplorerLink } from 'legacy/components/ExplorerLink' import { FaqDrawer } from 'legacy/components/FaqDrawer' import { Stepper } from 'legacy/components/Stepper' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' import { ClaimStatus } from 'legacy/state/claim/actions' import { useClaimState, @@ -23,9 +24,8 @@ import { } from 'legacy/state/claim/hooks' import { calculateInvestmentAmounts } from 'legacy/state/claim/hooks/utils' import { InvestClaim } from 'legacy/state/claim/reducer' -import { ExternalLink } from 'legacy/theme' - -import { useWalletInfo } from 'modules/wallet' +import { ClaimCommonTypes, ClaimWithInvestmentData, EnhancedUserClaimData } from 'legacy/state/claim/types' +import { ConfirmOperationType } from 'legacy/state/types' import { ClaimSummaryView } from 'pages/Claim/ClaimSummary' import { InvestSummaryRow } from 'pages/Claim/InvestmentFlow/InvestSummaryRow' @@ -43,8 +43,6 @@ import { import InvestOption from './InvestOption' -import { ClaimCommonTypes, ClaimWithInvestmentData, EnhancedUserClaimData } from '../types' - const STEPS_DATA = [ { title: 'Start', diff --git a/apps/cowswap-frontend/src/pages/Claim/const.ts b/apps/cowswap-frontend/src/pages/Claim/const.ts index 071a062a96..d377de27ce 100644 --- a/apps/cowswap-frontend/src/pages/Claim/const.ts +++ b/apps/cowswap-frontend/src/pages/Claim/const.ts @@ -1,3 +1,3 @@ -import { isProd, isEns, isBarn } from 'legacy/utils/environments' +import { isProd, isEns, isBarn } from '@cowprotocol/common-utils' export const IS_TESTING_ENV = !isProd && !isEns && !isBarn diff --git a/apps/cowswap-frontend/src/pages/Claim/index.tsx b/apps/cowswap-frontend/src/pages/Claim/index.tsx index b2e71d4d4a..15d1b068fb 100644 --- a/apps/cowswap-frontend/src/pages/Claim/index.tsx +++ b/apps/cowswap-frontend/src/pages/Claim/index.tsx @@ -1,26 +1,22 @@ import { useCallback, useEffect, useMemo } from 'react' +import { usePrevious } from '@cowprotocol/common-hooks' +import { getProviderErrorMessage } from '@cowprotocol/common-utils' +import { useENS } from '@cowprotocol/ens' +import { Loader } from '@cowprotocol/ui' +import { useWalletInfo } from '@cowprotocol/wallet' + import Confetti from 'legacy/components/Confetti' -import Loader from 'legacy/components/Loader' -import { ConfirmOperationType } from 'legacy/components/TransactionConfirmationModal' -import useENS from 'legacy/hooks/useENS' import { useErrorModal } from 'legacy/hooks/useErrorMessageAndModal' -import usePrevious from 'legacy/hooks/usePrevious' import useTransactionConfirmationModal from 'legacy/hooks/useTransactionConfirmationModal' import { useToggleWalletModal } from 'legacy/state/application/hooks' import { ClaimStatus } from 'legacy/state/claim/actions' -import { - useUserEnhancedClaimData, - useUserUnclaimedAmount, - useClaimCallback, - ClaimInput, -} from 'legacy/state/claim/hooks' +import { useUserEnhancedClaimData, useUserUnclaimedAmount, useClaimCallback } from 'legacy/state/claim/hooks' import { useClaimDispatchers, useClaimState } from 'legacy/state/claim/hooks' +import { ClaimInput } from 'legacy/state/claim/hooks/types' import { getFreeClaims, hasPaidClaim, hasFreeClaim, prepareInvestClaims } from 'legacy/state/claim/hooks/utils' import ClaimsOnOtherChainsUpdater from 'legacy/state/claim/updater' -import { getProviderErrorMessage } from 'legacy/utils/misc' - -import { useWalletInfo } from 'modules/wallet' +import { ConfirmOperationType } from 'legacy/state/types' import { PageWrapper, InnerPageWrapper } from 'pages/Claim/styled' diff --git a/apps/cowswap-frontend/src/pages/Claim/styled.ts b/apps/cowswap-frontend/src/pages/Claim/styled.ts index 869f0557bd..78e2615587 100644 --- a/apps/cowswap-frontend/src/pages/Claim/styled.ts +++ b/apps/cowswap-frontend/src/pages/Claim/styled.ts @@ -1,13 +1,14 @@ +import LogoGNO from '@cowprotocol/assets/cow-swap/gno.png' +import LogoETH from '@cowprotocol/assets/cow-swap/network-mainnet-logo.svg' +import LogoUSDC from '@cowprotocol/assets/cow-swap/usdc.png' +import LogoXDAI from '@cowprotocol/assets/cow-swap/xdai.png' +import { ButtonPrimary, ButtonSecondary } from '@cowprotocol/ui' + import { transparentize, darken, lighten } from 'polished' import { CheckCircle, Frown } from 'react-feather' import styled from 'styled-components/macro' -import LogoGNO from 'legacy/assets/cow-swap/gno.png' -import LogoETH from 'legacy/assets/cow-swap/network-mainnet-logo.svg' -import LogoUSDC from 'legacy/assets/cow-swap/usdc.png' -import LogoXDAI from 'legacy/assets/cow-swap/xdai.png' import BadgeOriginal from 'legacy/components/Badge' -import { ButtonPrimary, ButtonSecondary } from 'legacy/components/Button' import { CopyIcon } from 'legacy/components/Copy' import { Icon } from 'legacy/components/CowProtocolLogo' import { Step } from 'legacy/components/Stepper' @@ -573,7 +574,11 @@ export const UserMessage = styled.div<{ variant?: string }>` > svg > path { fill: ${({ variant, theme }) => - variant === 'danger' ? `var(${UI.COLOR_DANGER})` : variant === 'info' ? theme.blue2 : darken(0.1, theme.attention)}; + variant === 'danger' + ? `var(${UI.COLOR_DANGER})` + : variant === 'info' + ? theme.blue2 + : darken(0.1, theme.attention)}; } > span { diff --git a/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx index 0c16e79461..a2c55ddcb0 100644 --- a/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx @@ -1,9 +1,10 @@ +import { BARN_URL, PRODUCTION_URL } from '@cowprotocol/common-const' + import { Link } from 'react-router-dom' import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { LinkScrollable } from 'legacy/components/Link' -import { BARN_URL, PRODUCTION_URL } from 'legacy/constants' import { PageTitle } from 'modules/application/containers/PageTitle' import { Page, Content } from 'modules/application/pure/Page' diff --git a/apps/cowswap-frontend/src/pages/Faq/Menu.tsx b/apps/cowswap-frontend/src/pages/Faq/Menu.tsx index c1bf435cc1..fdb72cff07 100644 --- a/apps/cowswap-frontend/src/pages/Faq/Menu.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/Menu.tsx @@ -1,7 +1,8 @@ +import { FAQ_MENU_LINKS } from '@cowprotocol/common-const' + import { NavLink } from 'react-router-dom' import { SideMenu } from 'legacy/components/SideMenu' -import { FAQ_MENU_LINKS } from 'legacy/constants' export function FaqMenu() { return ( diff --git a/apps/cowswap-frontend/src/pages/Faq/index.tsx b/apps/cowswap-frontend/src/pages/Faq/index.tsx index 28636aeda1..cb1f9dbfba 100644 --- a/apps/cowswap-frontend/src/pages/Faq/index.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/index.tsx @@ -1,7 +1,3 @@ -import { Link } from 'react-router-dom' - -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { GPAUDIT_LINK, COWWIKI_LINK, @@ -10,7 +6,12 @@ import { DISCORD_LINK, MEV_TOTAL, FLASHBOTS_LINK, -} from 'legacy/constants' +} from '@cowprotocol/common-const' + +import { Link } from 'react-router-dom' + +import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' +import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { StyledInternalLink } from 'legacy/theme' import { PageTitle } from 'modules/application/containers/PageTitle' diff --git a/apps/cowswap-frontend/src/pages/Faq/styled.tsx b/apps/cowswap-frontend/src/pages/Faq/styled.tsx index 0a4b92fd8a..33c972294e 100644 --- a/apps/cowswap-frontend/src/pages/Faq/styled.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/styled.tsx @@ -1,8 +1,10 @@ +import { ButtonPrimary } from '@cowprotocol/ui' +import { ExternalLink as ExternalLinkTheme } from '@cowprotocol/ui' + import { transparentize } from 'polished' import styled from 'styled-components/macro' -import { ButtonPrimary } from 'legacy/components/Button' -import { ExternalLink as ExternalLinkTheme, StyledInternalLink } from 'legacy/theme' +import { StyledInternalLink } from 'legacy/theme' import { Content } from 'modules/application/pure/Page' diff --git a/apps/cowswap-frontend/src/pages/KitchenSink/index.tsx b/apps/cowswap-frontend/src/pages/KitchenSink/index.tsx deleted file mode 100644 index c6a78abe46..0000000000 --- a/apps/cowswap-frontend/src/pages/KitchenSink/index.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { PinkTitle } from '@cowswap/ui' -import { CowSwapWidgetSettings } from '@cowswap/widget-lib' -import { CowSwapWidget, CowSwapWidgetParams } from '@cowswap/widget-react' - -import styled from 'styled-components/macro' - -import { Page, Title, Content } from 'modules/application/pure/Page' - -const Wrapper = styled(Page)`` - -export default function KitchenSink() { - const cowSwapWidgetParams: CowSwapWidgetParams = { - width: 600, - height: 700, - metaData: { - appKey: 'KitchenSink', - url: '/', - }, - } - - const cowSwapWidgetSettings: CowSwapWidgetSettings = { - urlParams: { - chainId: 1, - tradeType: 'swap', - env: 'local', - }, - appParams: {}, - } - - return ( - - Kitchen Sink - - pink title - - - - - ) -} diff --git a/apps/cowswap-frontend/src/pages/LimitOrders/index.tsx b/apps/cowswap-frontend/src/pages/LimitOrders/index.tsx index e0d3a54523..45fecd5aa4 100644 --- a/apps/cowswap-frontend/src/pages/LimitOrders/index.tsx +++ b/apps/cowswap-frontend/src/pages/LimitOrders/index.tsx @@ -2,6 +2,7 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' import { OrderClass } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' import { useOrders } from 'legacy/state/orders/hooks' @@ -19,7 +20,6 @@ import { import { OrdersTableWidget } from 'modules/ordersTable' import { TabOrderTypes } from 'modules/ordersTable/pure/OrdersTableContainer' import * as styledEl from 'modules/trade/pure/TradePageLayout' -import { useWalletInfo } from 'modules/wallet' import { getIsNotComposableCowOrder } from 'utils/orderUtils/getIsNotComposableCowOrder' diff --git a/apps/cowswap-frontend/src/pages/Swap/index.tsx b/apps/cowswap-frontend/src/pages/Swap/index.tsx index f1a2a56abd..02bcef39c6 100644 --- a/apps/cowswap-frontend/src/pages/Swap/index.tsx +++ b/apps/cowswap-frontend/src/pages/Swap/index.tsx @@ -1,15 +1,15 @@ import React from 'react' -import { Navigate, useLocation, useParams } from 'react-router-dom' +import { WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const' +import { useWalletInfo } from '@cowprotocol/wallet' -import { WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens' +import { Navigate, useLocation, useParams } from 'react-router-dom' import { AppDataUpdater } from 'modules/appData' import { SwapWidget, SwapDerivedStateUpdater, SwapAmountsFromUrlUpdater } from 'modules/swap' import { useSwapSlippage } from 'modules/swap/hooks/useSwapSlippage' import { getDefaultTradeRawState } from 'modules/trade/types/TradeRawState' import { parameterizeTradeRoute } from 'modules/trade/utils/parameterizeTradeRoute' -import { useWalletInfo } from 'modules/wallet' import { Routes } from 'common/constants/routes' diff --git a/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx b/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx index 8c490424fb..d6c3ebc51d 100644 --- a/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx +++ b/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx @@ -1,8 +1,8 @@ -import styled from 'styled-components/macro' +import cow404IMG from '@cowprotocol/assets/cow-swap/cow-404.png' +import { ButtonPrimary } from '@cowprotocol/ui' +import { ExternalLink as ExternalLinkTheme } from '@cowprotocol/ui' -import cow404IMG from 'legacy/assets/cow-swap/cow-404.png' -import { ButtonPrimary } from 'legacy/components/Button' -import { ExternalLink as ExternalLinkTheme } from 'legacy/theme' +import styled from 'styled-components/macro' import { Page, Title, Content, GdocsListStyle } from 'modules/application/pure/Page' diff --git a/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/useIsAnySwapAffectedUser.ts b/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/useIsAnySwapAffectedUser.ts index 78e4192481..62a2618fc0 100644 --- a/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/useIsAnySwapAffectedUser.ts +++ b/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/useIsAnySwapAffectedUser.ts @@ -1,15 +1,13 @@ import { useMemo } from 'react' +import { Erc20Abi, Erc20Interface } from '@cowprotocol/abis' +import { ZERO_ADDRESS } from '@cowprotocol/common-const' +import { WRAPPED_NATIVE_CURRENCY as WETH } from '@cowprotocol/common-const' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' -import { Erc20Abi, Erc20Interface } from '@cowswap/abis' +import { useWalletInfo } from '@cowprotocol/wallet' import { Interface } from '@ethersproject/abi' import { BigNumber } from '@ethersproject/bignumber' -import { ZERO_ADDRESS } from 'legacy/constants/misc' -import { WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens' - -import { useWalletInfo } from 'modules/wallet' - import { useMultipleContractSingleData } from 'lib/hooks/multicall' const WETH_ADDRESS = WETH[ChainId.MAINNET].address diff --git a/apps/cowswap-frontend/src/pages/error/NotFound/index.tsx b/apps/cowswap-frontend/src/pages/error/NotFound/index.tsx index 401bd97461..b876efb624 100644 --- a/apps/cowswap-frontend/src/pages/error/NotFound/index.tsx +++ b/apps/cowswap-frontend/src/pages/error/NotFound/index.tsx @@ -1,9 +1,9 @@ +import cow404IMG from '@cowprotocol/assets/cow-swap/cow-404.png' +import { ButtonPrimary } from '@cowprotocol/ui' + import { Link } from 'react-router-dom' import styled from 'styled-components/macro' -import cow404IMG from 'legacy/assets/cow-swap/cow-404.png' -import { ButtonPrimary } from 'legacy/components/Button' - import { Page, Title, Content, GdocsListStyle } from 'modules/application/pure/Page' const Wrapper = styled(Page)` diff --git a/apps/cowswap-frontend/src/pages/games/CowRunner/index.tsx b/apps/cowswap-frontend/src/pages/games/CowRunner/index.tsx index 2e5eb2c843..ee7e5c0465 100644 --- a/apps/cowswap-frontend/src/pages/games/CowRunner/index.tsx +++ b/apps/cowswap-frontend/src/pages/games/CowRunner/index.tsx @@ -1,11 +1,10 @@ import { useEffect } from 'react' +import { gameAnalytics } from '@cowprotocol/analytics' import { CowGame } from '@cowprotocol/cow-runner-game' import styled from 'styled-components/macro' -import { gameAnalytics } from 'legacy/components/analytics' - import { PageTitle } from 'modules/application/containers/PageTitle' import { Page, Content } from 'modules/application/pure/Page' diff --git a/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx b/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx index e181fe114e..0cd932be19 100644 --- a/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx +++ b/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx @@ -1,8 +1,8 @@ -import styled from 'styled-components/macro' +import { gameAnalytics } from '@cowprotocol/analytics' +import ninjaCowImg from '@cowprotocol/assets/cow-swap/ninja-cow.png' +import { ButtonPrimary } from '@cowprotocol/ui' -import ninjaCowImg from 'legacy/assets/cow-swap/ninja-cow.png' -import { gameAnalytics } from 'legacy/components/analytics' -import { ButtonPrimary } from 'legacy/components/Button' +import styled from 'styled-components/macro' import { PageTitle } from 'modules/application/containers/PageTitle' import { Page, Content } from 'modules/application/pure/Page' diff --git a/apps/cowswap-frontend/src/react-app-env.d.ts b/apps/cowswap-frontend/src/react-app-env.d.ts index 8ffbf1ae56..b44e322480 100644 --- a/apps/cowswap-frontend/src/react-app-env.d.ts +++ b/apps/cowswap-frontend/src/react-app-env.d.ts @@ -6,8 +6,6 @@ declare module '@metamask/jazzicon' { export default function (diameter: number, seed: number): HTMLElement } -declare module 'fortmatic' - interface Window { console: Console & { force: Console } // walletLinkExtension is injected by the Coinbase Wallet extension diff --git a/apps/cowswap-frontend/src/test-utils.tsx b/apps/cowswap-frontend/src/test-utils.tsx index 38595a99bd..5ae90fdf46 100644 --- a/apps/cowswap-frontend/src/test-utils.tsx +++ b/apps/cowswap-frontend/src/test-utils.tsx @@ -15,7 +15,7 @@ import { MemoryRouter } from 'react-router-dom' import { ThemeProvider as StyledComponentsThemeProvider } from 'styled-components/macro' import Web3Provider from 'legacy/components/Web3Provider' -import store from 'legacy/state' +import { cowSwapStore } from 'legacy/state' import { useIsDarkMode } from 'legacy/state/user/hooks' import { theme } from 'legacy/theme' @@ -37,7 +37,7 @@ const WithProviders = ({ children }: { children?: ReactNode }) => { return ( - + {children} @@ -71,7 +71,7 @@ export function WithMockedWeb3({ children, location }: { children?: ReactNode; l return ( - + {children} diff --git a/apps/cowswap-frontend/src/types/index.ts b/apps/cowswap-frontend/src/types/index.ts index d5c2713020..dc466c7a62 100644 --- a/apps/cowswap-frontend/src/types/index.ts +++ b/apps/cowswap-frontend/src/types/index.ts @@ -23,7 +23,7 @@ declare global { } export type FractionLike = Fraction | Price | CurrencyAmount -// TODO: it's legacy from the old SDK version +// TODO: it'legacy from the old SDK version export interface PriceInformation { token: string amount: string | null diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculateAmountForRate.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculateAmountForRate.ts index 3a7b9d94f2..f15c72799f 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/calculateAmountForRate.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/calculateAmountForRate.ts @@ -1,8 +1,7 @@ +import { FractionUtils } from '@cowprotocol/common-utils' import { Currency, Fraction } from '@uniswap/sdk-core' -import JSBI from 'jsbi' - -import { Field } from 'legacy/state/swap/actions' +import { Field } from 'legacy/state/types' export type RateCalculationParams = { amount: Fraction | null @@ -12,21 +11,6 @@ export type RateCalculationParams = { outputCurrency: Currency | null } -/** - * Adjust a fraction defined in units for both token to consider the decimals. - * For example, a fraction like 1.1/1 representing the price of USDC, DAI in units, will be turned into - * 1.1/1000000000000 in atoms - */ -export function adjustDecimalsAtoms(value: Fraction, decimalsA: number, decimalsB: number): Fraction { - if (decimalsA === decimalsB) { - return value - } - - const decimalsShift = JSBI.BigInt(JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(Math.abs(decimalsA - decimalsB)))) - - return decimalsA < decimalsB ? value.multiply(decimalsShift) : value.divide(decimalsShift) -} - export function calculateAmountForRate({ activeRate, amount, @@ -41,7 +25,7 @@ export function calculateAmountForRate({ const { decimals: inputDecimals } = inputCurrency const { decimals: outputDecimals } = outputCurrency - const parsedValue = adjustDecimalsAtoms( + const parsedValue = FractionUtils.adjustDecimalsAtoms( amount, field === Field.INPUT ? inputDecimals : outputDecimals, field === Field.INPUT ? outputDecimals : inputDecimals diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.test.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.test.ts index 01474a1c8a..a65c715101 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.test.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.test.ts @@ -1,12 +1,10 @@ +import { USDC_GOERLI, WETH_GOERLI } from '@cowprotocol/common-const' +import { rawToTokenAmount } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/contracts' import { CurrencyAmount, Fraction } from '@uniswap/sdk-core' -import { USDC_GOERLI, WETH_GOERLI } from 'legacy/utils/goerli/constants' - import { calculateExecutionPrice, convertAmountToCurrency } from './calculateExecutionPrice' -import { rawToTokenAmount } from '../rawToTokenAmount' - describe('calculateExecutionPrice', () => { describe('When market price is less than execution price', () => { const marketPrice = new Fraction(3, 7000) // 0 diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.ts index 04762b4e94..77fa94c15c 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/calculateExecutionPrice.ts @@ -1,10 +1,9 @@ +import { rawToTokenAmount } from '@cowprotocol/common-utils' import { OrderKind } from '@cowprotocol/contracts' import { Currency, CurrencyAmount, Fraction, Price } from '@uniswap/sdk-core' import JSBI from 'jsbi' -import { rawToTokenAmount } from 'utils/rawToTokenAmount' - export interface ExecutionPriceParams { inputCurrencyAmount: CurrencyAmount | null outputCurrencyAmount: CurrencyAmount | null diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculatePercentageInRelationToReference.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculatePercentageInRelationToReference.ts index 6d72f305cd..0817b73a82 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/calculatePercentageInRelationToReference.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/calculatePercentageInRelationToReference.ts @@ -1,9 +1,8 @@ +import { ZERO_FRACTION } from '@cowprotocol/common-const' import { Percent } from '@uniswap/sdk-core' import { FractionLike, Nullish } from 'types' -import { ZERO_FRACTION } from 'legacy/constants' - export type CalculateAmountPercentDifferenceProps = { reference: Nullish value: Nullish diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.test.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.test.ts index 52e1a9e985..271ba0b29f 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.test.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.test.ts @@ -1,13 +1,9 @@ +import { ZERO_FRACTION } from '@cowprotocol/common-const' +import { DAI_GOERLI, USDC_GOERLI } from '@cowprotocol/common-const' +import { buildPriceFromCurrencyAmounts, tryParseCurrencyAmount } from '@cowprotocol/common-utils' +import { FractionUtils } from '@cowprotocol/common-utils' import { Currency, Price } from '@uniswap/sdk-core' -import { ZERO_FRACTION } from 'legacy/constants' -import { DAI_GOERLI, USDC_GOERLI } from 'legacy/utils/goerli/constants' - -import { buildPriceFromCurrencyAmounts } from 'modules/utils/orderUtils/buildPriceFromCurrencyAmounts' - -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' -import { FractionUtils } from 'utils/fractionUtils' - import { calculatePriceDifference, CalculatePriceDifferenceParams } from './calculatePriceDifference' function buildPrice(daiAmount: string, usdcAmount: string): Price { diff --git a/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.ts b/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.ts index d40019f8cc..0964d6ebec 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/calculatePriceDifference.ts @@ -1,14 +1,10 @@ +import { ZERO_FRACTION } from '@cowprotocol/common-const' +import { FractionUtils } from '@cowprotocol/common-utils' import { Currency, CurrencyAmount, Fraction, Percent, Price } from '@uniswap/sdk-core' +import invariant from 'tiny-invariant' import { Nullish } from 'types' -import { ZERO_FRACTION } from 'legacy/constants' - -import { assertSameMarket } from 'common/utils/markets' -import { FractionUtils } from 'utils/fractionUtils' - -import { adjustDecimalsAtoms } from './calculateAmountForRate' - const ONE = new Fraction(1) export type CalculatePriceDifferenceParams = { @@ -81,7 +77,7 @@ function calculatePriceDifferenceAux({ // Convert difference in token amount const differenceInUnits = FractionUtils.fromPrice(targetPrice).subtract(FractionUtils.fromPrice(referencePrice)) - const difference = adjustDecimalsAtoms(differenceInUnits, 0, referencePrice.quoteCurrency.decimals) + const difference = FractionUtils.adjustDecimalsAtoms(differenceInUnits, 0, referencePrice.quoteCurrency.decimals) const differenceInQuoteToken = CurrencyAmount.fromFractionalAmount( referencePrice.quoteCurrency, difference.numerator, @@ -98,3 +94,11 @@ function calculatePriceDifferenceAux({ return { percentage, amount: differenceInQuoteToken } } + +function assertSameMarket(price1: Price, price2: Price) { + // Assert I'm comparing apples with apples (prices should refer to market) + invariant( + price1.baseCurrency.equals(price2.baseCurrency) && price1.quoteCurrency.equals(price2.quoteCurrency), + 'Prices are not from the same market' + ) +} diff --git a/apps/cowswap-frontend/src/utils/orderUtils/getOrderFilledAmount.ts b/apps/cowswap-frontend/src/utils/orderUtils/getOrderFilledAmount.ts index 81aeba2aa7..8d1a92bb20 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/getOrderFilledAmount.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/getOrderFilledAmount.ts @@ -1,6 +1,7 @@ +import { ZERO_BIG_NUMBER } from '@cowprotocol/common-const' + import BigNumber from 'bignumber.js' -import { ZERO_BIG_NUMBER } from 'legacy/constants' import { Order } from 'legacy/state/orders/actions' /** diff --git a/apps/cowswap-frontend/src/utils/orderUtils/getOrderSurplus.ts b/apps/cowswap-frontend/src/utils/orderUtils/getOrderSurplus.ts index 77f6270ec5..6089b0ab4c 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/getOrderSurplus.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/getOrderSurplus.ts @@ -1,8 +1,9 @@ // Util functions that only pertain to/deal with operator API related stuff +import { ZERO_BIG_NUMBER } from '@cowprotocol/common-const' + import BigNumber from 'bignumber.js' import JSBI from 'jsbi' -import { ZERO_BIG_NUMBER } from 'legacy/constants' import { Order } from 'legacy/state/orders/actions' import { getOrderExecutedAmounts } from './getOrderExecutedAmounts' diff --git a/apps/cowswap-frontend/src/utils/orderUtils/getTokenFromMapping.ts b/apps/cowswap-frontend/src/utils/orderUtils/getTokenFromMapping.ts index 11fccd9a07..b0e3a4735c 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/getTokenFromMapping.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/getTokenFromMapping.ts @@ -1,11 +1,9 @@ +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' +import { getIsNativeToken } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { getAddress } from '@ethersproject/address' import { Token } from '@uniswap/sdk-core' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' - -import { getIsNativeToken } from '../getIsNativeToken' - export function getTokenFromMapping( address: string, chainId: SupportedChainId, diff --git a/apps/cowswap-frontend/tsconfig.json b/apps/cowswap-frontend/tsconfig.json index 65e6c88429..fd5681c653 100644 --- a/apps/cowswap-frontend/tsconfig.json +++ b/apps/cowswap-frontend/tsconfig.json @@ -9,12 +9,20 @@ "types": ["node", "vite/client"], "baseUrl": "src", "paths": { - "@cowswap/abis": ["../../../libs/abis/src/index.ts"], - "@cowswap/ui": ["../../../libs/ui/src/index.ts"], - "@cowswap/ui-utils": ["../../../libs/ui-utils/src/index.ts"], - "@cowswap/widget-lib": ["../../../libs/widget-lib/src/index.ts"], - "@cowswap/widget-react": ["../../../libs/widget-react/src/index.ts"], - "@cowswap/snackbars": ["../../../libs/snackbars/src/index.ts"] + "@cowprotocol/abis": ["../../../libs/abis/src/index.ts"], + "@cowprotocol/ui": ["../../../libs/ui/src/index.ts"], + "@cowprotocol/ui-utils": ["../../../libs/ui-utils/src/index.ts"], + "@cowprotocol/widget-lib": ["../../../libs/widget-lib/src/index.ts"], + "@cowprotocol/widget-react": ["../../../libs/widget-react/src/index.ts"], + "@cowprotocol/snackbars": ["../../../libs/snackbars/src/index.ts"], + "@cowprotocol/wallet": ["../../../libs/wallet/src/index.ts"], + "@cowprotocol/assets/*": ["../../../libs/assets/src/*"], + "@cowprotocol/common-const": ["../../../libs/common-const/src/index.ts"], + "@cowprotocol/common-utils": ["../../../libs/common-utils/src/index.ts"], + "@cowprotocol/common-hooks": ["../../../libs/common-hooks/src/index.ts"], + "@cowprotocol/ens": ["../../../libs/ens/src/index.ts"], + "@cowprotocol/core": ["../../../libs/core/src/index.ts"], + "@cowprotocol/analytics": ["../../../libs/analytics/src/index.ts"] } }, "files": [], diff --git a/apps/cowswap-frontend/vite.config.ts b/apps/cowswap-frontend/vite.config.ts index 51c69e5673..6c557ded36 100644 --- a/apps/cowswap-frontend/vite.config.ts +++ b/apps/cowswap-frontend/vite.config.ts @@ -3,7 +3,7 @@ import { lingui } from '@lingui/vite-plugin' import react from '@vitejs/plugin-react-swc' import stdLibBrowser from 'node-stdlib-browser' import { visualizer } from 'rollup-plugin-visualizer' -import { defineConfig, loadEnv, PluginOption, searchForWorkspaceRoot } from 'vite' +import { defineConfig, PluginOption, searchForWorkspaceRoot } from 'vite' import macrosPlugin from 'vite-plugin-babel-macros' import { ModuleNameWithoutNodePrefix, nodePolyfills } from 'vite-plugin-node-polyfills' import { VitePWA } from 'vite-plugin-pwa' @@ -12,6 +12,8 @@ import viteTsConfigPaths from 'vite-tsconfig-paths' import * as path from 'path' +import { getReactProcessEnv } from '../../tools/getReactProcessEnv' + // eslint-disable-next-line no-restricted-imports import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types' @@ -24,16 +26,6 @@ const analyzeBundle = process.env.ANALYZE_BUNDLE === 'true' const analyzeBundleTemplate: TemplateType = (process.env.ANALYZE_BUNDLE_TEMPLATE as TemplateType) || 'treemap' // "sunburst" | "treemap" | "network" | "raw-data" | "list"; export default defineConfig(({ mode }) => { - const env = loadEnv(mode, process.cwd(), ['REACT_APP_']) - - // expose .env as process.env instead of import.meta since jest does not import meta yet - const envWithProcessPrefix = Object.entries(env).reduce((prev, [key, val]) => { - return { - ...prev, - ['process.env.' + key]: JSON.stringify(val), - } - }, {}) - const plugins = [ nodePolyfills({ exclude: allNodeDeps.filter((dep) => !nodeDepsToInclude.includes(dep)), @@ -81,7 +73,7 @@ export default defineConfig(({ mode }) => { return { define: { - ...envWithProcessPrefix, + ...getReactProcessEnv(mode), }, assetsInclude: ['**/*.md'], diff --git a/jest.preset.js b/jest.preset.js index 8cd53f8e9b..9ba35593e5 100644 --- a/jest.preset.js +++ b/jest.preset.js @@ -1,3 +1,11 @@ const nxPreset = require('@nx/jest/preset').default -module.exports = { ...nxPreset } +module.exports = { + ...nxPreset, + moduleNameMapper: { + '\\.svg': '../../testing/svgrMock.js', + '\\.gif': '../../testing/imgMock.js', + '\\.webp': '../../testing/imgMock.js', + '\\.png': '../../testing/imgMock.js', + }, +} diff --git a/libs/analytics/.babelrc b/libs/analytics/.babelrc new file mode 100644 index 0000000000..ef4889c1ab --- /dev/null +++ b/libs/analytics/.babelrc @@ -0,0 +1,20 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [ + [ + "styled-components", + { + "pure": true, + "ssr": true + } + ] + ] +} diff --git a/libs/analytics/.eslintrc.json b/libs/analytics/.eslintrc.json new file mode 100644 index 0000000000..231aaa5f83 --- /dev/null +++ b/libs/analytics/.eslintrc.json @@ -0,0 +1,21 @@ +{ + "extends": ["plugin:@nx/react", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "rules": { + "@typescript-eslint/no-explicit-any": "off" + }, + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/analytics/README.md b/libs/analytics/README.md new file mode 100644 index 0000000000..f097a1dbbf --- /dev/null +++ b/libs/analytics/README.md @@ -0,0 +1 @@ +# Analytics diff --git a/libs/analytics/jest.config.ts b/libs/analytics/jest.config.ts new file mode 100644 index 0000000000..2e6915c373 --- /dev/null +++ b/libs/analytics/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'analytics', + preset: '../../jest.preset.js', + transform: { + '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', + '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/libs/analytics', +} diff --git a/libs/analytics/package.json b/libs/analytics/package.json new file mode 100644 index 0000000000..31f055efc5 --- /dev/null +++ b/libs/analytics/package.json @@ -0,0 +1,12 @@ +{ + "name": "@cowprotocol/analytics", + "version": "0.0.1", + "main": "./index.js", + "types": "./index.d.ts", + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.js" + } + } +} diff --git a/libs/analytics/project.json b/libs/analytics/project.json new file mode 100644 index 0000000000..3943c48429 --- /dev/null +++ b/libs/analytics/project.json @@ -0,0 +1,46 @@ +{ + "name": "@cowprotocol/analytics", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/analytics/src", + "projectType": "library", + "tags": [], + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/analytics/**/*.{ts,tsx,js,jsx}"] + } + }, + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/libs/analytics" + }, + "configurations": { + "development": { + "mode": "development" + }, + "production": { + "mode": "production" + } + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/analytics/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + } +} diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/cowFortune.ts b/libs/analytics/src/events/cowFortune.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/events/cowFortune.ts rename to libs/analytics/src/events/cowFortune.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/listEvents.ts b/libs/analytics/src/events/listEvents.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/events/listEvents.ts rename to libs/analytics/src/events/listEvents.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/otherEvents.ts b/libs/analytics/src/events/otherEvents.ts similarity index 94% rename from apps/cowswap-frontend/src/legacy/components/analytics/events/otherEvents.ts rename to libs/analytics/src/events/otherEvents.ts index 132edbaae1..eab7c4cb22 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/events/otherEvents.ts +++ b/libs/analytics/src/events/otherEvents.ts @@ -1,4 +1,4 @@ -import { detectExplorer } from 'legacy/utils/explorer' +import { detectExplorer } from '@cowprotocol/common-utils' import { sendEvent } from '../googleAnalytics' import { Category } from '../types' diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/settingsEvents.ts b/libs/analytics/src/events/settingsEvents.ts similarity index 95% rename from apps/cowswap-frontend/src/legacy/components/analytics/events/settingsEvents.ts rename to libs/analytics/src/events/settingsEvents.ts index af0c0ffc5e..0718548e96 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/events/settingsEvents.ts +++ b/libs/analytics/src/events/settingsEvents.ts @@ -1,4 +1,4 @@ -import { debounce } from 'legacy/utils/misc' +import { debounce } from '@cowprotocol/common-utils' import { sendEvent } from '../googleAnalytics' import { Category } from '../types' diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/swapEvents.ts b/libs/analytics/src/events/swapEvents.ts similarity index 75% rename from apps/cowswap-frontend/src/legacy/components/analytics/events/swapEvents.ts rename to libs/analytics/src/events/swapEvents.ts index 8f0956776f..fdb7bf7798 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/events/swapEvents.ts +++ b/libs/analytics/src/events/swapEvents.ts @@ -1,10 +1,9 @@ -import { Field } from 'legacy/state/swap/actions' -import { debounce } from 'legacy/utils/misc' +import { debounce } from '@cowprotocol/common-utils' import { sendEvent } from '../googleAnalytics' import { Category } from '../types' -export function currencySelectAnalytics(field: Field, label: string | undefined) { +export function currencySelectAnalytics(field: string, label: string | undefined) { sendEvent({ category: Category.CURRENCY_SELECT, action: `Change ${field} token`, @@ -19,7 +18,7 @@ export function setMaxSellTokensAnalytics() { }) } -function _changeSwapAmountAnalytics(field: Field, value: number) { +function _changeSwapAmountAnalytics(field: string, value: number) { sendEvent({ category: Category.TRADE, action: `Change ${field} field amount`, @@ -27,7 +26,7 @@ function _changeSwapAmountAnalytics(field: Field, value: number) { }) } -export const changeSwapAmountAnalytics = debounce(([field, value]: [Field, number]) => { +export const changeSwapAmountAnalytics = debounce(([field, value]: [string, number]) => { _changeSwapAmountAnalytics(field, value) }, 2000) diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/themeEvents.ts b/libs/analytics/src/events/themeEvents.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/events/themeEvents.ts rename to libs/analytics/src/events/themeEvents.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/transactionEvents.ts b/libs/analytics/src/events/transactionEvents.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/events/transactionEvents.ts rename to libs/analytics/src/events/transactionEvents.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/twapEvents.ts b/libs/analytics/src/events/twapEvents.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/events/twapEvents.ts rename to libs/analytics/src/events/twapEvents.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/events/walletEvents.ts b/libs/analytics/src/events/walletEvents.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/events/walletEvents.ts rename to libs/analytics/src/events/walletEvents.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/googleAnalytics.ts b/libs/analytics/src/googleAnalytics.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/googleAnalytics.ts rename to libs/analytics/src/googleAnalytics.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/index.ts b/libs/analytics/src/index.ts similarity index 87% rename from apps/cowswap-frontend/src/legacy/components/analytics/index.ts rename to libs/analytics/src/index.ts index 64a6c8420e..884c06dbc5 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/index.ts +++ b/libs/analytics/src/index.ts @@ -1,11 +1,9 @@ -import { isMobile } from 'legacy/utils/userAgent' +import { isMobile } from '@cowprotocol/common-utils' import { initAnalytics, serviceWorkerAnalytics } from './events/otherEvents' import { googleAnalytics } from './googleAnalytics' import { Dimensions } from './types' -export { useAnalyticsReporter } from './hooks/useAnalyticsReporter' - const GOOGLE_ANALYTICS_ID: string | undefined = process.env.REACT_APP_GOOGLE_ANALYTICS_ID export const GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY = 'ga_client_id' @@ -42,7 +40,6 @@ if (typeof GOOGLE_ANALYTICS_ID === 'string') { serviceWorkerAnalytics() initAnalytics() -// MOD export * from './events/listEvents' export * from './events/settingsEvents' export * from './events/themeEvents' @@ -50,3 +47,8 @@ export * from './events/transactionEvents' export * from './events/walletEvents' export * from './events/swapEvents' export * from './events/otherEvents' +export * from './events/cowFortune' +export * from './events/twapEvents' +export * from './googleAnalytics' +export * from './pixel' +export * from './types' diff --git a/libs/analytics/src/pixel/constants.ts b/libs/analytics/src/pixel/constants.ts new file mode 100644 index 0000000000..6428232da7 --- /dev/null +++ b/libs/analytics/src/pixel/constants.ts @@ -0,0 +1,3 @@ +import { isEns, isProd } from '@cowprotocol/common-utils' + +export const PIXEL_ENABLED = isProd || isEns diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/facebook.ts b/libs/analytics/src/pixel/facebook.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/pixel/facebook.ts rename to libs/analytics/src/pixel/facebook.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/index.ts b/libs/analytics/src/pixel/index.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/pixel/index.ts rename to libs/analytics/src/pixel/index.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/linkedin.ts b/libs/analytics/src/pixel/linkedin.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/pixel/linkedin.ts rename to libs/analytics/src/pixel/linkedin.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/microsoft.ts b/libs/analytics/src/pixel/microsoft.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/pixel/microsoft.ts rename to libs/analytics/src/pixel/microsoft.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/paved.ts b/libs/analytics/src/pixel/paved.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/pixel/paved.ts rename to libs/analytics/src/pixel/paved.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/reddit.ts b/libs/analytics/src/pixel/reddit.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/pixel/reddit.ts rename to libs/analytics/src/pixel/reddit.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/sendAllPixels.ts b/libs/analytics/src/pixel/sendAllPixels.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/pixel/sendAllPixels.ts rename to libs/analytics/src/pixel/sendAllPixels.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/twitter.ts b/libs/analytics/src/pixel/twitter.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/pixel/twitter.ts rename to libs/analytics/src/pixel/twitter.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/types.ts b/libs/analytics/src/pixel/types.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/pixel/types.ts rename to libs/analytics/src/pixel/types.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/pixel/utils.ts b/libs/analytics/src/pixel/utils.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/pixel/utils.ts rename to libs/analytics/src/pixel/utils.ts diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/provider/index.ts b/libs/analytics/src/provider/index.ts similarity index 98% rename from apps/cowswap-frontend/src/legacy/components/analytics/provider/index.ts rename to libs/analytics/src/provider/index.ts index 2c807dc196..219a57d9df 100644 --- a/apps/cowswap-frontend/src/legacy/components/analytics/provider/index.ts +++ b/libs/analytics/src/provider/index.ts @@ -1,10 +1,10 @@ import { ErrorInfo } from 'react' +import { debounce } from '@cowprotocol/common-utils' + import ReactGA from 'react-ga4' import { GaOptions, InitOptions, UaEventOptions } from 'react-ga4/types/ga4' -import { debounce } from 'legacy/utils/misc' - import { Dimensions } from '../types' const DIMENSION_MAP = { diff --git a/apps/cowswap-frontend/src/legacy/components/analytics/types.ts b/libs/analytics/src/types.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/analytics/types.ts rename to libs/analytics/src/types.ts diff --git a/libs/analytics/tsconfig.json b/libs/analytics/tsconfig.json new file mode 100644 index 0000000000..bab74ff2e6 --- /dev/null +++ b/libs/analytics/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["vite/client"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/analytics/tsconfig.lib.json b/libs/analytics/tsconfig.lib.json new file mode 100644 index 0000000000..1b2b0c12df --- /dev/null +++ b/libs/analytics/tsconfig.lib.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node", "vite/client"] + }, + "files": ["../../node_modules/@nx/react/typings/cssmodule.d.ts", "../../node_modules/@nx/react/typings/image.d.ts"], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/analytics/tsconfig.spec.json b/libs/analytics/tsconfig.spec.json new file mode 100644 index 0000000000..26ef046ac5 --- /dev/null +++ b/libs/analytics/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/libs/analytics/vite.config.ts b/libs/analytics/vite.config.ts new file mode 100644 index 0000000000..078f6d3ff0 --- /dev/null +++ b/libs/analytics/vite.config.ts @@ -0,0 +1,49 @@ +/// +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' +import viteTsConfigPaths from 'vite-tsconfig-paths' +import dts from 'vite-plugin-dts' +import * as path from 'path' + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/analytics', + + plugins: [ + dts({ + entryRoot: 'src', + tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'), + skipDiagnostics: true, + }), + react(), + viteTsConfigPaths({ + root: '../../', + }), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + lib: { + // Could also be a dictionary or array of multiple entry points. + entry: 'src/index.ts', + name: 'analytics', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es', 'cjs'], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: ['react', 'react-dom', 'react/jsx-runtime'], + }, + }, +}) diff --git a/libs/assets/.babelrc b/libs/assets/.babelrc new file mode 100644 index 0000000000..ef4889c1ab --- /dev/null +++ b/libs/assets/.babelrc @@ -0,0 +1,20 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [ + [ + "styled-components", + { + "pure": true, + "ssr": true + } + ] + ] +} diff --git a/libs/assets/.eslintrc.json b/libs/assets/.eslintrc.json new file mode 100644 index 0000000000..a39ac5d057 --- /dev/null +++ b/libs/assets/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["plugin:@nx/react", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/assets/README.md b/libs/assets/README.md new file mode 100644 index 0000000000..5d1b13d506 --- /dev/null +++ b/libs/assets/README.md @@ -0,0 +1 @@ +# Assets diff --git a/libs/assets/jest.config.ts b/libs/assets/jest.config.ts new file mode 100644 index 0000000000..6fbf3d7c4d --- /dev/null +++ b/libs/assets/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'assets', + preset: '../../jest.preset.js', + transform: { + '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', + '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/libs/assets', +} diff --git a/libs/assets/package.json b/libs/assets/package.json new file mode 100644 index 0000000000..a839ad81d8 --- /dev/null +++ b/libs/assets/package.json @@ -0,0 +1,12 @@ +{ + "name": "@cowprotocol/assets", + "version": "0.0.1", + "main": "./index.js", + "types": "./index.d.ts", + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.js" + } + } +} diff --git a/libs/assets/project.json b/libs/assets/project.json new file mode 100644 index 0000000000..564800aa19 --- /dev/null +++ b/libs/assets/project.json @@ -0,0 +1,46 @@ +{ + "name": "@cowprotocol/assets", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/assets/src", + "projectType": "library", + "tags": [], + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/assets/**/*.{ts,tsx,js,jsx}"] + } + }, + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/libs/assets" + }, + "configurations": { + "development": { + "mode": "development" + }, + "production": { + "mode": "production" + } + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/assets/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + } +} diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/CowError.png b/libs/assets/src/cow-swap/CowError.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/CowError.png rename to libs/assets/src/cow-swap/CowError.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/alert-circle.svg b/libs/assets/src/cow-swap/alert-circle.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/alert-circle.svg rename to libs/assets/src/cow-swap/alert-circle.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/alert.svg b/libs/assets/src/cow-swap/alert.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/alert.svg rename to libs/assets/src/cow-swap/alert.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/0x.png b/libs/assets/src/cow-swap/ammslogo/0x.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/0x.png rename to libs/assets/src/cow-swap/ammslogo/0x.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/1inch.png b/libs/assets/src/cow-swap/ammslogo/1inch.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/1inch.png rename to libs/assets/src/cow-swap/ammslogo/1inch.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/baoswap.png b/libs/assets/src/cow-swap/ammslogo/baoswap.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/baoswap.png rename to libs/assets/src/cow-swap/ammslogo/baoswap.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/curve.png b/libs/assets/src/cow-swap/ammslogo/curve.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/curve.png rename to libs/assets/src/cow-swap/ammslogo/curve.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/elk.png b/libs/assets/src/cow-swap/ammslogo/elk.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/elk.png rename to libs/assets/src/cow-swap/ammslogo/elk.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/honeyswap.png b/libs/assets/src/cow-swap/ammslogo/honeyswap.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/honeyswap.png rename to libs/assets/src/cow-swap/ammslogo/honeyswap.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/levinswap.png b/libs/assets/src/cow-swap/ammslogo/levinswap.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/levinswap.png rename to libs/assets/src/cow-swap/ammslogo/levinswap.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/matcha.png b/libs/assets/src/cow-swap/ammslogo/matcha.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/matcha.png rename to libs/assets/src/cow-swap/ammslogo/matcha.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/paraswap.png b/libs/assets/src/cow-swap/ammslogo/paraswap.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/paraswap.png rename to libs/assets/src/cow-swap/ammslogo/paraswap.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/sushi.png b/libs/assets/src/cow-swap/ammslogo/sushi.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/sushi.png rename to libs/assets/src/cow-swap/ammslogo/sushi.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/swapr.png b/libs/assets/src/cow-swap/ammslogo/swapr.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/swapr.png rename to libs/assets/src/cow-swap/ammslogo/swapr.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/symmetric.png b/libs/assets/src/cow-swap/ammslogo/symmetric.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/symmetric.png rename to libs/assets/src/cow-swap/ammslogo/symmetric.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/uniswap.png b/libs/assets/src/cow-swap/ammslogo/uniswap.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ammslogo/uniswap.png rename to libs/assets/src/cow-swap/ammslogo/uniswap.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/anniversary-icons.png b/libs/assets/src/cow-swap/anniversary-icons.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/anniversary-icons.png rename to libs/assets/src/cow-swap/anniversary-icons.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/arrow.svg b/libs/assets/src/cow-swap/arrow.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/arrow.svg rename to libs/assets/src/cow-swap/arrow.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/arrowDownRight.svg b/libs/assets/src/cow-swap/arrowDownRight.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/arrowDownRight.svg rename to libs/assets/src/cow-swap/arrowDownRight.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/attention.svg b/libs/assets/src/cow-swap/attention.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/attention.svg rename to libs/assets/src/cow-swap/attention.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/carret-down.svg b/libs/assets/src/cow-swap/carret-down.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/carret-down.svg rename to libs/assets/src/cow-swap/carret-down.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/check-singular.svg b/libs/assets/src/cow-swap/check-singular.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/check-singular.svg rename to libs/assets/src/cow-swap/check-singular.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/check.svg b/libs/assets/src/cow-swap/check.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/check.svg rename to libs/assets/src/cow-swap/check.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/checkmark.svg b/libs/assets/src/cow-swap/checkmark.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/checkmark.svg rename to libs/assets/src/cow-swap/checkmark.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/code.svg b/libs/assets/src/cow-swap/code.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/code.svg rename to libs/assets/src/cow-swap/code.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cookie-policy.svg b/libs/assets/src/cow-swap/cookie-policy.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cookie-policy.svg rename to libs/assets/src/cow-swap/cookie-policy.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cow-404.png b/libs/assets/src/cow-swap/cow-404.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cow-404.png rename to libs/assets/src/cow-swap/cow-404.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cow-load.gif b/libs/assets/src/cow-swap/cow-load.gif similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cow-load.gif rename to libs/assets/src/cow-swap/cow-load.gif diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cow-load.webp b/libs/assets/src/cow-swap/cow-load.webp similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cow-load.webp rename to libs/assets/src/cow-swap/cow-load.webp diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cow-no-connection.png b/libs/assets/src/cow-swap/cow-no-connection.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cow-no-connection.png rename to libs/assets/src/cow-swap/cow-no-connection.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cow.svg b/libs/assets/src/cow-swap/cow.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cow.svg rename to libs/assets/src/cow-swap/cow.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cow_v2.svg b/libs/assets/src/cow-swap/cow_v2.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cow_v2.svg rename to libs/assets/src/cow-swap/cow_v2.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cowprotocol.svg b/libs/assets/src/cow-swap/cowprotocol.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cowprotocol.svg rename to libs/assets/src/cow-swap/cowprotocol.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cowswap-diagram.png b/libs/assets/src/cow-swap/cowswap-diagram.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cowswap-diagram.png rename to libs/assets/src/cow-swap/cowswap-diagram.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cowswap-logo.svg b/libs/assets/src/cow-swap/cowswap-logo.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cowswap-logo.svg rename to libs/assets/src/cow-swap/cowswap-logo.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cursor1.gif b/libs/assets/src/cow-swap/cursor1.gif similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cursor1.gif rename to libs/assets/src/cow-swap/cursor1.gif diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cursor2.gif b/libs/assets/src/cow-swap/cursor2.gif similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cursor2.gif rename to libs/assets/src/cow-swap/cursor2.gif diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cursor3.gif b/libs/assets/src/cow-swap/cursor3.gif similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cursor3.gif rename to libs/assets/src/cow-swap/cursor3.gif diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/cursor4.gif b/libs/assets/src/cow-swap/cursor4.gif similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/cursor4.gif rename to libs/assets/src/cow-swap/cursor4.gif diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/discord.svg b/libs/assets/src/cow-swap/discord.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/discord.svg rename to libs/assets/src/cow-swap/discord.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/doc.svg b/libs/assets/src/cow-swap/doc.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/doc.svg rename to libs/assets/src/cow-swap/doc.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/etherscan-icon.svg b/libs/assets/src/cow-swap/etherscan-icon.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/etherscan-icon.svg rename to libs/assets/src/cow-swap/etherscan-icon.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/exclamation.svg b/libs/assets/src/cow-swap/exclamation.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/exclamation.svg rename to libs/assets/src/cow-swap/exclamation.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/experiment.svg b/libs/assets/src/cow-swap/experiment.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/experiment.svg rename to libs/assets/src/cow-swap/experiment.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/feedback.svg b/libs/assets/src/cow-swap/feedback.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/feedback.svg rename to libs/assets/src/cow-swap/feedback.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/finish.svg b/libs/assets/src/cow-swap/finish.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/finish.svg rename to libs/assets/src/cow-swap/finish.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/fortune-cookie.png b/libs/assets/src/cow-swap/fortune-cookie.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/fortune-cookie.png rename to libs/assets/src/cow-swap/fortune-cookie.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/game.gif b/libs/assets/src/cow-swap/game.gif similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/game.gif rename to libs/assets/src/cow-swap/game.gif diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/gasless.png b/libs/assets/src/cow-swap/gasless.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/gasless.png rename to libs/assets/src/cow-swap/gasless.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/gno.png b/libs/assets/src/cow-swap/gno.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/gno.png rename to libs/assets/src/cow-swap/gno.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/halloween-bats.svg b/libs/assets/src/cow-swap/halloween-bats.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/halloween-bats.svg rename to libs/assets/src/cow-swap/halloween-bats.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/halloween-spider.svg b/libs/assets/src/cow-swap/halloween-spider.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/halloween-spider.svg rename to libs/assets/src/cow-swap/halloween-spider.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/important.svg b/libs/assets/src/cow-swap/important.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/important.svg rename to libs/assets/src/cow-swap/important.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/info.svg b/libs/assets/src/cow-swap/info.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/info.svg rename to libs/assets/src/cow-swap/info.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/loading.svg b/libs/assets/src/cow-swap/loading.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/loading.svg rename to libs/assets/src/cow-swap/loading.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/meditating-cow-v2.svg b/libs/assets/src/cow-swap/meditating-cow-v2.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/meditating-cow-v2.svg rename to libs/assets/src/cow-swap/meditating-cow-v2.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/menu.svg b/libs/assets/src/cow-swap/menu.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/menu.svg rename to libs/assets/src/cow-swap/menu.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/mev.png b/libs/assets/src/cow-swap/mev.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/mev.png rename to libs/assets/src/cow-swap/mev.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/moon.svg b/libs/assets/src/cow-swap/moon.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/moon.svg rename to libs/assets/src/cow-swap/moon.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/network-gnosis-chain-logo.svg b/libs/assets/src/cow-swap/network-gnosis-chain-logo.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/network-gnosis-chain-logo.svg rename to libs/assets/src/cow-swap/network-gnosis-chain-logo.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/network-goerli-logo.svg b/libs/assets/src/cow-swap/network-goerli-logo.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/network-goerli-logo.svg rename to libs/assets/src/cow-swap/network-goerli-logo.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/network-mainnet-logo.svg b/libs/assets/src/cow-swap/network-mainnet-logo.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/network-mainnet-logo.svg rename to libs/assets/src/cow-swap/network-mainnet-logo.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/network-rinkeby-logo.svg b/libs/assets/src/cow-swap/network-rinkeby-logo.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/network-rinkeby-logo.svg rename to libs/assets/src/cow-swap/network-rinkeby-logo.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/ninja-cow.png b/libs/assets/src/cow-swap/ninja-cow.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/ninja-cow.png rename to libs/assets/src/cow-swap/ninja-cow.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/order-cancelled.svg b/libs/assets/src/cow-swap/order-cancelled.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/order-cancelled.svg rename to libs/assets/src/cow-swap/order-cancelled.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/order-check.svg b/libs/assets/src/cow-swap/order-check.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/order-check.svg rename to libs/assets/src/cow-swap/order-check.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/order-cross.svg b/libs/assets/src/cow-swap/order-cross.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/order-cross.svg rename to libs/assets/src/cow-swap/order-cross.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/order-expired.svg b/libs/assets/src/cow-swap/order-expired.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/order-expired.svg rename to libs/assets/src/cow-swap/order-expired.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/order-open.svg b/libs/assets/src/cow-swap/order-open.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/order-open.svg rename to libs/assets/src/cow-swap/order-open.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/order-presignature-pending.svg b/libs/assets/src/cow-swap/order-presignature-pending.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/order-presignature-pending.svg rename to libs/assets/src/cow-swap/order-presignature-pending.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/orderExecution.svg b/libs/assets/src/cow-swap/orderExecution.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/orderExecution.svg rename to libs/assets/src/cow-swap/orderExecution.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/pie.svg b/libs/assets/src/cow-swap/pie.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/pie.svg rename to libs/assets/src/cow-swap/pie.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/plus.svg b/libs/assets/src/cow-swap/plus.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/plus.svg rename to libs/assets/src/cow-swap/plus.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/privacy-policy.svg b/libs/assets/src/cow-swap/privacy-policy.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/privacy-policy.svg rename to libs/assets/src/cow-swap/privacy-policy.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/protection.svg b/libs/assets/src/cow-swap/protection.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/protection.svg rename to libs/assets/src/cow-swap/protection.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/question.ts b/libs/assets/src/cow-swap/question.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/question.ts rename to libs/assets/src/cow-swap/question.ts diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/refund.svg b/libs/assets/src/cow-swap/refund.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/refund.svg rename to libs/assets/src/cow-swap/refund.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/round-arrow.svg b/libs/assets/src/cow-swap/round-arrow.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/round-arrow.svg rename to libs/assets/src/cow-swap/round-arrow.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/safe-logo.svg b/libs/assets/src/cow-swap/safe-logo.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/safe-logo.svg rename to libs/assets/src/cow-swap/safe-logo.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/savings.svg b/libs/assets/src/cow-swap/savings.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/savings.svg rename to libs/assets/src/cow-swap/savings.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/send.svg b/libs/assets/src/cow-swap/send.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/send.svg rename to libs/assets/src/cow-swap/send.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/sun.svg b/libs/assets/src/cow-swap/sun.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/sun.svg rename to libs/assets/src/cow-swap/sun.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/surplus-cow.svg b/libs/assets/src/cow-swap/surplus-cow.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/surplus-cow.svg rename to libs/assets/src/cow-swap/surplus-cow.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/terms-and-conditions.svg b/libs/assets/src/cow-swap/terms-and-conditions.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/terms-and-conditions.svg rename to libs/assets/src/cow-swap/terms-and-conditions.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/transaction-arrows.svg b/libs/assets/src/cow-swap/transaction-arrows.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/transaction-arrows.svg rename to libs/assets/src/cow-swap/transaction-arrows.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/transaction-confirmed.svg b/libs/assets/src/cow-swap/transaction-confirmed.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/transaction-confirmed.svg rename to libs/assets/src/cow-swap/transaction-confirmed.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/twitter.svg b/libs/assets/src/cow-swap/twitter.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/twitter.svg rename to libs/assets/src/cow-swap/twitter.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/usdc.png b/libs/assets/src/cow-swap/usdc.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/usdc.png rename to libs/assets/src/cow-swap/usdc.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/vCOW.png b/libs/assets/src/cow-swap/vCOW.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/vCOW.png rename to libs/assets/src/cow-swap/vCOW.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/wallet-plus.svg b/libs/assets/src/cow-swap/wallet-plus.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/wallet-plus.svg rename to libs/assets/src/cow-swap/wallet-plus.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/wxdai.png b/libs/assets/src/cow-swap/wxdai.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/wxdai.png rename to libs/assets/src/cow-swap/wxdai.png diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/x.svg b/libs/assets/src/cow-swap/x.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/x.svg rename to libs/assets/src/cow-swap/x.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/cow-swap/xdai.png b/libs/assets/src/cow-swap/xdai.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/cow-swap/xdai.png rename to libs/assets/src/cow-swap/xdai.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/amms-graph-gc.svg b/libs/assets/src/images/amms-graph-gc.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/amms-graph-gc.svg rename to libs/assets/src/images/amms-graph-gc.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/amms-graph.svg b/libs/assets/src/images/amms-graph.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/amms-graph.svg rename to libs/assets/src/images/amms-graph.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/arrow-down-blue.svg b/libs/assets/src/images/arrow-down-blue.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/arrow-down-blue.svg rename to libs/assets/src/images/arrow-down-blue.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/arrow-down-grey.svg b/libs/assets/src/images/arrow-down-grey.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/arrow-down-grey.svg rename to libs/assets/src/images/arrow-down-grey.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/big_unicorn.png b/libs/assets/src/images/big_unicorn.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/big_unicorn.png rename to libs/assets/src/images/big_unicorn.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/blue-loader.svg b/libs/assets/src/images/blue-loader.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/blue-loader.svg rename to libs/assets/src/images/blue-loader.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/circle-grey.svg b/libs/assets/src/images/circle-grey.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/circle-grey.svg rename to libs/assets/src/images/circle-grey.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/circle.svg b/libs/assets/src/images/circle.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/circle.svg rename to libs/assets/src/images/circle.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/cow-graph.svg b/libs/assets/src/images/cow-graph.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/cow-graph.svg rename to libs/assets/src/images/cow-graph.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/cow-meditating-smoooth.svg b/libs/assets/src/images/cow-meditating-smoooth.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/cow-meditating-smoooth.svg rename to libs/assets/src/images/cow-meditating-smoooth.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/cow-meditating.svg b/libs/assets/src/images/cow-meditating.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/cow-meditating.svg rename to libs/assets/src/images/cow-meditating.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/dropdown-blue.svg b/libs/assets/src/images/dropdown-blue.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/dropdown-blue.svg rename to libs/assets/src/images/dropdown-blue.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/dropdown.svg b/libs/assets/src/images/dropdown.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/dropdown.svg rename to libs/assets/src/images/dropdown.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/dropup-blue.svg b/libs/assets/src/images/dropup-blue.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/dropup-blue.svg rename to libs/assets/src/images/dropup-blue.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/ethereum-logo.png b/libs/assets/src/images/ethereum-logo.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/ethereum-logo.png rename to libs/assets/src/images/ethereum-logo.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/gas-icon.svg b/libs/assets/src/images/gas-icon.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/gas-icon.svg rename to libs/assets/src/images/gas-icon.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/link.svg b/libs/assets/src/images/link.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/link.svg rename to libs/assets/src/images/link.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/magnifying-glass.svg b/libs/assets/src/images/magnifying-glass.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/magnifying-glass.svg rename to libs/assets/src/images/magnifying-glass.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/menu.svg b/libs/assets/src/images/menu.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/menu.svg rename to libs/assets/src/images/menu.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/noise.png b/libs/assets/src/images/noise.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/noise.png rename to libs/assets/src/images/noise.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/plus-blue.svg b/libs/assets/src/images/plus-blue.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/plus-blue.svg rename to libs/assets/src/images/plus-blue.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/plus-grey.svg b/libs/assets/src/images/plus-grey.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/plus-grey.svg rename to libs/assets/src/images/plus-grey.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/portisIcon.png b/libs/assets/src/images/portisIcon.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/portisIcon.png rename to libs/assets/src/images/portisIcon.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/question-mark.svg b/libs/assets/src/images/question-mark.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/question-mark.svg rename to libs/assets/src/images/question-mark.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/question.svg b/libs/assets/src/images/question.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/question.svg rename to libs/assets/src/images/question.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/router-icon-grey.svg b/libs/assets/src/images/router-icon-grey.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/router-icon-grey.svg rename to libs/assets/src/images/router-icon-grey.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/sandtexture.webp b/libs/assets/src/images/sandtexture.webp similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/sandtexture.webp rename to libs/assets/src/images/sandtexture.webp diff --git a/apps/cowswap-frontend/src/legacy/assets/images/santa-hat.png b/libs/assets/src/images/santa-hat.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/santa-hat.png rename to libs/assets/src/images/santa-hat.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/spinner.svg b/libs/assets/src/images/spinner.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/spinner.svg rename to libs/assets/src/images/spinner.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/squiggle.png b/libs/assets/src/images/squiggle.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/squiggle.png rename to libs/assets/src/images/squiggle.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/survey-orb.svg b/libs/assets/src/images/survey-orb.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/survey-orb.svg rename to libs/assets/src/images/survey-orb.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/token-list-logo.png b/libs/assets/src/images/token-list-logo.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/token-list-logo.png rename to libs/assets/src/images/token-list-logo.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/token-list/lists-dark.png b/libs/assets/src/images/token-list/lists-dark.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/token-list/lists-dark.png rename to libs/assets/src/images/token-list/lists-dark.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/token-list/lists-light.png b/libs/assets/src/images/token-list/lists-light.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/token-list/lists-light.png rename to libs/assets/src/images/token-list/lists-light.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/token-logo.png b/libs/assets/src/images/token-logo.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/token-logo.png rename to libs/assets/src/images/token-logo.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/tokenlistsgrouped.png b/libs/assets/src/images/tokenlistsgrouped.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/tokenlistsgrouped.png rename to libs/assets/src/images/tokenlistsgrouped.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/trustWallet.png b/libs/assets/src/images/trustWallet.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/trustWallet.png rename to libs/assets/src/images/trustWallet.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/ukraine.png b/libs/assets/src/images/ukraine.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/ukraine.png rename to libs/assets/src/images/ukraine.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/widget-screenshot.png b/libs/assets/src/images/widget-screenshot.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/widget-screenshot.png rename to libs/assets/src/images/widget-screenshot.png diff --git a/apps/cowswap-frontend/src/legacy/assets/images/x.svg b/libs/assets/src/images/x.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/x.svg rename to libs/assets/src/images/x.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/images/xl_uni.png b/libs/assets/src/images/xl_uni.png similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/images/xl_uni.png rename to libs/assets/src/images/xl_uni.png diff --git a/libs/assets/src/index.ts b/libs/assets/src/index.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/cowswap-frontend/src/legacy/assets/styles/styled.ts b/libs/assets/src/styles/styled.ts similarity index 88% rename from apps/cowswap-frontend/src/legacy/assets/styles/styled.ts rename to libs/assets/src/styles/styled.ts index 8273f079f6..24e3d25d78 100644 --- a/apps/cowswap-frontend/src/legacy/assets/styles/styled.ts +++ b/libs/assets/src/styles/styled.ts @@ -1,7 +1,5 @@ import styled from 'styled-components/macro' -import { UI } from 'common/constants/theme' - // with font size convert to rems export const Txt = styled.span<{ fontSize?: number @@ -16,6 +14,6 @@ export const Txt = styled.span<{ font-size: ${({ fontSize }) => `${fontSize ? fontSize : 12}px`}; font-weight: ${({ fontWeight }) => (fontWeight ? fontWeight : 'normal')}; line-height: ${({ lineHeight }) => (lineHeight ? `${lineHeight}px` : 1.2)}; - color: var(${UI.COLOR_TEXT1}); + color: var(--cow-color-text1); gap: ${({ gap }) => (gap ? `${gap}px` : 0)}; ` diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/QR.svg b/libs/assets/src/svg/QR.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/QR.svg rename to libs/assets/src/svg/QR.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/arbitrum_logo.svg b/libs/assets/src/svg/arbitrum_logo.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/arbitrum_logo.svg rename to libs/assets/src/svg/arbitrum_logo.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/celo_logo.svg b/libs/assets/src/svg/celo_logo.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/celo_logo.svg rename to libs/assets/src/svg/celo_logo.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/dot_line.svg b/libs/assets/src/svg/dot_line.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/dot_line.svg rename to libs/assets/src/svg/dot_line.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/lightcircle.svg b/libs/assets/src/svg/lightcircle.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/lightcircle.svg rename to libs/assets/src/svg/lightcircle.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/logo.svg b/libs/assets/src/svg/logo.svg similarity index 99% rename from apps/cowswap-frontend/src/legacy/assets/svg/logo.svg rename to libs/assets/src/svg/logo.svg index d93197e48b..46a1821920 100644 --- a/apps/cowswap-frontend/src/legacy/assets/svg/logo.svg +++ b/libs/assets/src/svg/logo.svg @@ -10,4 +10,5 @@ + diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/logo_pink.svg b/libs/assets/src/svg/logo_pink.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/logo_pink.svg rename to libs/assets/src/svg/logo_pink.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/matic-token-icon.svg b/libs/assets/src/svg/matic-token-icon.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/matic-token-icon.svg rename to libs/assets/src/svg/matic-token-icon.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/optimism_logo.svg b/libs/assets/src/svg/optimism_logo.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/optimism_logo.svg rename to libs/assets/src/svg/optimism_logo.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/optimistic_ethereum.svg b/libs/assets/src/svg/optimistic_ethereum.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/optimistic_ethereum.svg rename to libs/assets/src/svg/optimistic_ethereum.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/polygon-matic-logo.svg b/libs/assets/src/svg/polygon-matic-logo.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/polygon-matic-logo.svg rename to libs/assets/src/svg/polygon-matic-logo.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/question.svg b/libs/assets/src/svg/question.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/question.svg rename to libs/assets/src/svg/question.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/static_route.svg b/libs/assets/src/svg/static_route.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/static_route.svg rename to libs/assets/src/svg/static_route.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/switch.svg b/libs/assets/src/svg/switch.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/switch.svg rename to libs/assets/src/svg/switch.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/tokenlist.svg b/libs/assets/src/svg/tokenlist.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/tokenlist.svg rename to libs/assets/src/svg/tokenlist.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/wordmark.svg b/libs/assets/src/svg/wordmark.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/wordmark.svg rename to libs/assets/src/svg/wordmark.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/wordmark_pink.svg b/libs/assets/src/svg/wordmark_pink.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/wordmark_pink.svg rename to libs/assets/src/svg/wordmark_pink.svg diff --git a/apps/cowswap-frontend/src/legacy/assets/svg/wordmark_white.svg b/libs/assets/src/svg/wordmark_white.svg similarity index 100% rename from apps/cowswap-frontend/src/legacy/assets/svg/wordmark_white.svg rename to libs/assets/src/svg/wordmark_white.svg diff --git a/libs/assets/tsconfig.json b/libs/assets/tsconfig.json new file mode 100644 index 0000000000..bab74ff2e6 --- /dev/null +++ b/libs/assets/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["vite/client"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/assets/tsconfig.lib.json b/libs/assets/tsconfig.lib.json new file mode 100644 index 0000000000..1b2b0c12df --- /dev/null +++ b/libs/assets/tsconfig.lib.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node", "vite/client"] + }, + "files": ["../../node_modules/@nx/react/typings/cssmodule.d.ts", "../../node_modules/@nx/react/typings/image.d.ts"], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/assets/tsconfig.spec.json b/libs/assets/tsconfig.spec.json new file mode 100644 index 0000000000..26ef046ac5 --- /dev/null +++ b/libs/assets/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/libs/assets/vite.config.ts b/libs/assets/vite.config.ts new file mode 100644 index 0000000000..f4563c5110 --- /dev/null +++ b/libs/assets/vite.config.ts @@ -0,0 +1,49 @@ +/// +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' +import viteTsConfigPaths from 'vite-tsconfig-paths' +import dts from 'vite-plugin-dts' +import * as path from 'path' + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/assets', + + plugins: [ + dts({ + entryRoot: 'src', + tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'), + skipDiagnostics: true, + }), + react(), + viteTsConfigPaths({ + root: '../../', + }), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + lib: { + // Could also be a dictionary or array of multiple entry points. + entry: 'src/index.ts', + name: 'assets', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es', 'cjs'], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: ['react', 'react-dom', 'react/jsx-runtime'], + }, + }, +}) diff --git a/libs/common-const/.babelrc b/libs/common-const/.babelrc new file mode 100644 index 0000000000..ef4889c1ab --- /dev/null +++ b/libs/common-const/.babelrc @@ -0,0 +1,20 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [ + [ + "styled-components", + { + "pure": true, + "ssr": true + } + ] + ] +} diff --git a/libs/common-const/.eslintrc.json b/libs/common-const/.eslintrc.json new file mode 100644 index 0000000000..a39ac5d057 --- /dev/null +++ b/libs/common-const/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["plugin:@nx/react", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/common-const/README.md b/libs/common-const/README.md new file mode 100644 index 0000000000..01bdccc346 --- /dev/null +++ b/libs/common-const/README.md @@ -0,0 +1 @@ +# Common const diff --git a/libs/common-const/jest.config.ts b/libs/common-const/jest.config.ts new file mode 100644 index 0000000000..96c3ce6fcd --- /dev/null +++ b/libs/common-const/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'common-const', + preset: '../../jest.preset.js', + transform: { + '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', + '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/libs/common-const', +} diff --git a/libs/common-const/package.json b/libs/common-const/package.json new file mode 100644 index 0000000000..a4d54a4f13 --- /dev/null +++ b/libs/common-const/package.json @@ -0,0 +1,12 @@ +{ + "name": "@cowprotocol/common-const", + "version": "0.0.1", + "main": "./index.js", + "types": "./index.d.ts", + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.js" + } + } +} diff --git a/libs/common-const/project.json b/libs/common-const/project.json new file mode 100644 index 0000000000..ab3b759bb3 --- /dev/null +++ b/libs/common-const/project.json @@ -0,0 +1,46 @@ +{ + "name": "@cowprotocol/common-const", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/common-const/src", + "projectType": "library", + "tags": [], + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/common-const/**/*.{ts,tsx,js,jsx}"] + } + }, + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/libs/common-const" + }, + "configurations": { + "development": { + "mode": "development" + }, + "production": { + "mode": "production" + } + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/common-const/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + } +} diff --git a/apps/cowswap-frontend/src/legacy/constants/addresses.ts b/libs/common-const/src/addresses.ts similarity index 63% rename from apps/cowswap-frontend/src/legacy/constants/addresses.ts rename to libs/common-const/src/addresses.ts index 0400a3672d..8857ca62c6 100644 --- a/apps/cowswap-frontend/src/legacy/constants/addresses.ts +++ b/libs/common-const/src/addresses.ts @@ -1,9 +1,19 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { constructSameAddressMap } from '../utils/constructSameAddressMap' - export type AddressMap = { [chainId: number]: string } +const DEFAULT_NETWORKS = [SupportedChainId.MAINNET, SupportedChainId.GOERLI] + +function constructSameAddressMap( + address: T, + additionalNetworks: SupportedChainId[] = [] +): { [chainId: number]: T } { + return DEFAULT_NETWORKS.concat(additionalNetworks).reduce<{ [chainId: number]: T }>((memo, chainId) => { + memo[chainId] = address + return memo + }, {}) +} + export const MULTICALL_ADDRESS: AddressMap = { ...constructSameAddressMap('0x1F98415757620B543A52E61c46B32eB19261F984', []), [SupportedChainId.GNOSIS_CHAIN]: '0x0f41c16b8ad27c11f181eca85f0941868c1297af', diff --git a/apps/cowswap-frontend/src/legacy/constants/chainInfo.ts b/libs/common-const/src/chainInfo.ts similarity index 89% rename from apps/cowswap-frontend/src/legacy/constants/chainInfo.ts rename to libs/common-const/src/chainInfo.ts index 4c8d873581..f43a04c165 100644 --- a/apps/cowswap-frontend/src/legacy/constants/chainInfo.ts +++ b/libs/common-const/src/chainInfo.ts @@ -1,8 +1,8 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' -import GnosisChainLogo from 'legacy/assets/cow-swap/network-gnosis-chain-logo.svg' -import GoerliLogo from 'legacy/assets/cow-swap/network-goerli-logo.svg' -import EthereumLogo from 'legacy/assets/cow-swap/network-mainnet-logo.svg' +import GnosisChainLogo from '@cowprotocol/assets/cow-swap/network-gnosis-chain-logo.svg' +import GoerliLogo from '@cowprotocol/assets/cow-swap/network-goerli-logo.svg' +import EthereumLogo from '@cowprotocol/assets/cow-swap/network-mainnet-logo.svg' export enum NetworkType { L1, diff --git a/apps/cowswap-frontend/src/legacy/constants/index.ts b/libs/common-const/src/common.ts similarity index 96% rename from apps/cowswap-frontend/src/legacy/constants/index.ts rename to libs/common-const/src/common.ts index 4eb7a8a498..4488559c9f 100644 --- a/apps/cowswap-frontend/src/legacy/constants/index.ts +++ b/libs/common-const/src/common.ts @@ -1,12 +1,12 @@ import networksJson from '@cowprotocol/contracts/networks.json' import { IpfsConfig, SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' -import { ethFlowBarnJson, ethFlowProdJson } from '@cowswap/abis' +import { ethFlowBarnJson, ethFlowProdJson } from '@cowprotocol/abis' import { Fraction, Percent, Token } from '@uniswap/sdk-core' import BigNumber from 'bignumber.js' import ms from 'ms.macro' -import { PINATA_API_KEY, PINATA_SECRET_API_KEY } from 'legacy/constants/ipfs' +import { PINATA_API_KEY, PINATA_SECRET_API_KEY } from './ipfs' // TODO: move those consts to src/constants/common @@ -47,9 +47,6 @@ export const BARN_URL = `barn.cow.fi` export const APP_TITLE = 'CoW Swap | The smartest way to trade cryptocurrencies' -// Smart contract wallets are filtered out by default, no need to add them to this list -export const UNSUPPORTED_WC_WALLETS = new Set(['DeFi Wallet', 'WallETH']) - type Env = 'barn' | 'prod' export const COWSWAP_ETHFLOW_CONTRACT_ADDRESS: Record>> = { @@ -99,7 +96,6 @@ export const NATIVE_CURRENCY_BUY_TOKEN: { [chainId in ChainId | number]: Token } [ChainId.GNOSIS_CHAIN]: new Token(ChainId.GNOSIS_CHAIN, NATIVE_CURRENCY_BUY_ADDRESS, 18, 'xDAI', 'xDAI'), } -export const ORDER_ID_SHORT_LENGTH = 8 export const INPUT_OUTPUT_EXPLANATION = 'Only executed swaps incur fees.' export const PENDING_ORDERS_BUFFER = ms`60s` // 60s export const CANCELLED_ORDERS_PENDING_TIME = ms`5min` // 5min diff --git a/apps/cowswap-frontend/src/legacy/utils/gnosis_chain/constants.ts b/libs/common-const/src/gnosis_chain/constants.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/gnosis_chain/constants.ts rename to libs/common-const/src/gnosis_chain/constants.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/gnosis_chain/hack.ts b/libs/common-const/src/gnosis_chain/hack.ts similarity index 52% rename from apps/cowswap-frontend/src/legacy/utils/gnosis_chain/hack.ts rename to libs/common-const/src/gnosis_chain/hack.ts index fecc3472d0..5f3c2fd721 100644 --- a/apps/cowswap-frontend/src/legacy/utils/gnosis_chain/hack.ts +++ b/libs/common-const/src/gnosis_chain/hack.ts @@ -1,15 +1,18 @@ // this file essentially provides all the overrides employed in uniswap-xdai-sdk fork // + logic for chainId switch to/from xDAI -import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' - -import { GpEther as ETHER } from 'legacy/constants/tokens' +import { SupportedChainId } from '@cowprotocol/cow-sdk' import { XDAI_SYMBOL } from './constants' const CURRENCY_SYMBOLS_XDAI = { native: XDAI_SYMBOL, wrapped: 'wxDAI' } const CURRENCY_SYMBOLS_ETH = { native: 'Ether', wrapped: 'WETH' } -export function getChainCurrencySymbols(chainId?: ChainId): { native: string; wrapped: string } { +export function getChainCurrencySymbols(chainId?: SupportedChainId): { native: string; wrapped: string } { if (!chainId) return CURRENCY_SYMBOLS_ETH - return ETHER.onChain(chainId).symbol === XDAI_SYMBOL ? CURRENCY_SYMBOLS_XDAI : CURRENCY_SYMBOLS_ETH + + if (chainId === SupportedChainId.GNOSIS_CHAIN) { + return CURRENCY_SYMBOLS_XDAI + } + + return CURRENCY_SYMBOLS_ETH } diff --git a/apps/cowswap-frontend/src/legacy/utils/goerli/constants.ts b/libs/common-const/src/goerli/constants.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/goerli/constants.ts rename to libs/common-const/src/goerli/constants.ts diff --git a/libs/common-const/src/index.ts b/libs/common-const/src/index.ts new file mode 100644 index 0000000000..34320bd6e6 --- /dev/null +++ b/libs/common-const/src/index.ts @@ -0,0 +1,14 @@ +export * from './common' +export * from './locales' +export * from './lists' +export * from './tokens' +export * from './intl' +export * from './addresses' +export * from './misc' +export * from './chainInfo' +export * from './networks' +export * from './routing' +export * from './ipfs' +export * from './gnosis_chain/constants' +export * from './gnosis_chain/hack' +export { DAI_GOERLI, WETH_GOERLI, USDT_GOERLI } from './goerli/constants' diff --git a/apps/cowswap-frontend/src/common/constants/intl.ts b/libs/common-const/src/intl.ts similarity index 100% rename from apps/cowswap-frontend/src/common/constants/intl.ts rename to libs/common-const/src/intl.ts diff --git a/apps/cowswap-frontend/src/legacy/constants/ipfs.ts b/libs/common-const/src/ipfs.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/constants/ipfs.ts rename to libs/common-const/src/ipfs.ts diff --git a/apps/cowswap-frontend/src/legacy/constants/lists.ts b/libs/common-const/src/lists.ts similarity index 98% rename from apps/cowswap-frontend/src/legacy/constants/lists.ts rename to libs/common-const/src/lists.ts index e640b8d21b..9d26dc1b78 100644 --- a/apps/cowswap-frontend/src/legacy/constants/lists.ts +++ b/libs/common-const/src/lists.ts @@ -1,6 +1,6 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' -import { RAW_CODE_LINK } from 'legacy/constants' +import { RAW_CODE_LINK } from './common' export type NetworkLists = { [chain in ChainId]: string[] diff --git a/apps/cowswap-frontend/src/legacy/constants/locales.ts b/libs/common-const/src/locales.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/constants/locales.ts rename to libs/common-const/src/locales.ts diff --git a/apps/cowswap-frontend/src/legacy/constants/misc.ts b/libs/common-const/src/misc.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/constants/misc.ts rename to libs/common-const/src/misc.ts diff --git a/apps/cowswap-frontend/src/legacy/constants/networks.ts b/libs/common-const/src/networks.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/constants/networks.ts rename to libs/common-const/src/networks.ts diff --git a/apps/cowswap-frontend/src/legacy/constants/routing.ts b/libs/common-const/src/routing.ts similarity index 95% rename from apps/cowswap-frontend/src/legacy/constants/routing.ts rename to libs/common-const/src/routing.ts index 07369e0c80..4ff9a047cb 100644 --- a/apps/cowswap-frontend/src/legacy/constants/routing.ts +++ b/libs/common-const/src/routing.ts @@ -21,9 +21,10 @@ import { USDT, WBTC, WRAPPED_NATIVE_CURRENCY, -} from 'legacy/constants/tokens' -import { USDC_GNOSIS_CHAIN, WBTC_GNOSIS_CHAIN, WETH_GNOSIS_CHAIN } from 'legacy/utils/gnosis_chain/constants' -import { DAI_GOERLI, USDC_GOERLI } from 'legacy/utils/goerli/constants' +} from './tokens' + +import { USDC_GNOSIS_CHAIN, WBTC_GNOSIS_CHAIN, WETH_GNOSIS_CHAIN } from './gnosis_chain/constants' +import { DAI_GOERLI, USDC_GOERLI } from './goerli/constants' type ChainTokenList = { readonly [chainId: number]: Token[] diff --git a/apps/cowswap-frontend/src/legacy/constants/tokenLists/broken.tokenlist.json b/libs/common-const/src/tokenLists/broken.tokenlist.json similarity index 100% rename from apps/cowswap-frontend/src/legacy/constants/tokenLists/broken.tokenlist.json rename to libs/common-const/src/tokenLists/broken.tokenlist.json diff --git a/apps/cowswap-frontend/src/legacy/constants/tokenLists/unsupported.tokenlist.json b/libs/common-const/src/tokenLists/unsupported.tokenlist.json similarity index 100% rename from apps/cowswap-frontend/src/legacy/constants/tokenLists/unsupported.tokenlist.json rename to libs/common-const/src/tokenLists/unsupported.tokenlist.json diff --git a/apps/cowswap-frontend/src/legacy/constants/tokens.ts b/libs/common-const/src/tokens.ts similarity index 95% rename from apps/cowswap-frontend/src/legacy/constants/tokens.ts rename to libs/common-const/src/tokens.ts index e36b4e57fa..11278f34f3 100644 --- a/apps/cowswap-frontend/src/legacy/constants/tokens.ts +++ b/libs/common-const/src/tokens.ts @@ -1,12 +1,12 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Currency, Ether, NativeCurrency, Token, WETH9 } from '@uniswap/sdk-core' -import cowLogo from 'legacy/assets/cow-swap/cow.svg' -import gnoLogo from 'legacy/assets/cow-swap/gno.png' -import usdcLogo from 'legacy/assets/cow-swap/usdc.png' -import vCowLogo from 'legacy/assets/cow-swap/vCOW.png' -import wxDaiLogo from 'legacy/assets/cow-swap/wxdai.png' -import { COW_CONTRACT_ADDRESS, V_COW_CONTRACT_ADDRESS } from 'legacy/constants' +import cowLogo from '@cowprotocol/assets/cow-swap/cow.svg' +import gnoLogo from '@cowprotocol/assets/cow-swap/gno.png' +import usdcLogo from '@cowprotocol/assets/cow-swap/usdc.png' +import vCowLogo from '@cowprotocol/assets/cow-swap/vCOW.png' +import wxDaiLogo from '@cowprotocol/assets/cow-swap/wxdai.png' + import { USDC_GNOSIS_CHAIN, WBTC_GNOSIS_CHAIN, @@ -14,8 +14,9 @@ import { WXDAI, XDAI_NAME, XDAI_SYMBOL, -} from 'legacy/utils/gnosis_chain/constants' -import { DAI_GOERLI, USDT_GOERLI, WBTC_GOERLI, WETH_GOERLI } from 'legacy/utils/goerli/constants' +} from './gnosis_chain/constants' +import { DAI_GOERLI, USDT_GOERLI, WBTC_GOERLI, WETH_GOERLI } from './goerli/constants' +import { COW_CONTRACT_ADDRESS, V_COW_CONTRACT_ADDRESS } from './common' export const USDC_MAINNET = new Token( SupportedChainId.MAINNET, diff --git a/libs/common-const/tsconfig.json b/libs/common-const/tsconfig.json new file mode 100644 index 0000000000..bab74ff2e6 --- /dev/null +++ b/libs/common-const/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["vite/client"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/common-const/tsconfig.lib.json b/libs/common-const/tsconfig.lib.json new file mode 100644 index 0000000000..1b2b0c12df --- /dev/null +++ b/libs/common-const/tsconfig.lib.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node", "vite/client"] + }, + "files": ["../../node_modules/@nx/react/typings/cssmodule.d.ts", "../../node_modules/@nx/react/typings/image.d.ts"], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/common-const/tsconfig.spec.json b/libs/common-const/tsconfig.spec.json new file mode 100644 index 0000000000..26ef046ac5 --- /dev/null +++ b/libs/common-const/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/libs/common-const/vite.config.ts b/libs/common-const/vite.config.ts new file mode 100644 index 0000000000..fc139c12d2 --- /dev/null +++ b/libs/common-const/vite.config.ts @@ -0,0 +1,49 @@ +/// +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' +import viteTsConfigPaths from 'vite-tsconfig-paths' +import dts from 'vite-plugin-dts' +import * as path from 'path' + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/common-const', + + plugins: [ + dts({ + entryRoot: 'src', + tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'), + skipDiagnostics: true, + }), + react(), + viteTsConfigPaths({ + root: '../../', + }), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + lib: { + // Could also be a dictionary or array of multiple entry points. + entry: 'src/index.ts', + name: 'common-const', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es', 'cjs'], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: ['react', 'react-dom', 'react/jsx-runtime'], + }, + }, +}) diff --git a/libs/common-hooks/.babelrc b/libs/common-hooks/.babelrc new file mode 100644 index 0000000000..ef4889c1ab --- /dev/null +++ b/libs/common-hooks/.babelrc @@ -0,0 +1,20 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [ + [ + "styled-components", + { + "pure": true, + "ssr": true + } + ] + ] +} diff --git a/libs/common-hooks/.eslintrc.json b/libs/common-hooks/.eslintrc.json new file mode 100644 index 0000000000..231aaa5f83 --- /dev/null +++ b/libs/common-hooks/.eslintrc.json @@ -0,0 +1,21 @@ +{ + "extends": ["plugin:@nx/react", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "rules": { + "@typescript-eslint/no-explicit-any": "off" + }, + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/common-hooks/README.md b/libs/common-hooks/README.md new file mode 100644 index 0000000000..6fc5afcb20 --- /dev/null +++ b/libs/common-hooks/README.md @@ -0,0 +1 @@ +# Common hooks diff --git a/libs/common-hooks/jest.config.ts b/libs/common-hooks/jest.config.ts new file mode 100644 index 0000000000..ca22397e85 --- /dev/null +++ b/libs/common-hooks/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'common-hooks', + preset: '../../jest.preset.js', + transform: { + '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', + '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/libs/common-hooks', +} diff --git a/libs/common-hooks/package.json b/libs/common-hooks/package.json new file mode 100644 index 0000000000..38109c240d --- /dev/null +++ b/libs/common-hooks/package.json @@ -0,0 +1,12 @@ +{ + "name": "@cowprotocol/common-hooks", + "version": "0.0.1", + "main": "./index.js", + "types": "./index.d.ts", + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.js" + } + } +} diff --git a/libs/common-hooks/project.json b/libs/common-hooks/project.json new file mode 100644 index 0000000000..7de25fb3e2 --- /dev/null +++ b/libs/common-hooks/project.json @@ -0,0 +1,46 @@ +{ + "name": "@cowprotocol/common-hooks", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/common-hooks/src", + "projectType": "library", + "tags": [], + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/common-hooks/**/*.{ts,tsx,js,jsx}"] + } + }, + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/libs/common-hooks" + }, + "configurations": { + "development": { + "mode": "development" + }, + "production": { + "mode": "production" + } + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/common-hooks/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + } +} diff --git a/libs/common-hooks/src/index.ts b/libs/common-hooks/src/index.ts new file mode 100644 index 0000000000..57ca43320f --- /dev/null +++ b/libs/common-hooks/src/index.ts @@ -0,0 +1,24 @@ +export * from './useContract' +export * from './useDebounce' +export * from './usePrevious' +export * from './useParsedQueryString' +export * from './useIsMounted' +export * from './useLoadingWithTimeout' +export * from './useInterval' +export * from './useNetworkName' +export * from './useIsOnline' +export * from './useTheme' +export * from './useColor' +export * from './useToggle' +export * from './useOnClickOutside' +export * from './useFilterTokens' +export * from './useTimeAgo' +export * from './useIsWindowVisible' +export * from './useGetReceipt' +export * from './useBlockNumber' +export * from './useMachineTime' +export * from './useFetchFile' +export * from './useWindowSize' +export * from './useCopyClipboard' +export * from './useLast' +export * from './useDebouncedChangeHandler' diff --git a/apps/cowswap-frontend/src/lib/hooks/useBlockNumber.tsx b/libs/common-hooks/src/useBlockNumber.tsx similarity index 95% rename from apps/cowswap-frontend/src/lib/hooks/useBlockNumber.tsx rename to libs/common-hooks/src/useBlockNumber.tsx index d17087e524..0eee5685fb 100644 --- a/apps/cowswap-frontend/src/lib/hooks/useBlockNumber.tsx +++ b/libs/common-hooks/src/useBlockNumber.tsx @@ -1,9 +1,8 @@ import { createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState } from 'react' +import { useIsWindowVisible } from './useIsWindowVisible' import { useWeb3React } from '@web3-react/core' -import useIsWindowVisible from 'legacy/hooks/useIsWindowVisible' - const MISSING_PROVIDER = Symbol() const BlockNumberContext = createContext< | { @@ -22,7 +21,7 @@ function useBlockNumberContext() { } /** Requires that BlockUpdater be installed in the DOM tree. */ -export default function useBlockNumber(): number | undefined { +export function useBlockNumber(): number | undefined { return useBlockNumberContext().value } diff --git a/apps/cowswap-frontend/src/legacy/hooks/useColor/useColorMod.ts b/libs/common-hooks/src/useColor/index.ts similarity index 95% rename from apps/cowswap-frontend/src/legacy/hooks/useColor/useColorMod.ts rename to libs/common-hooks/src/useColor/index.ts index 5a252d47ff..f1c2c8b8e1 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useColor/useColorMod.ts +++ b/libs/common-hooks/src/useColor/index.ts @@ -3,8 +3,7 @@ import { useLayoutEffect, useState } from 'react' import Vibrant from 'node-vibrant/lib/bundle' import { shade } from 'polished' import { hex } from 'wcag-contrast' - -import uriToHttp from 'lib/utils/uriToHttp' +import { uriToHttp } from '@cowprotocol/common-utils' export async function getColorFromUriPath(uri: string): Promise { const formattedPath = uriToHttp(uri)[0] diff --git a/apps/cowswap-frontend/src/legacy/hooks/useContract.ts b/libs/common-hooks/src/useContract.ts similarity index 82% rename from apps/cowswap-frontend/src/legacy/hooks/useContract.ts rename to libs/common-hooks/src/useContract.ts index f4f421d9ef..f526ff170f 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useContract.ts +++ b/libs/common-hooks/src/useContract.ts @@ -2,17 +2,11 @@ import { useMemo } from 'react' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { - ArgentWalletDetector, - EnsPublicResolver, - EnsRegistrar, Erc20, Erc721, Erc1155, Weth, - ArgentWalletDetectorAbi, Eip2612Abi, - EnsPublicResolverAbi, - EnsAbi, Erc20Abi, Erc20Bytes32Abi, Erc721Abi, @@ -26,7 +20,7 @@ import { vCowAbi, UniswapInterfaceMulticall, CoWSwapEthFlowAbi, -} from '@cowswap/abis' +} from '@cowprotocol/abis' import { Contract } from '@ethersproject/contracts' import type { JsonRpcProvider } from '@ethersproject/providers' import { useWeb3React } from '@web3-react/core' @@ -35,13 +29,12 @@ import { COWSWAP_ETHFLOW_CONTRACT_ADDRESS, GP_SETTLEMENT_CONTRACT_ADDRESS, V_COW_CONTRACT_ADDRESS, -} from 'legacy/constants' -import { ARGENT_WALLET_DETECTOR_ADDRESS, ENS_REGISTRAR_ADDRESSES, MULTICALL_ADDRESS } from 'legacy/constants/addresses' -import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' -import { getContract } from 'legacy/utils' -import { isEns, isProd, isStaging } from 'legacy/utils/environments' + MULTICALL_ADDRESS, + WRAPPED_NATIVE_CURRENCY, +} from '@cowprotocol/common-const' +import { getContract, isEns, isProd, isStaging } from '@cowprotocol/common-utils' -import { useWalletInfo } from 'modules/wallet' +import { useWalletInfo } from '@cowprotocol/wallet' const { abi: MulticallABI } = UniswapInterfaceMulticallAbi @@ -90,18 +83,6 @@ export function useERC1155Contract(nftAddress?: string) { return useContract(nftAddress, Erc1155Abi, false) } -export function useArgentWalletDetectorContract() { - return useContract(ARGENT_WALLET_DETECTOR_ADDRESS, ArgentWalletDetectorAbi, false) -} - -export function useENSRegistrarContract(withSignerIfPossible?: boolean) { - return useContract(ENS_REGISTRAR_ADDRESSES, EnsAbi, withSignerIfPossible) -} - -export function useENSResolverContract(address: string | undefined, withSignerIfPossible?: boolean) { - return useContract(address, EnsPublicResolverAbi, withSignerIfPossible) -} - export function useBytes32TokenContract(tokenAddress?: string, withSignerIfPossible?: boolean): Contract | null { return useContract(tokenAddress, Erc20Bytes32Abi, withSignerIfPossible) } diff --git a/apps/cowswap-frontend/src/legacy/hooks/useCopyClipboard.ts b/libs/common-hooks/src/useCopyClipboard.ts similarity index 85% rename from apps/cowswap-frontend/src/legacy/hooks/useCopyClipboard.ts rename to libs/common-hooks/src/useCopyClipboard.ts index c922affd50..a0b9e91803 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useCopyClipboard.ts +++ b/libs/common-hooks/src/useCopyClipboard.ts @@ -2,7 +2,7 @@ import { useCallback, useEffect, useState } from 'react' import copy from 'copy-to-clipboard' -export default function useCopyClipboard(timeout = 500): [boolean, (toCopy: string) => void] { +export function useCopyClipboard(timeout = 500): [boolean, (toCopy: string) => void] { const [isCopied, setIsCopied] = useState(false) const staticCopy = useCallback((text: string) => { diff --git a/apps/cowswap-frontend/src/legacy/hooks/useDebounce.ts b/libs/common-hooks/src/useDebounce.ts similarity index 92% rename from apps/cowswap-frontend/src/legacy/hooks/useDebounce.ts rename to libs/common-hooks/src/useDebounce.ts index c03ee2bc68..fcedeacaa6 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useDebounce.ts +++ b/libs/common-hooks/src/useDebounce.ts @@ -5,7 +5,7 @@ import { useEffect, useState } from 'react' * Non-primitives *must* wrap the value in useMemo, or the value will be updated due to referential inequality. */ // modified from https://usehooks.com/useDebounce/ -export default function useDebounce(value: T, delay: number): T { +export function useDebounce(value: T, delay: number): T { const [debouncedValue, setDebouncedValue] = useState(value) useEffect(() => { diff --git a/apps/cowswap-frontend/src/legacy/hooks/useDebouncedChangeHandler.tsx b/libs/common-hooks/src/useDebouncedChangeHandler.tsx similarity index 95% rename from apps/cowswap-frontend/src/legacy/hooks/useDebouncedChangeHandler.tsx rename to libs/common-hooks/src/useDebouncedChangeHandler.tsx index 21a71f9b90..5d78e63ca3 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useDebouncedChangeHandler.tsx +++ b/libs/common-hooks/src/useDebouncedChangeHandler.tsx @@ -6,7 +6,7 @@ import { useCallback, useEffect, useRef, useState } from 'react' * @param onChange change handler that should receive the debounced updates to the value * @param debouncedMs how long we should wait for changes to be applied */ -export default function useDebouncedChangeHandler( +export function useDebouncedChangeHandler( value: T, onChange: (newValue: T) => void, debouncedMs = 100 diff --git a/apps/cowswap-frontend/src/legacy/hooks/useFetchFile.ts b/libs/common-hooks/src/useFetchFile.ts similarity index 93% rename from apps/cowswap-frontend/src/legacy/hooks/useFetchFile.ts rename to libs/common-hooks/src/useFetchFile.ts index 0ee84cf6e9..0ad4d93c52 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useFetchFile.ts +++ b/libs/common-hooks/src/useFetchFile.ts @@ -4,7 +4,7 @@ function getErrorMessage(filePath: string, res: Response): string { return `Error fetching file ${filePath} - status: ${res.statusText}` } -export default function useFetchFile(filePath: string) { +export function useFetchFile(filePath: string) { const [file, setFile] = useState(null) const [error, setError] = useState(null) diff --git a/apps/cowswap-frontend/src/legacy/hooks/useFilterTokens.ts b/libs/common-hooks/src/useFilterTokens.ts similarity index 88% rename from apps/cowswap-frontend/src/legacy/hooks/useFilterTokens.ts rename to libs/common-hooks/src/useFilterTokens.ts index 8143f436e9..00539eb4cf 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useFilterTokens.ts +++ b/libs/common-hooks/src/useFilterTokens.ts @@ -2,9 +2,9 @@ import { useMemo } from 'react' import { Token } from '@uniswap/sdk-core' -import { isAddress } from 'legacy/utils' +import { isAddress } from '@cowprotocol/common-utils' -export default function useFilterTokens(tokens: Token[], query: string): Token[] { +export function useFilterTokens(tokens: Token[], query: string): Token[] { return useMemo(() => { // only calc anything if we actually have more than 1 token in list // and the user is actively searching tokens diff --git a/apps/cowswap-frontend/src/legacy/hooks/useGetReceipt.ts b/libs/common-hooks/src/useGetReceipt.ts similarity index 78% rename from apps/cowswap-frontend/src/legacy/hooks/useGetReceipt.ts rename to libs/common-hooks/src/useGetReceipt.ts index 90f66fa516..533ee94615 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useGetReceipt.ts +++ b/libs/common-hooks/src/useGetReceipt.ts @@ -3,20 +3,21 @@ import { useCallback } from 'react' import { TransactionReceipt } from '@ethersproject/abstract-provider' import { useWeb3React } from '@web3-react/core' -import { RetryResult } from 'types' - -import { retry, RetryableError, RetryOptions } from 'legacy/utils/retry' - -import { useWalletInfo } from 'modules/wallet' +import { retry, RetryableError, RetryOptions } from '@cowprotocol/common-utils' +import { SupportedChainId } from '@cowprotocol/cow-sdk' const DEFAULT_RETRY_OPTIONS: RetryOptions = { n: 3, minWait: 1000, maxWait: 3000 } const RETRY_OPTIONS_BY_CHAIN_ID: { [chainId: number]: RetryOptions } = {} +interface RetryResult { + promise: Promise + cancel: () => void +} + export type GetReceipt = (hash: string) => RetryResult -export function useGetReceipt(): GetReceipt { +export function useGetReceipt(chainId: SupportedChainId): GetReceipt { const { provider } = useWeb3React() - const { chainId } = useWalletInfo() const getReceipt = useCallback( (hash) => { diff --git a/apps/cowswap-frontend/src/lib/hooks/useInterval.ts b/libs/common-hooks/src/useInterval.ts similarity index 89% rename from apps/cowswap-frontend/src/lib/hooks/useInterval.ts rename to libs/common-hooks/src/useInterval.ts index 926e7c2545..274b32511b 100644 --- a/apps/cowswap-frontend/src/lib/hooks/useInterval.ts +++ b/libs/common-hooks/src/useInterval.ts @@ -6,7 +6,7 @@ import { useEffect, useRef } from 'react' * @param delay if null, the callback will not be invoked * @param leading if true, the callback will be invoked immediately (on the leading edge); otherwise, it will be invoked after delay */ -export default function useInterval(callback: () => void, delay: null | number, leading = true) { +export function useInterval(callback: () => void, delay: null | number, leading = true) { const savedCallback = useRef<() => void>() // Remember the latest callback. diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsMounted.ts b/libs/common-hooks/src/useIsMounted.ts similarity index 89% rename from apps/cowswap-frontend/src/legacy/hooks/useIsMounted.ts rename to libs/common-hooks/src/useIsMounted.ts index ef187c973b..f91a60b959 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useIsMounted.ts +++ b/libs/common-hooks/src/useIsMounted.ts @@ -4,7 +4,7 @@ import { useRef, useEffect } from 'react' * Creates a ref that can be used to solve the issue of * "Can't perform a React state update on an unmounted component." */ -export default function useIsMounted() { +export function useIsMounted() { const isMounted = useRef(false) useEffect(() => { diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsOnline.ts b/libs/common-hooks/src/useIsOnline.ts similarity index 95% rename from apps/cowswap-frontend/src/legacy/hooks/useIsOnline.ts rename to libs/common-hooks/src/useIsOnline.ts index f98a07c190..54d957f736 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useIsOnline.ts +++ b/libs/common-hooks/src/useIsOnline.ts @@ -2,7 +2,7 @@ import { useCallback, useEffect, useState } from 'react' import ms from 'ms.macro' -import { getTimeoutAbortController } from 'utils/request' +import { getTimeoutAbortController } from '@cowprotocol/common-utils' const CONNECTIVITY_CHECK_POLLING_TIME = ms`30s` const CONNECTIVITY_CHECK_TIMEOUT = ms`15s` @@ -37,7 +37,7 @@ export async function hasConnectivity(): Promise { /** * Returns whether the window is currently visible to the user. */ -export default function useIsOnline(): boolean { +export function useIsOnline(): boolean { const [online, setOnline] = useState(isOnline()) // Double-check if we REALLY don't have connectivity when the browser says so (There's cases where `online = false` flag might be not true) diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsWindowVisible.ts b/libs/common-hooks/src/useIsWindowVisible.ts similarity index 93% rename from apps/cowswap-frontend/src/legacy/hooks/useIsWindowVisible.ts rename to libs/common-hooks/src/useIsWindowVisible.ts index 2fe4247355..765def549a 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useIsWindowVisible.ts +++ b/libs/common-hooks/src/useIsWindowVisible.ts @@ -11,7 +11,7 @@ function isWindowVisible() { /** * Returns whether the window is currently visible to the user. */ -export default function useIsWindowVisible(): boolean { +export function useIsWindowVisible(): boolean { const [focused, setFocused] = useState(false) const listener = useCallback(() => { setFocused(isWindowVisible()) diff --git a/apps/cowswap-frontend/src/legacy/hooks/useLast.ts b/libs/common-hooks/src/useLast.ts similarity index 94% rename from apps/cowswap-frontend/src/legacy/hooks/useLast.ts rename to libs/common-hooks/src/useLast.ts index 33f169bd22..07c1fbc0ad 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useLast.ts +++ b/libs/common-hooks/src/useLast.ts @@ -5,7 +5,7 @@ import { useEffect, useState } from 'react' * @param value changing value * @param filterFn function that determines whether a given value should be considered for the last value */ -export default function useLast( +export function useLast( value: T | undefined | null, filterFn?: (value: T | null | undefined) => boolean ): T | null | undefined { diff --git a/apps/cowswap-frontend/src/legacy/hooks/useLoadingWithTimeout.ts b/libs/common-hooks/src/useLoadingWithTimeout.ts similarity index 92% rename from apps/cowswap-frontend/src/legacy/hooks/useLoadingWithTimeout.ts rename to libs/common-hooks/src/useLoadingWithTimeout.ts index 73675783e5..f0ef775825 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useLoadingWithTimeout.ts +++ b/libs/common-hooks/src/useLoadingWithTimeout.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' -export default function useLoadingWithTimeout(isLoading: boolean, time: number) { +export function useLoadingWithTimeout(isLoading: boolean, time: number) { const [delayedLoad, setDelayedLoad] = useState(isLoading) useEffect(() => { diff --git a/apps/cowswap-frontend/src/legacy/hooks/useMachineTime.ts b/libs/common-hooks/src/useMachineTime.ts similarity index 52% rename from apps/cowswap-frontend/src/legacy/hooks/useMachineTime.ts rename to libs/common-hooks/src/useMachineTime.ts index a25087b251..3781dcfce9 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useMachineTime.ts +++ b/libs/common-hooks/src/useMachineTime.ts @@ -1,8 +1,7 @@ import { useState } from 'react' +import { useInterval } from './useInterval' -import useInterval from 'lib/hooks/useInterval' - -const useMachineTimeMs = (updateInterval: number): number => { +export const useMachineTimeMs = (updateInterval: number): number => { const [now, setNow] = useState(Date.now()) useInterval(() => { @@ -10,5 +9,3 @@ const useMachineTimeMs = (updateInterval: number): number => { }, updateInterval) return now } - -export default useMachineTimeMs diff --git a/libs/common-hooks/src/useNetworkName.ts b/libs/common-hooks/src/useNetworkName.ts new file mode 100644 index 0000000000..93492f5df0 --- /dev/null +++ b/libs/common-hooks/src/useNetworkName.ts @@ -0,0 +1,13 @@ +import { useMemo } from 'react' + +import { CHAIN_INFO } from '@cowprotocol/common-const' + +import { useWalletInfo } from '@cowprotocol/wallet' + +export function useNetworkName(): string | undefined { + const { chainId } = useWalletInfo() + + return useMemo(() => { + return CHAIN_INFO[chainId].label || '' + }, [chainId]) +} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useOnClickOutside.tsx b/libs/common-hooks/src/useOnClickOutside.tsx similarity index 100% rename from apps/cowswap-frontend/src/legacy/hooks/useOnClickOutside.tsx rename to libs/common-hooks/src/useOnClickOutside.tsx diff --git a/apps/cowswap-frontend/src/legacy/hooks/useParsedQueryString.ts b/libs/common-hooks/src/useParsedQueryString.ts similarity index 90% rename from apps/cowswap-frontend/src/legacy/hooks/useParsedQueryString.ts rename to libs/common-hooks/src/useParsedQueryString.ts index 0780e568d3..38e8113bcb 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useParsedQueryString.ts +++ b/libs/common-hooks/src/useParsedQueryString.ts @@ -12,7 +12,7 @@ export function parsedQueryString(search?: string): ParsedQs { return search && search.length > 1 ? parse(search, { parseArrays: false, ignoreQueryPrefix: true }) : {} } -export default function useParsedQueryString(): ParsedQs { +export function useParsedQueryString(): ParsedQs { const { search } = useLocation() return useMemo(() => parsedQueryString(search), [search]) } diff --git a/apps/cowswap-frontend/src/legacy/hooks/usePrevious.ts b/libs/common-hooks/src/usePrevious.ts similarity index 90% rename from apps/cowswap-frontend/src/legacy/hooks/usePrevious.ts rename to libs/common-hooks/src/usePrevious.ts index 18d5ba3dba..6e83485f1e 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/usePrevious.ts +++ b/libs/common-hooks/src/usePrevious.ts @@ -1,7 +1,7 @@ import { useEffect, useRef } from 'react' // modified from https://usehooks.com/usePrevious/ -export default function usePrevious(value: T) { +export function usePrevious(value: T) { // The ref object is a generic container whose current property is mutable ... // ... and can hold any value, similar to an instance property on a class const ref = useRef() diff --git a/libs/common-hooks/src/useTheme.ts b/libs/common-hooks/src/useTheme.ts new file mode 100644 index 0000000000..0e79aabdc3 --- /dev/null +++ b/libs/common-hooks/src/useTheme.ts @@ -0,0 +1,7 @@ +import { useContext } from 'react' + +import { ThemeContext } from 'styled-components' + +export function useTheme() { + return useContext(ThemeContext) +} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useTimeAgo.ts b/libs/common-hooks/src/useTimeAgo.ts similarity index 84% rename from apps/cowswap-frontend/src/legacy/hooks/useTimeAgo.ts rename to libs/common-hooks/src/useTimeAgo.ts index 5ea6cb654f..166e9eb6b3 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useTimeAgo.ts +++ b/libs/common-hooks/src/useTimeAgo.ts @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react' import * as timeago from 'timeago.js' -export default function useTimeAgo(value?: string | Date, interval = 1000): string { +export function useTimeAgo(value?: string | Date, interval = 1000): string { const [timeAgoValue, setTimeAgoValue] = useState('') useEffect(() => { diff --git a/apps/cowswap-frontend/src/legacy/hooks/useToggle.ts b/libs/common-hooks/src/useToggle.ts similarity index 70% rename from apps/cowswap-frontend/src/legacy/hooks/useToggle.ts rename to libs/common-hooks/src/useToggle.ts index 2da340a46b..852375bac9 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useToggle.ts +++ b/libs/common-hooks/src/useToggle.ts @@ -1,6 +1,6 @@ import { useCallback, useState } from 'react' -export default function useToggle(initialState = false): [boolean, () => void] { +export function useToggle(initialState = false): [boolean, () => void] { const [state, setState] = useState(initialState) const toggle = useCallback(() => setState((state) => !state), []) return [state, toggle] diff --git a/apps/cowswap-frontend/src/legacy/hooks/useWindowSize.ts b/libs/common-hooks/src/useWindowSize.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/hooks/useWindowSize.ts rename to libs/common-hooks/src/useWindowSize.ts diff --git a/libs/common-hooks/tsconfig.json b/libs/common-hooks/tsconfig.json new file mode 100644 index 0000000000..bab74ff2e6 --- /dev/null +++ b/libs/common-hooks/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["vite/client"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/common-hooks/tsconfig.lib.json b/libs/common-hooks/tsconfig.lib.json new file mode 100644 index 0000000000..1b2b0c12df --- /dev/null +++ b/libs/common-hooks/tsconfig.lib.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node", "vite/client"] + }, + "files": ["../../node_modules/@nx/react/typings/cssmodule.d.ts", "../../node_modules/@nx/react/typings/image.d.ts"], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/common-hooks/tsconfig.spec.json b/libs/common-hooks/tsconfig.spec.json new file mode 100644 index 0000000000..26ef046ac5 --- /dev/null +++ b/libs/common-hooks/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/libs/common-hooks/vite.config.ts b/libs/common-hooks/vite.config.ts new file mode 100644 index 0000000000..de5a06d695 --- /dev/null +++ b/libs/common-hooks/vite.config.ts @@ -0,0 +1,49 @@ +/// +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' +import viteTsConfigPaths from 'vite-tsconfig-paths' +import dts from 'vite-plugin-dts' +import * as path from 'path' + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/common-hooks', + + plugins: [ + dts({ + entryRoot: 'src', + tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'), + skipDiagnostics: true, + }), + react(), + viteTsConfigPaths({ + root: '../../', + }), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + lib: { + // Could also be a dictionary or array of multiple entry points. + entry: 'src/index.ts', + name: 'common-hooks', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es', 'cjs'], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: ['react', 'react-dom', 'react/jsx-runtime'], + }, + }, +}) diff --git a/libs/common-utils/.babelrc b/libs/common-utils/.babelrc new file mode 100644 index 0000000000..ef4889c1ab --- /dev/null +++ b/libs/common-utils/.babelrc @@ -0,0 +1,20 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [ + [ + "styled-components", + { + "pure": true, + "ssr": true + } + ] + ] +} diff --git a/libs/common-utils/.env b/libs/common-utils/.env new file mode 100644 index 0000000000..8293a86c66 --- /dev/null +++ b/libs/common-utils/.env @@ -0,0 +1,96 @@ +# PRICE ESTIMATION +REACT_APP_PRICE_FEED_GP_ENABLED=true +REACT_APP_PRICE_FEED_PARASWAP_ENABLED=true +REACT_APP_PRICE_FEED_1INCH_ENABLED=true +REACT_APP_PRICE_FEED_0X_ENABLED=true + +# Order book API urls +#REACT_APP_ORDER_BOOK_URLS='{"1":"https://YOUR_HOST","100":"https://YOUR_HOST","5":"https://YOUR_HOST"}' + +# AppData, build yours at https://explorer.cow.fi/appdata +REACT_APP_FULL_APP_DATA_PRODUCTION='{"version":"0.7.0","appCode":"CoW Swap","environment":"production","metadata":{}}' +REACT_APP_FULL_APP_DATA_ENS='{"version":"0.7.0","appCode":"CoW Swap","environment":"ens","metadata":{}}' +REACT_APP_FULL_APP_DATA_BARN='{"version":"0.7.0","appCode":"CoW Swap","environment":"barn","metadata":{}}' +REACT_APP_FULL_APP_DATA_STAGING='{"version":"0.7.0","appCode":"CoW Swap","environment":"staging","metadata":{}}' +REACT_APP_FULL_APP_DATA_PR='{"version":"0.7.0","appCode":"CoW Swap","environment":"pr","metadata":{}}' +REACT_APP_FULL_APP_DATA_DEVELOPMENT='{"version":"0.7.0","appCode":"CoW Swap","environment":"development","metadata":{}}' +REACT_APP_FULL_APP_DATA_LOCAL='{"version":"0.7.0","appCode":"CoW Swap","environment":"local","metadata":{}}' + +# INFURA KEY +REACT_APP_INFURA_KEY=586e7e6b7c7e437aa41f5da496a749f5 + +# Cypress Integration Tests +INTEGRATION_TEST_PRIVATE_KEY= +INTEGRATION_TESTS_INFURA_KEY= + + +# BLOCKNATIVE KEY +# if you need that locally, get the key from blocknative. Access details in shared team vault +#REACT_APP_BLOCKNATIVE_API_KEY= + +# Node +REACT_APP_CHAIN_ID="1" +REACT_APP_SUPPORTED_CHAIN_IDS="1,100,5" +REACT_APP_NETWORK_URL_1=https://mainnet.infura.io/v3/586e7e6b7c7e437aa41f5da496a749f5 +REACT_APP_NETWORK_URL_5=https://goerli.infura.io/v3/586e7e6b7c7e437aa41f5da496a749f5 +REACT_APP_NETWORK_URL_100=https://rpc.gnosischain.com + +# Wallet Connect +# REACT_APP_WALLET_CONNECT_V1_BRIDGE='https://safe-walletconnect.safe.global' + +# Wallets +REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236" +REACT_APP_FORTMATIC_KEY="pk_live_6AED76CA755EFDC7" +REACT_APP_FORTMATIC_SITE_VERIFICATION="LzjrtdM7hqVJfvvA" + +# Domain regex (to detect environment) +REACT_APP_DOMAIN_REGEX_LOCAL="^(:?localhost:\d{2,5}|(?:127|192)(?:\.[0-9]{1,3}){3})" +REACT_APP_DOMAIN_REGEX_PR="^pr\d+--cowswap\.review|^(swap-dev-git-[\w\d-]+|swap-\w{9}-)cowswap\.vercel\.app" +REACT_APP_DOMAIN_REGEX_DEV="^(cowswap\.dev|dev\.swap\.cow\.fi|swap-develop\.vercel\.app)" +REACT_APP_DOMAIN_REGEX_STAGING="^(cowswap\.staging|staging\.swap\.cow\.fi|swap-staging\.vercel\.app)" +REACT_APP_DOMAIN_REGEX_PROD="^(swap\.cow\.fi|swap-prod\.vercel\.app)$" +REACT_APP_DOMAIN_REGEX_BARN="^(barn\.cow\.fi|swap-barn\.vercel\.app)$" +REACT_APP_DOMAIN_REGEX_ENS="(:?^cowswap\.eth|ipfs)" + +# Path regex (to detect environment) +REACT_APP_PATH_REGEX_ENS="/ipfs" + +# Analytics +#REACT_APP_GOOGLE_ANALYTICS_ID= + +# Sentry +#REACT_APP_SENTRY_DSN='https://' +#REACT_APP_SENTRY_TRACES_SAMPLE_RATE="1.0" +#REACT_APP_SENTRY_AUTH_TOKEN='' + +# API +#REACT_APP_API_URL_PROD_MAINNET= +#REACT_APP_API_URL_PROD_XDAI= +#REACT_APP_API_URL_PROD_GOERLI= +#REACT_APP_API_URL_STAGING_MAINNET= +#REACT_APP_API_URL_STAGING_XDAI= +#REACT_APP_API_URL_STAGING_GOERLI= + +# EXPLORER +#REACT_APP_EXPLORER_URL_DEV= +#REACT_APP_EXPLORER_URL_STAGING= +#REACT_APP_EXPLORER_URL_PROD= +#REACT_APP_EXPLORER_URL_BARN= + +# Enables mock mode (default = true) +REACT_APP_MOCK=true + +# IPFS uploading +REACT_APP_PINATA_API_KEY= +REACT_APP_PINATA_SECRET_API_KEY= + +# Appzi NPS feedback +REACT_APP_FEEDBACK_ENABLED_DEV=false +#REACT_APP_APPZI_FEEDBACK_KEY= +#REACT_APP_APPZI_NPS_KEY= + +# Amplitude +# REACT_APP_AMPLITUDE_KEY= + +# Launch darkly +REACT_APP_LAUNCH_DARKLY_KEY=643681f370ea6d135128b2ce diff --git a/libs/common-utils/.eslintrc.json b/libs/common-utils/.eslintrc.json new file mode 100644 index 0000000000..231aaa5f83 --- /dev/null +++ b/libs/common-utils/.eslintrc.json @@ -0,0 +1,21 @@ +{ + "extends": ["plugin:@nx/react", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "rules": { + "@typescript-eslint/no-explicit-any": "off" + }, + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/common-utils/README.md b/libs/common-utils/README.md new file mode 100644 index 0000000000..1ecf2638af --- /dev/null +++ b/libs/common-utils/README.md @@ -0,0 +1,42 @@ +# Snackbars + +![](./demo.png) + +## Usage + +```tsx +// Add the widget in the root component + +import { SnackbarsWidget } from '@cowprotocol/common-utils' + +export function App() { + return ( + + + + + ) +} +``` + +```tsx +// Use the hook to add a snackbar + +import { useAddSnackbar } from '@cowprotocol/common-utils' + +export function MyComponent() { + const addSnackbar = useAddSnackbar() + + addSnackbar({ + content: {walletName} account changed, + id: 'account-changed', + icon: 'success' + }) +} +``` + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test common-utils` to execute the unit tests via [Vitest](https://vitest.dev/). diff --git a/libs/common-utils/jest.config.ts b/libs/common-utils/jest.config.ts new file mode 100644 index 0000000000..c1973b852d --- /dev/null +++ b/libs/common-utils/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'common-utils', + preset: '../../jest.preset.js', + transform: { + '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', + '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/libs/common-utils', +} diff --git a/libs/common-utils/package.json b/libs/common-utils/package.json new file mode 100644 index 0000000000..6ff7b85475 --- /dev/null +++ b/libs/common-utils/package.json @@ -0,0 +1,12 @@ +{ + "name": "@cowprotocol/common-utils", + "version": "0.0.1", + "main": "./index.js", + "types": "./index.d.ts", + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.js" + } + } +} diff --git a/libs/common-utils/project.json b/libs/common-utils/project.json new file mode 100644 index 0000000000..8fd06b9f7b --- /dev/null +++ b/libs/common-utils/project.json @@ -0,0 +1,46 @@ +{ + "name": "@cowprotocol/common-utils", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/common-utils/src", + "projectType": "library", + "tags": [], + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/common-utils/**/*.{ts,tsx,js,jsx}"] + } + }, + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/libs/common-utils" + }, + "configurations": { + "development": { + "mode": "development" + }, + "production": { + "mode": "production" + } + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/common-utils/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + } +} diff --git a/apps/cowswap-frontend/src/utils/amountFormat/README.md b/libs/common-utils/src/amountFormat/README.md similarity index 100% rename from apps/cowswap-frontend/src/utils/amountFormat/README.md rename to libs/common-utils/src/amountFormat/README.md diff --git a/apps/cowswap-frontend/src/utils/amountFormat/index.test.ts b/libs/common-utils/src/amountFormat/index.test.ts similarity index 97% rename from apps/cowswap-frontend/src/utils/amountFormat/index.test.ts rename to libs/common-utils/src/amountFormat/index.test.ts index 6f5343a866..f864a38c27 100644 --- a/apps/cowswap-frontend/src/utils/amountFormat/index.test.ts +++ b/libs/common-utils/src/amountFormat/index.test.ts @@ -1,7 +1,6 @@ import { CurrencyAmount, Percent } from '@uniswap/sdk-core' -import { USDC_GNOSIS_CHAIN } from 'legacy/utils/gnosis_chain/constants' -import { DAI_GOERLI, USDC_GOERLI } from 'legacy/utils/goerli/constants' +import { USDC_GNOSIS_CHAIN, DAI_GOERLI, USDC_GOERLI } from '@cowprotocol/common-const' import { formatAmountWithPrecision, formatFiatAmount, formatPercent, formatTokenAmount } from './index' diff --git a/apps/cowswap-frontend/src/utils/amountFormat/index.ts b/libs/common-utils/src/amountFormat/index.ts similarity index 89% rename from apps/cowswap-frontend/src/utils/amountFormat/index.ts rename to libs/common-utils/src/amountFormat/index.ts index 457f0d8759..093b89ac36 100644 --- a/apps/cowswap-frontend/src/utils/amountFormat/index.ts +++ b/libs/common-utils/src/amountFormat/index.ts @@ -1,16 +1,20 @@ import { Currency, CurrencyAmount, Percent, Rounding } from '@uniswap/sdk-core' import JSBI from 'jsbi' -import { FractionLike, Nullish } from 'types' +import { FractionLike, Nullish } from '../types' -import { AMOUNT_PRECISION, FIAT_PRECISION, PERCENTAGE_PRECISION, ZERO_FRACTION } from 'legacy/constants' -import { maxAmountSpend } from 'legacy/utils/maxAmountSpend' - -import { INTL_NUMBER_FORMAT } from 'common/constants/intl' -import { FractionUtils } from 'utils/fractionUtils' -import { trimTrailingZeros } from 'utils/trimTrailingZeros' +import { + AMOUNT_PRECISION, + FIAT_PRECISION, + PERCENTAGE_PRECISION, + ZERO_FRACTION, + INTL_NUMBER_FORMAT, +} from '@cowprotocol/common-const' import { getPrecisionForAmount, getSuffixForAmount, lessThanPrecisionSymbol, trimHugeAmounts } from './utils' +import { trimTrailingZeros } from '../trimTrailingZeros' +import { FractionUtils } from '../fractionUtils' +import { maxAmountSpend } from '../maxAmountSpend' export function formatFiatAmount(amount: Nullish): string { return formatAmountWithPrecision(amount, FIAT_PRECISION) diff --git a/apps/cowswap-frontend/src/utils/amountFormat/utils.ts b/libs/common-utils/src/amountFormat/utils.ts similarity index 94% rename from apps/cowswap-frontend/src/utils/amountFormat/utils.ts rename to libs/common-utils/src/amountFormat/utils.ts index 0b9ac4554e..e5258df037 100644 --- a/apps/cowswap-frontend/src/utils/amountFormat/utils.ts +++ b/libs/common-utils/src/amountFormat/utils.ts @@ -1,9 +1,9 @@ import { CurrencyAmount, Fraction } from '@uniswap/sdk-core' import JSBI from 'jsbi' -import { FractionLike, Nullish } from 'types' +import { FractionLike, Nullish } from '../types' -import { FractionUtils } from 'utils/fractionUtils' +import { FractionUtils } from '../fractionUtils' const ONE = JSBI.BigInt(1) const HUNDRED_K = JSBI.BigInt(100_000) diff --git a/apps/cowswap-frontend/src/legacy/utils/anonymizeLink.test.ts b/libs/common-utils/src/anonymizeLink.test.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/anonymizeLink.test.ts rename to libs/common-utils/src/anonymizeLink.test.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/anonymizeLink.ts b/libs/common-utils/src/anonymizeLink.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/anonymizeLink.ts rename to libs/common-utils/src/anonymizeLink.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/appzi.ts b/libs/common-utils/src/appzi.ts similarity index 96% rename from apps/cowswap-frontend/src/legacy/utils/appzi.ts rename to libs/common-utils/src/appzi.ts index 1fde05ac09..83795f8590 100644 --- a/apps/cowswap-frontend/src/legacy/utils/appzi.ts +++ b/libs/common-utils/src/appzi.ts @@ -1,10 +1,9 @@ import ms from 'ms.macro' import ReactAppzi from 'react-appzi' -import { environmentName, isProdLike } from 'legacy/utils/environments' -import { userAgent, majorBrowserVersion, isImTokenBrowser } from 'legacy/utils/userAgent' - import EventEmitter from 'events' +import { isImTokenBrowser, majorBrowserVersion, userAgent } from './userAgent' +import { environmentName, isProdLike } from './environments' // Metamask IOS app uses a version from July 2019 which causes problems in appZi const OLD_CHROME_FROM_METAMASK_IOS_APP = 76 diff --git a/apps/cowswap-frontend/src/utils/areFractionsEqual.ts b/libs/common-utils/src/areFractionsEqual.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/areFractionsEqual.ts rename to libs/common-utils/src/areFractionsEqual.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/async.ts b/libs/common-utils/src/async.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/async.ts rename to libs/common-utils/src/async.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/blocks.ts b/libs/common-utils/src/blocks.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/blocks.ts rename to libs/common-utils/src/blocks.ts diff --git a/apps/cowswap-frontend/src/modules/utils/orderUtils/buildPriceFromCurrencyAmounts.ts b/libs/common-utils/src/buildPriceFromCurrencyAmounts.ts similarity index 91% rename from apps/cowswap-frontend/src/modules/utils/orderUtils/buildPriceFromCurrencyAmounts.ts rename to libs/common-utils/src/buildPriceFromCurrencyAmounts.ts index 6b3e3e9e72..c25068e3cb 100644 --- a/apps/cowswap-frontend/src/modules/utils/orderUtils/buildPriceFromCurrencyAmounts.ts +++ b/libs/common-utils/src/buildPriceFromCurrencyAmounts.ts @@ -1,8 +1,7 @@ import { Currency, CurrencyAmount, Price } from '@uniswap/sdk-core' -import { Nullish } from 'types' - -import { isFractionFalsy } from 'utils/isFractionFalsy' +import { Nullish } from './types' +import { isFractionFalsy } from './isFractionFalsy' export function buildPriceFromCurrencyAmounts( inputCurrencyAmount: CurrencyAmount, diff --git a/apps/cowswap-frontend/src/legacy/utils/calculateGasMargin.test.ts b/libs/common-utils/src/calculateGasMargin.test.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/calculateGasMargin.test.ts rename to libs/common-utils/src/calculateGasMargin.test.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/calculateGasMargin.ts b/libs/common-utils/src/calculateGasMargin.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/calculateGasMargin.ts rename to libs/common-utils/src/calculateGasMargin.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/calculatePriceImpact.test.ts b/libs/common-utils/src/calculatePriceImpact.test.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/calculatePriceImpact.test.ts rename to libs/common-utils/src/calculatePriceImpact.test.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/calculateSlippageAmount.test.ts b/libs/common-utils/src/calculateSlippageAmount.test.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/calculateSlippageAmount.test.ts rename to libs/common-utils/src/calculateSlippageAmount.test.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/calculateSlippageAmount.ts b/libs/common-utils/src/calculateSlippageAmount.ts similarity index 74% rename from apps/cowswap-frontend/src/legacy/utils/calculateSlippageAmount.ts rename to libs/common-utils/src/calculateSlippageAmount.ts index 87588fc006..4ea0d01be8 100644 --- a/apps/cowswap-frontend/src/legacy/utils/calculateSlippageAmount.ts +++ b/libs/common-utils/src/calculateSlippageAmount.ts @@ -1,8 +1,8 @@ -import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' +import { Currency, CurrencyAmount, Fraction, Percent } from '@uniswap/sdk-core' import JSBI from 'jsbi' -import { ONE_FRACTION } from 'legacy/constants/misc' +const ONE_FRACTION = new Fraction(1, 1) export function calculateSlippageAmount(value: CurrencyAmount, slippage: Percent): [JSBI, JSBI] { if (slippage.lessThan(0) || slippage.greaterThan(ONE_FRACTION)) throw new Error('Unexpected slippage') diff --git a/apps/cowswap-frontend/src/lib/utils/contenthashToUri.ts b/libs/common-utils/src/contenthashToUri.ts similarity index 94% rename from apps/cowswap-frontend/src/lib/utils/contenthashToUri.ts rename to libs/common-utils/src/contenthashToUri.ts index 2c667f108f..23eb13e19a 100644 --- a/apps/cowswap-frontend/src/lib/utils/contenthashToUri.ts +++ b/libs/common-utils/src/contenthashToUri.ts @@ -18,7 +18,7 @@ const UTF_8_DECODER = new TextDecoder('utf-8') * Returns the URI representation of the content hash for supported codecs * @param contenthash to decode */ -export default function contenthashToUri(contenthash: string): string { +export function contenthashToUri(contenthash: string): string { const data = hexToUint8Array(contenthash) const codec = getNameFromData(data) switch (codec) { diff --git a/apps/cowswap-frontend/src/utils/currencyAmountToTokenAmount.ts b/libs/common-utils/src/currencyAmountToTokenAmount.ts similarity index 64% rename from apps/cowswap-frontend/src/utils/currencyAmountToTokenAmount.ts rename to libs/common-utils/src/currencyAmountToTokenAmount.ts index 7193c4943b..d52376d533 100644 --- a/apps/cowswap-frontend/src/utils/currencyAmountToTokenAmount.ts +++ b/libs/common-utils/src/currencyAmountToTokenAmount.ts @@ -1,8 +1,8 @@ import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' -import { Nullish } from 'types' - -export function currencyAmountToTokenAmount(amount: Nullish>): CurrencyAmount | null { +export function currencyAmountToTokenAmount( + amount: CurrencyAmount | null | undefined +): CurrencyAmount | null { if (!amount) return null if (amount.currency.isToken) return amount as CurrencyAmount diff --git a/apps/cowswap-frontend/src/legacy/utils/currencyId.ts b/libs/common-utils/src/currencyId.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/currencyId.ts rename to libs/common-utils/src/currencyId.ts diff --git a/apps/cowswap-frontend/src/utils/deepEqual.ts b/libs/common-utils/src/deepEqual.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/deepEqual.ts rename to libs/common-utils/src/deepEqual.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/deterministicHash.test.ts b/libs/common-utils/src/deterministicHash.test.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/deterministicHash.test.ts rename to libs/common-utils/src/deterministicHash.test.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/deterministicHash.ts b/libs/common-utils/src/deterministicHash.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/deterministicHash.ts rename to libs/common-utils/src/deterministicHash.ts diff --git a/apps/cowswap-frontend/src/utils/displayTime.tsx b/libs/common-utils/src/displayTime.tsx similarity index 100% rename from apps/cowswap-frontend/src/utils/displayTime.tsx rename to libs/common-utils/src/displayTime.tsx diff --git a/apps/cowswap-frontend/src/utils/doesTokenMatchSymbolOrAddress.ts b/libs/common-utils/src/doesTokenMatchSymbolOrAddress.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/doesTokenMatchSymbolOrAddress.ts rename to libs/common-utils/src/doesTokenMatchSymbolOrAddress.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/env.ts b/libs/common-utils/src/env.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/env.ts rename to libs/common-utils/src/env.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/environments.test.ts b/libs/common-utils/src/environments.test.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/environments.test.ts rename to libs/common-utils/src/environments.test.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/environments.ts b/libs/common-utils/src/environments.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/environments.ts rename to libs/common-utils/src/environments.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/explorer.ts b/libs/common-utils/src/explorer.ts similarity index 93% rename from apps/cowswap-frontend/src/legacy/utils/explorer.ts rename to libs/common-utils/src/explorer.ts index cf68f39964..f93fd71b6b 100644 --- a/apps/cowswap-frontend/src/legacy/utils/explorer.ts +++ b/libs/common-utils/src/explorer.ts @@ -1,6 +1,4 @@ -import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' - -import { OrderID } from 'api/gnosisProtocol' +import { SupportedChainId as ChainId, UID } from '@cowprotocol/cow-sdk' import { isLocal, isDev, isPr, isStaging, isBarn } from './environments' @@ -36,7 +34,7 @@ export function getExplorerBaseUrl(chainId: ChainId): string { } } -export function getExplorerOrderLink(chainId: ChainId, orderId: OrderID): string { +export function getExplorerOrderLink(chainId: ChainId, orderId: UID): string { const baseUrl = getExplorerBaseUrl(chainId) return baseUrl + `/orders/${orderId}` diff --git a/apps/cowswap-frontend/src/utils/featureFlags.ts b/libs/common-utils/src/featureFlags.ts similarity index 88% rename from apps/cowswap-frontend/src/utils/featureFlags.ts rename to libs/common-utils/src/featureFlags.ts index 11d570c7a9..5eab21a3a1 100644 --- a/apps/cowswap-frontend/src/utils/featureFlags.ts +++ b/libs/common-utils/src/featureFlags.ts @@ -1,7 +1,8 @@ -import { isProdLike } from 'legacy/utils/environments' +import { isProdLike } from './environments' // We can define here some flags to be enabled while we develop // TODO: update this before the deployment + const ENABLED_FOR_DEVELOP: string[] = [] export class FeatureFlag { diff --git a/apps/cowswap-frontend/src/utils/format.ts b/libs/common-utils/src/format.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/format.ts rename to libs/common-utils/src/format.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/formatCurrencyAmount.ts b/libs/common-utils/src/formatCurrencyAmount.ts similarity index 88% rename from apps/cowswap-frontend/src/legacy/utils/formatCurrencyAmount.ts rename to libs/common-utils/src/formatCurrencyAmount.ts index ededc1e331..14411e5b7a 100644 --- a/apps/cowswap-frontend/src/legacy/utils/formatCurrencyAmount.ts +++ b/libs/common-utils/src/formatCurrencyAmount.ts @@ -2,9 +2,9 @@ import { Currency, CurrencyAmount, Fraction, Price } from '@uniswap/sdk-core' import JSBI from 'jsbi' -import { DEFAULT_LOCALE, SupportedLocale } from 'legacy/constants/locales' +import { DEFAULT_LOCALE, SupportedLocale } from '@cowprotocol/common-const' -import formatLocaleNumber from 'lib/utils/formatLocaleNumber' +import formatLocaleNumber from './formatLocaleNumber' export function formatCurrencyAmount( amount: CurrencyAmount | undefined, diff --git a/apps/cowswap-frontend/src/lib/utils/formatLocaleNumber.test.ts b/libs/common-utils/src/formatLocaleNumber.test.ts similarity index 87% rename from apps/cowswap-frontend/src/lib/utils/formatLocaleNumber.test.ts rename to libs/common-utils/src/formatLocaleNumber.test.ts index 7640446f3f..2c7ef66907 100644 --- a/apps/cowswap-frontend/src/lib/utils/formatLocaleNumber.test.ts +++ b/libs/common-utils/src/formatLocaleNumber.test.ts @@ -1,4 +1,4 @@ -import { SUPPORTED_LOCALES, SupportedLocale } from 'legacy/constants/locales' +import { SUPPORTED_LOCALES, SupportedLocale } from '@cowprotocol/common-const' import formatLocaleNumber from './formatLocaleNumber' @@ -15,6 +15,7 @@ function expectedOutput(l: SupportedLocale): string { case 'zh-TW': return `4,000,000.123` case 'fr-FR': + // eslint-disable-next-line no-irregular-whitespace return `4 000 000,123` case 'ar-SA': return `٤٬٠٠٠٬٠٠٠٫١٢٣` @@ -28,6 +29,7 @@ function expectedOutput(l: SupportedLocale): string { case 'ru-RU': case 'sv-SE': case 'uk-UA': + // eslint-disable-next-line no-irregular-whitespace return `4 000 000,123` case 'ca-ES': case 'da-DK': diff --git a/apps/cowswap-frontend/src/lib/utils/formatLocaleNumber.ts b/libs/common-utils/src/formatLocaleNumber.ts similarity index 94% rename from apps/cowswap-frontend/src/lib/utils/formatLocaleNumber.ts rename to libs/common-utils/src/formatLocaleNumber.ts index b8f8b5cbac..9cc88b8f18 100644 --- a/apps/cowswap-frontend/src/lib/utils/formatLocaleNumber.ts +++ b/libs/common-utils/src/formatLocaleNumber.ts @@ -1,6 +1,6 @@ import { Currency, CurrencyAmount, Price } from '@uniswap/sdk-core' -import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from 'legacy/constants/locales' +import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from '@cowprotocol/common-const' interface FormatLocaleNumberArgs { number: CurrencyAmount | Price | number diff --git a/apps/cowswap-frontend/src/utils/fractionUtils.test.ts b/libs/common-utils/src/fractionUtils.test.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/fractionUtils.test.ts rename to libs/common-utils/src/fractionUtils.test.ts diff --git a/apps/cowswap-frontend/src/utils/fractionUtils.ts b/libs/common-utils/src/fractionUtils.ts similarity index 80% rename from apps/cowswap-frontend/src/utils/fractionUtils.ts rename to libs/common-utils/src/fractionUtils.ts index b4f3ee6d0c..f98270b611 100644 --- a/apps/cowswap-frontend/src/utils/fractionUtils.ts +++ b/libs/common-utils/src/fractionUtils.ts @@ -2,12 +2,10 @@ import { BigintIsh, Currency, CurrencyAmount, Fraction, Price, Rounding, Token } import { BigNumber } from 'bignumber.js' import JSBI from 'jsbi' -import { FractionLike, Nullish } from 'types' +import { FractionLike, Nullish } from './types' -import { FULL_PRICE_PRECISION } from 'legacy/constants' - -import { adjustDecimalsAtoms } from 'utils/orderUtils/calculateAmountForRate' -import { trimTrailingZeros } from 'utils/trimTrailingZeros' +import { FULL_PRICE_PRECISION } from '@cowprotocol/common-const' +import { trimTrailingZeros } from './trimTrailingZeros' export class FractionUtils { static serializeFractionToJSON(fraction: Nullish): string { @@ -82,7 +80,11 @@ export class FractionUtils { */ static toPrice(fraction: Fraction, inputCurrency: Token, outputCurrency: Token): Price { // Note that here the fraction shows the price in units (for both tokens). The Price class is decimals aware, so we need to adapt it - const adjustedFraction = adjustDecimalsAtoms(fraction, inputCurrency.decimals, outputCurrency.decimals) + const adjustedFraction = FractionUtils.adjustDecimalsAtoms( + fraction, + inputCurrency.decimals, + outputCurrency.decimals + ) return new Price({ quoteAmount: CurrencyAmount.fromRawAmount(outputCurrency, adjustedFraction.numerator), @@ -100,13 +102,28 @@ export class FractionUtils { * @returns */ static fromPrice(price: Price): Fraction { - return adjustDecimalsAtoms( + return FractionUtils.adjustDecimalsAtoms( new Fraction(price.numerator, price.denominator), price.quoteCurrency.decimals, price.baseCurrency.decimals ) } + /** + * Adjust a fraction defined in units for both token to consider the decimals. + * For example, a fraction like 1.1/1 representing the price of USDC, DAI in units, will be turned into + * 1.1/1000000000000 in atoms + */ + static adjustDecimalsAtoms(value: Fraction, decimalsA: number, decimalsB: number): Fraction { + if (decimalsA === decimalsB) { + return value + } + + const decimalsShift = JSBI.BigInt(JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(Math.abs(decimalsA - decimalsB)))) + + return decimalsA < decimalsB ? value.multiply(decimalsShift) : value.divide(decimalsShift) + } + /** * Converts a number into a Fraction * diff --git a/apps/cowswap-frontend/src/utils/genericPropsChecker.test.ts b/libs/common-utils/src/genericPropsChecker.test.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/genericPropsChecker.test.ts rename to libs/common-utils/src/genericPropsChecker.test.ts diff --git a/apps/cowswap-frontend/src/utils/genericPropsChecker.ts b/libs/common-utils/src/genericPropsChecker.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/genericPropsChecker.ts rename to libs/common-utils/src/genericPropsChecker.ts diff --git a/apps/cowswap-frontend/src/utils/getAddress.ts b/libs/common-utils/src/getAddress.ts similarity index 54% rename from apps/cowswap-frontend/src/utils/getAddress.ts rename to libs/common-utils/src/getAddress.ts index a29ff61f43..753efa6c2f 100644 --- a/apps/cowswap-frontend/src/utils/getAddress.ts +++ b/libs/common-utils/src/getAddress.ts @@ -1,11 +1,9 @@ import { Currency } from '@uniswap/sdk-core' -import { WrappedTokenInfo } from 'legacy/state/lists/wrappedTokenInfo' - export function getAddress(currency: Currency | null | undefined): string | null { if (!currency || currency.isNative) { return null } - return currency?.address || (currency as WrappedTokenInfo)?.tokenInfo?.address || null + return currency?.address || (currency as { tokenInfo?: { address?: string } })?.tokenInfo?.address || null } diff --git a/apps/cowswap-frontend/src/utils/getCurrentChainIdFromUrl.test.ts b/libs/common-utils/src/getCurrentChainIdFromUrl.test.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/getCurrentChainIdFromUrl.test.ts rename to libs/common-utils/src/getCurrentChainIdFromUrl.test.ts diff --git a/apps/cowswap-frontend/src/utils/getCurrentChainIdFromUrl.ts b/libs/common-utils/src/getCurrentChainIdFromUrl.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/getCurrentChainIdFromUrl.ts rename to libs/common-utils/src/getCurrentChainIdFromUrl.ts diff --git a/apps/cowswap-frontend/src/utils/getDoesMessageIncludeToken.ts b/libs/common-utils/src/getDoesMessageIncludeToken.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/getDoesMessageIncludeToken.ts rename to libs/common-utils/src/getDoesMessageIncludeToken.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/getExplorerLink.test.ts b/libs/common-utils/src/getExplorerLink.test.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/getExplorerLink.test.ts rename to libs/common-utils/src/getExplorerLink.test.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/getExplorerLink.ts b/libs/common-utils/src/getExplorerLink.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/getExplorerLink.ts rename to libs/common-utils/src/getExplorerLink.ts diff --git a/apps/cowswap-frontend/src/utils/getIntOrFloat.ts b/libs/common-utils/src/getIntOrFloat.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/getIntOrFloat.ts rename to libs/common-utils/src/getIntOrFloat.ts diff --git a/apps/cowswap-frontend/src/utils/getIsNativeToken.ts b/libs/common-utils/src/getIsNativeToken.ts similarity index 83% rename from apps/cowswap-frontend/src/utils/getIsNativeToken.ts rename to libs/common-utils/src/getIsNativeToken.ts index 75f380a12e..e6da863fcd 100644 --- a/apps/cowswap-frontend/src/utils/getIsNativeToken.ts +++ b/libs/common-utils/src/getIsNativeToken.ts @@ -1,6 +1,6 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' +import { NATIVE_CURRENCY_BUY_TOKEN } from '@cowprotocol/common-const' import { doesTokenMatchSymbolOrAddress } from './doesTokenMatchSymbolOrAddress' diff --git a/apps/cowswap-frontend/src/utils/getIsWrapOrUnwrap.ts b/libs/common-utils/src/getIsWrapOrUnwrap.ts similarity index 84% rename from apps/cowswap-frontend/src/utils/getIsWrapOrUnwrap.ts rename to libs/common-utils/src/getIsWrapOrUnwrap.ts index 11305d728f..5e61384504 100644 --- a/apps/cowswap-frontend/src/utils/getIsWrapOrUnwrap.ts +++ b/libs/common-utils/src/getIsWrapOrUnwrap.ts @@ -1,11 +1,10 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { NATIVE_CURRENCY_BUY_TOKEN } from 'legacy/constants' -import { WRAPPED_NATIVE_CURRENCY } from 'legacy/constants/tokens' +import { NATIVE_CURRENCY_BUY_TOKEN, WRAPPED_NATIVE_CURRENCY } from '@cowprotocol/common-const' import { doesTokenMatchSymbolOrAddress } from './doesTokenMatchSymbolOrAddress' -import { Nullish } from '../types' +import { Nullish } from './types' export function getIsWrapOrUnwrap( chainId: SupportedChainId, diff --git a/apps/cowswap-frontend/src/utils/getQuoteUnsupportedToken.ts b/libs/common-utils/src/getQuoteUnsupportedToken.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/getQuoteUnsupportedToken.ts rename to libs/common-utils/src/getQuoteUnsupportedToken.ts diff --git a/apps/cowswap-frontend/src/utils/getRandomInt.ts b/libs/common-utils/src/getRandomInt.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/getRandomInt.ts rename to libs/common-utils/src/getRandomInt.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/getUserAgent.ts b/libs/common-utils/src/getUserAgent.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/getUserAgent.ts rename to libs/common-utils/src/getUserAgent.ts diff --git a/libs/common-utils/src/index.ts b/libs/common-utils/src/index.ts new file mode 100644 index 0000000000..70de2e928a --- /dev/null +++ b/libs/common-utils/src/index.ts @@ -0,0 +1,54 @@ +export * from './env' +export * from './environments' +export * from './legacyAddressUtils' +export * from './format' +export * from './tokens' +export * from './misc' +export * from './time' +export * from './isZero' +export * from './retry' +export * from './request' +export * from './async' +export * from './uriToHttp' +export * from './contenthashToUri' +export * from './parseENSAddress' +export * from './safeNamehash' +export * from './calculateGasMargin' +export * from './doesTokenMatchSymbolOrAddress' +export * from './amountFormat/index' +export * from './explorer' +export * from './getQuoteUnsupportedToken' +export * from './buildPriceFromCurrencyAmounts' +export * from './tryParseCurrencyAmount' +export * from './resolveENSContentHash' +export * from './fractionUtils' +export * from './getCurrentChainIdFromUrl' +export * from './node' +export * from './isInjectedWidget' +export * from './toggleBodyClass' +export * from './featureFlags' +export * from './currencyId' +export * from './isFractionFalsy' +export * from './getAddress' +export * from './tooltips' +export * from './genericPropsChecker' +export * from './listSort' +export * from './sound' +export * from './userAgent' +export * from './getExplorerLink' +export * from './getIsNativeToken' +export * from './getIsWrapOrUnwrap' +export * from './logging' +export * from './getIntOrFloat' +export * from './appzi' +export * from './anonymizeLink' +export * from './deepEqual' +export * from './rawToTokenAmount' +export * from './areFractionsEqual' +export * from './currencyAmountToTokenAmount' +export * from './localStorage' +export * from './getRandomInt' +export * from './isEnoughAmount' +export * from './tryParseFractionalAmount' +export * from './maxAmountSpend' +export * from './jotai/atomWithPartialUpdate' diff --git a/apps/cowswap-frontend/src/utils/isEnoughAmount.ts b/libs/common-utils/src/isEnoughAmount.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/isEnoughAmount.ts rename to libs/common-utils/src/isEnoughAmount.ts diff --git a/apps/cowswap-frontend/src/utils/isFractionFalsy.ts b/libs/common-utils/src/isFractionFalsy.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/isFractionFalsy.ts rename to libs/common-utils/src/isFractionFalsy.ts diff --git a/apps/cowswap-frontend/src/common/utils/isInjectedWidget.ts b/libs/common-utils/src/isInjectedWidget.ts similarity index 100% rename from apps/cowswap-frontend/src/common/utils/isInjectedWidget.ts rename to libs/common-utils/src/isInjectedWidget.ts diff --git a/apps/cowswap-frontend/src/utils/isNotNullish.ts b/libs/common-utils/src/isNotNullish.ts similarity index 77% rename from apps/cowswap-frontend/src/utils/isNotNullish.ts rename to libs/common-utils/src/isNotNullish.ts index 4bbccdbd58..c016871db6 100644 --- a/apps/cowswap-frontend/src/utils/isNotNullish.ts +++ b/libs/common-utils/src/isNotNullish.ts @@ -1,4 +1,4 @@ -import { Nullish } from 'types' +import { Nullish } from './types' export function isNotNullish(input: Nullish): input is T { return input !== null && input !== undefined diff --git a/apps/cowswap-frontend/src/legacy/utils/isZero.ts b/libs/common-utils/src/isZero.ts similarity index 68% rename from apps/cowswap-frontend/src/legacy/utils/isZero.ts rename to libs/common-utils/src/isZero.ts index 1b84e67560..ca6d44a162 100644 --- a/apps/cowswap-frontend/src/legacy/utils/isZero.ts +++ b/libs/common-utils/src/isZero.ts @@ -2,6 +2,6 @@ * Returns true if the string value is zero in hex * @param hexNumberString */ -export default function isZero(hexNumberString: string) { +export function isZero(hexNumberString: string) { return /^0x0*$/.test(hexNumberString) } diff --git a/apps/cowswap-frontend/src/utils/jotai/atomWithPartialUpdate.ts b/libs/common-utils/src/jotai/atomWithPartialUpdate.ts similarity index 82% rename from apps/cowswap-frontend/src/utils/jotai/atomWithPartialUpdate.ts rename to libs/common-utils/src/jotai/atomWithPartialUpdate.ts index ae0ac9c5ad..6b3fab7bed 100644 --- a/apps/cowswap-frontend/src/utils/jotai/atomWithPartialUpdate.ts +++ b/libs/common-utils/src/jotai/atomWithPartialUpdate.ts @@ -1,5 +1,4 @@ -import { PrimitiveAtom, WritableAtom } from 'jotai' -import { atom } from 'jotai/index' +import { atom, PrimitiveAtom, WritableAtom } from 'jotai' export function atomWithPartialUpdate(anyAtom: PrimitiveAtom): { atom: typeof anyAtom diff --git a/apps/cowswap-frontend/src/legacy/utils/index.test.ts b/libs/common-utils/src/legacyAddressUtils.test.ts similarity index 89% rename from apps/cowswap-frontend/src/legacy/utils/index.test.ts rename to libs/common-utils/src/legacyAddressUtils.test.ts index 45b4642f70..890cf964f2 100644 --- a/apps/cowswap-frontend/src/legacy/utils/index.test.ts +++ b/libs/common-utils/src/legacyAddressUtils.test.ts @@ -1,13 +1,10 @@ -import { isAddress, shortenAddress } from '.' +import { isAddress, shortenAddress } from './legacyAddressUtils' describe('utils', () => { describe('#isAddress', () => { it('returns false if not', () => { expect(isAddress('')).toBe(false) expect(isAddress('0x0000')).toBe(false) - expect(isAddress(1)).toBe(false) - expect(isAddress({})).toBe(false) - expect(isAddress(undefined)).toBe(false) }) it('returns the checksummed address', () => { diff --git a/apps/cowswap-frontend/src/legacy/utils/index.ts b/libs/common-utils/src/legacyAddressUtils.ts similarity index 90% rename from apps/cowswap-frontend/src/legacy/utils/index.ts rename to libs/common-utils/src/legacyAddressUtils.ts index 176479f1e5..b5e706ee73 100644 --- a/apps/cowswap-frontend/src/legacy/utils/index.ts +++ b/libs/common-utils/src/legacyAddressUtils.ts @@ -1,16 +1,16 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { getAddress } from '@ethersproject/address' import { AddressZero } from '@ethersproject/constants' -import { Contract } from '@ethersproject/contracts' +import { Contract, ContractInterface } from '@ethersproject/contracts' import { JsonRpcProvider, JsonRpcSigner } from '@ethersproject/providers' +import { getExplorerOrderLink } from './explorer' -import { ORDER_ID_SHORT_LENGTH } from 'legacy/constants' -import { getExplorerOrderLink } from 'legacy/utils/explorer' +const ORDER_ID_SHORT_LENGTH = 8 // returns the checksummed address if the address is valid, otherwise returns false -export function isAddress(value: any): string | false { +export function isAddress(value: string | undefined | null): string | false { try { - return getAddress(value) + return getAddress(value as never) } catch { return false } @@ -36,12 +36,17 @@ export function getProviderOrSigner(provider: JsonRpcProvider, account?: string) } // account is optional -export function getContract(address: string, ABI: any, provider: JsonRpcProvider, account?: string): Contract { +export function getContract( + address: string, + ABI: ContractInterface, + provider: JsonRpcProvider, + account?: string +): Contract { if (!isAddress(address) || address === AddressZero) { throw Error(`Invalid 'address' parameter '${address}'.`) } - return new Contract(address, ABI, getProviderOrSigner(provider, account) as any) + return new Contract(address, ABI, getProviderOrSigner(provider, account)) } export function escapeRegExp(string: string): string { diff --git a/apps/cowswap-frontend/src/legacy/utils/listSort.ts b/libs/common-utils/src/listSort.ts similarity index 74% rename from apps/cowswap-frontend/src/legacy/utils/listSort.ts rename to libs/common-utils/src/listSort.ts index 259ff4da71..1c97484f5c 100644 --- a/apps/cowswap-frontend/src/legacy/utils/listSort.ts +++ b/libs/common-utils/src/listSort.ts @@ -1,4 +1,4 @@ -import { DEFAULT_LIST_OF_LISTS } from './../constants/lists' +import { DEFAULT_LIST_OF_LISTS } from '@cowprotocol/common-const' const DEFAULT_LIST_PRIORITIES = DEFAULT_LIST_OF_LISTS.reduce<{ [listUrl: string]: number }>((memo, listUrl, index) => { memo[listUrl] = index + 1 @@ -6,7 +6,7 @@ const DEFAULT_LIST_PRIORITIES = DEFAULT_LIST_OF_LISTS.reduce<{ [listUrl: string] }, {}) // use ordering of default list of lists to assign priority -export default function sortByListPriority(urlA: string, urlB: string) { +export function sortByListPriority(urlA: string, urlB: string) { if (DEFAULT_LIST_PRIORITIES[urlA] && DEFAULT_LIST_PRIORITIES[urlB]) { return DEFAULT_LIST_PRIORITIES[urlA] - DEFAULT_LIST_PRIORITIES[urlB] } diff --git a/apps/cowswap-frontend/src/utils/localStorage.ts b/libs/common-utils/src/localStorage.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/localStorage.ts rename to libs/common-utils/src/localStorage.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/logging/index.ts b/libs/common-utils/src/logging/index.ts similarity index 90% rename from apps/cowswap-frontend/src/legacy/utils/logging/index.ts rename to libs/common-utils/src/logging/index.ts index fc922f318f..2955e23795 100644 --- a/apps/cowswap-frontend/src/legacy/utils/logging/index.ts +++ b/libs/common-utils/src/logging/index.ts @@ -1,8 +1,5 @@ import * as Sentry from '@sentry/react' -import OperatorError from 'api/gnosisProtocol/errors/OperatorError' -import QuoteError from 'api/gnosisProtocol/errors/QuoteError' - type SentryErrorOptions = { message: string name: string @@ -12,7 +9,7 @@ type SentryErrorOptions = { } export function constructSentryError( - baseError: QuoteError | OperatorError | Error, + baseError: Error, response: any, { message, name, optionalTags = {} }: SentryErrorOptions ) { diff --git a/apps/cowswap-frontend/src/legacy/utils/maxAmountSpend.ts b/libs/common-utils/src/maxAmountSpend.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/maxAmountSpend.ts rename to libs/common-utils/src/maxAmountSpend.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/misc.ts b/libs/common-utils/src/misc.ts similarity index 98% rename from apps/cowswap-frontend/src/legacy/utils/misc.ts rename to libs/common-utils/src/misc.ts index 0c8d68004e..8ca3b699d7 100644 --- a/apps/cowswap-frontend/src/legacy/utils/misc.ts +++ b/libs/common-utils/src/misc.ts @@ -2,7 +2,10 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { OrderKind } from '@cowprotocol/cow-sdk' import { Percent } from '@uniswap/sdk-core' -import { Market } from 'legacy/types' +interface Market { + baseToken: T + quoteToken: T +} const PROVIDER_REJECT_REQUEST_CODES = [4001, -32000] // See https://eips.ethereum.org/EIPS/eip-1193 const PROVIDER_REJECT_REQUEST_ERROR_MESSAGES = [ diff --git a/apps/cowswap-frontend/src/legacy/utils/node.ts b/libs/common-utils/src/node.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/node.ts rename to libs/common-utils/src/node.ts diff --git a/apps/cowswap-frontend/src/lib/utils/parseENSAddress.test.ts b/libs/common-utils/src/parseENSAddress.test.ts similarity index 95% rename from apps/cowswap-frontend/src/lib/utils/parseENSAddress.test.ts rename to libs/common-utils/src/parseENSAddress.test.ts index 9a3f5fc946..975449b601 100644 --- a/apps/cowswap-frontend/src/lib/utils/parseENSAddress.test.ts +++ b/libs/common-utils/src/parseENSAddress.test.ts @@ -1,4 +1,4 @@ -import parseENSAddress from './parseENSAddress' +import { parseENSAddress } from './parseENSAddress' describe('parseENSAddress', () => { it('test cases', () => { diff --git a/apps/cowswap-frontend/src/lib/utils/parseENSAddress.ts b/libs/common-utils/src/parseENSAddress.ts similarity index 64% rename from apps/cowswap-frontend/src/lib/utils/parseENSAddress.ts rename to libs/common-utils/src/parseENSAddress.ts index ababade998..68818595fc 100644 --- a/apps/cowswap-frontend/src/lib/utils/parseENSAddress.ts +++ b/libs/common-utils/src/parseENSAddress.ts @@ -1,8 +1,6 @@ const ENS_NAME_REGEX = /^(([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\.)+)eth(\/.*)?$/ -export default function parseENSAddress( - ensAddress: string -): { ensName: string; ensPath: string | undefined } | undefined { +export function parseENSAddress(ensAddress: string): { ensName: string; ensPath: string | undefined } | undefined { const match = ensAddress.match(ENS_NAME_REGEX) if (!match) return undefined return { ensName: `${match[1].toLowerCase()}eth`, ensPath: match[4] } diff --git a/apps/cowswap-frontend/src/utils/rawToTokenAmount.ts b/libs/common-utils/src/rawToTokenAmount.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/rawToTokenAmount.ts rename to libs/common-utils/src/rawToTokenAmount.ts diff --git a/apps/cowswap-frontend/src/utils/request.ts b/libs/common-utils/src/request.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/request.ts rename to libs/common-utils/src/request.ts diff --git a/apps/cowswap-frontend/src/lib/utils/resolveENSContentHash.ts b/libs/common-utils/src/resolveENSContentHash.ts similarity index 93% rename from apps/cowswap-frontend/src/lib/utils/resolveENSContentHash.ts rename to libs/common-utils/src/resolveENSContentHash.ts index 97e9f5e6aa..a3560b1166 100644 --- a/apps/cowswap-frontend/src/lib/utils/resolveENSContentHash.ts +++ b/libs/common-utils/src/resolveENSContentHash.ts @@ -59,7 +59,7 @@ function resolverContract(resolverAddress: string, provider: Provider): Contract * @param ensName to resolve * @param provider provider to use to fetch the data */ -export default async function resolveENSContentHash(ensName: string, provider: Provider): Promise { +export async function resolveENSContentHash(ensName: string, provider: Provider): Promise { const ensRegistrarContract = new Contract(REGISTRAR_ADDRESS, REGISTRAR_ABI, provider) const hash = namehash(ensName) const resolverAddress = await ensRegistrarContract.resolver(hash) diff --git a/apps/cowswap-frontend/src/legacy/utils/retry.test.ts b/libs/common-utils/src/retry.test.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/retry.test.ts rename to libs/common-utils/src/retry.test.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/retry.ts b/libs/common-utils/src/retry.ts similarity index 94% rename from apps/cowswap-frontend/src/legacy/utils/retry.ts rename to libs/common-utils/src/retry.ts index 789b2c92b6..768be301fc 100644 --- a/apps/cowswap-frontend/src/legacy/utils/retry.ts +++ b/libs/common-utils/src/retry.ts @@ -43,8 +43,10 @@ export function retry( ): { promise: Promise; cancel: () => void } { let completed = false let rejectCancelled: (error: Error) => void + // eslint-disable-next-line no-async-promise-executor const promise = new Promise(async (resolve, reject) => { rejectCancelled = reject + // eslint-disable-next-line no-constant-condition while (true) { let result: T try { diff --git a/apps/cowswap-frontend/src/legacy/utils/safeNamehash.ts b/libs/common-utils/src/safeNamehash.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/safeNamehash.ts rename to libs/common-utils/src/safeNamehash.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/sound.ts b/libs/common-utils/src/sound.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/sound.ts rename to libs/common-utils/src/sound.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/swapErrorToUserReadableMessage.tsx b/libs/common-utils/src/swapErrorToUserReadableMessage.tsx similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/swapErrorToUserReadableMessage.tsx rename to libs/common-utils/src/swapErrorToUserReadableMessage.tsx diff --git a/apps/cowswap-frontend/src/utils/time.ts b/libs/common-utils/src/time.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/time.ts rename to libs/common-utils/src/time.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/toggleBodyClass.ts b/libs/common-utils/src/toggleBodyClass.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/toggleBodyClass.ts rename to libs/common-utils/src/toggleBodyClass.ts diff --git a/apps/cowswap-frontend/src/legacy/utils/tokens.ts b/libs/common-utils/src/tokens.ts similarity index 82% rename from apps/cowswap-frontend/src/legacy/utils/tokens.ts rename to libs/common-utils/src/tokens.ts index 80c4124f25..de556a5f11 100644 --- a/apps/cowswap-frontend/src/legacy/utils/tokens.ts +++ b/libs/common-utils/src/tokens.ts @@ -1,7 +1,10 @@ import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' -import { NATIVE_CURRENCY_BUY_ADDRESS } from 'legacy/constants' -import { GpEther as ETHER, WRAPPED_NATIVE_CURRENCY as WETH } from 'legacy/constants/tokens' +import { + NATIVE_CURRENCY_BUY_ADDRESS, + GpEther as ETHER, + WRAPPED_NATIVE_CURRENCY as WETH, +} from '@cowprotocol/common-const' export function isNativeAddress(tokenAddress: string, chainId: ChainId) { return tokenAddress === 'ETH' || tokenAddress === ETHER.onChain(chainId).symbol diff --git a/apps/cowswap-frontend/src/legacy/utils/tooltips.ts b/libs/common-utils/src/tooltips.ts similarity index 89% rename from apps/cowswap-frontend/src/legacy/utils/tooltips.ts rename to libs/common-utils/src/tooltips.ts index 9093b7c648..1f35e44235 100644 --- a/apps/cowswap-frontend/src/legacy/utils/tooltips.ts +++ b/libs/common-utils/src/tooltips.ts @@ -1,6 +1,5 @@ import { Percent } from '@uniswap/sdk-core' - -import { formatPercent } from 'utils/amountFormat' +import { formatPercent } from './amountFormat' export function getMinimumReceivedTooltip(allowedSlippage: Percent, isExactIn: boolean): string { return `${ diff --git a/apps/cowswap-frontend/src/utils/trimTrailingZeros.test.ts b/libs/common-utils/src/trimTrailingZeros.test.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/trimTrailingZeros.test.ts rename to libs/common-utils/src/trimTrailingZeros.test.ts diff --git a/apps/cowswap-frontend/src/utils/trimTrailingZeros.ts b/libs/common-utils/src/trimTrailingZeros.ts similarity index 100% rename from apps/cowswap-frontend/src/utils/trimTrailingZeros.ts rename to libs/common-utils/src/trimTrailingZeros.ts diff --git a/apps/cowswap-frontend/src/lib/utils/tryParseCurrencyAmount.ts b/libs/common-utils/src/tryParseCurrencyAmount.ts similarity index 78% rename from apps/cowswap-frontend/src/lib/utils/tryParseCurrencyAmount.ts rename to libs/common-utils/src/tryParseCurrencyAmount.ts index 630f395e93..6d13db3884 100644 --- a/apps/cowswap-frontend/src/lib/utils/tryParseCurrencyAmount.ts +++ b/libs/common-utils/src/tryParseCurrencyAmount.ts @@ -7,13 +7,13 @@ import JSBI from 'jsbi' * Parses a CurrencyAmount from the passed string. * Returns the CurrencyAmount, or undefined if parsing fails. */ -export default function tryParseCurrencyAmount(value: string, currency: T): CurrencyAmount -export default function tryParseCurrencyAmount(value: Fraction, currency: T): CurrencyAmount -export default function tryParseCurrencyAmount( +export function tryParseCurrencyAmount(value: string, currency: T): CurrencyAmount +export function tryParseCurrencyAmount(value: Fraction, currency: T): CurrencyAmount +export function tryParseCurrencyAmount( value?: string, currency?: T ): CurrencyAmount | undefined -export default function tryParseCurrencyAmount( +export function tryParseCurrencyAmount( value?: string | Fraction, currency?: T ): CurrencyAmount | undefined { diff --git a/apps/cowswap-frontend/src/utils/tryParseFractionalAmount.ts b/libs/common-utils/src/tryParseFractionalAmount.ts similarity index 90% rename from apps/cowswap-frontend/src/utils/tryParseFractionalAmount.ts rename to libs/common-utils/src/tryParseFractionalAmount.ts index 0c4dc7e8c9..e2c55d5860 100644 --- a/apps/cowswap-frontend/src/utils/tryParseFractionalAmount.ts +++ b/libs/common-utils/src/tryParseFractionalAmount.ts @@ -1,6 +1,5 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' - -import { FractionUtils } from 'utils/fractionUtils' +import { FractionUtils } from './fractionUtils' export function tryParseFractionalAmount( currency: Currency | null, diff --git a/libs/common-utils/src/types.ts b/libs/common-utils/src/types.ts new file mode 100644 index 0000000000..ea882b0091 --- /dev/null +++ b/libs/common-utils/src/types.ts @@ -0,0 +1,25 @@ +import { Currency, CurrencyAmount, Fraction, Price } from '@uniswap/sdk-core' + +export type Writeable = { -readonly [P in keyof T]: T[P] } + +export type Nullish = T | null | undefined + +// This is for Pixel tracking injected code +declare global { + interface Window { + fbq: any // Facebook (Meta) + lintrk: any // Linkedin + twq: any // Twitter + rdt: any // Reddit + pvd: any // Paved + uetq: any // Microsoft Ads + } +} +export type FractionLike = Fraction | Price | CurrencyAmount + +export type ComposableCowInfo = { + id?: string + parentId?: string + isVirtualPart?: boolean + isTheLastPart?: boolean +} diff --git a/apps/cowswap-frontend/src/lib/utils/uriToHttp.test.ts b/libs/common-utils/src/uriToHttp.test.ts similarity index 96% rename from apps/cowswap-frontend/src/lib/utils/uriToHttp.test.ts rename to libs/common-utils/src/uriToHttp.test.ts index 2e922cf9fa..482fb4720a 100644 --- a/apps/cowswap-frontend/src/lib/utils/uriToHttp.test.ts +++ b/libs/common-utils/src/uriToHttp.test.ts @@ -1,4 +1,4 @@ -import uriToHttp from './uriToHttp' +import { uriToHttp } from './uriToHttp' describe('uriToHttp', () => { it('returns .eth.link for ens names', () => { diff --git a/apps/cowswap-frontend/src/lib/utils/uriToHttp.ts b/libs/common-utils/src/uriToHttp.ts similarity index 81% rename from apps/cowswap-frontend/src/lib/utils/uriToHttp.ts rename to libs/common-utils/src/uriToHttp.ts index 5de73c982c..1158fff329 100644 --- a/apps/cowswap-frontend/src/lib/utils/uriToHttp.ts +++ b/libs/common-utils/src/uriToHttp.ts @@ -2,7 +2,7 @@ * Given a URI that may be ipfs, ipns, http, https, ar, or data protocol, return the fetch-able http(s) URLs for the same content * @param uri to convert to fetch-able http url */ -export default function uriToHttp(uri: string): string[] { +export function uriToHttp(uri: string): string[] { const protocol = uri.split(':')[0].toLowerCase() switch (protocol) { case 'data': @@ -12,12 +12,15 @@ export default function uriToHttp(uri: string): string[] { case 'http': return ['https' + uri.substr(4), uri] case 'ipfs': + // eslint-disable-next-line no-case-declarations const hash = uri.match(/^ipfs:(\/\/)?(ipfs\/)?(.*)$/i)?.[3] // TODO: probably a bug on original code return [`https://cloudflare-ipfs.com/ipfs/${hash}/`, `https://ipfs.io/ipfs/${hash}/`] case 'ipns': + // eslint-disable-next-line no-case-declarations const name = uri.match(/^ipns:(\/\/)?(.*)$/i)?.[2] return [`https://cloudflare-ipfs.com/ipns/${name}/`, `https://ipfs.io/ipns/${name}/`] case 'ar': + // eslint-disable-next-line no-case-declarations const tx = uri.match(/^ar:(\/\/)?(.*)$/i)?.[2] return [`https://arweave.net/${tx}`] default: diff --git a/apps/cowswap-frontend/src/legacy/utils/userAgent.ts b/libs/common-utils/src/userAgent.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/utils/userAgent.ts rename to libs/common-utils/src/userAgent.ts diff --git a/libs/common-utils/tsconfig.json b/libs/common-utils/tsconfig.json new file mode 100644 index 0000000000..bab74ff2e6 --- /dev/null +++ b/libs/common-utils/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["vite/client"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/common-utils/tsconfig.lib.json b/libs/common-utils/tsconfig.lib.json new file mode 100644 index 0000000000..1b2b0c12df --- /dev/null +++ b/libs/common-utils/tsconfig.lib.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node", "vite/client"] + }, + "files": ["../../node_modules/@nx/react/typings/cssmodule.d.ts", "../../node_modules/@nx/react/typings/image.d.ts"], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/common-utils/tsconfig.spec.json b/libs/common-utils/tsconfig.spec.json new file mode 100644 index 0000000000..26ef046ac5 --- /dev/null +++ b/libs/common-utils/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/libs/common-utils/vite.config.ts b/libs/common-utils/vite.config.ts new file mode 100644 index 0000000000..9232cc2b74 --- /dev/null +++ b/libs/common-utils/vite.config.ts @@ -0,0 +1,56 @@ +/// +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' +import viteTsConfigPaths from 'vite-tsconfig-paths' +import dts from 'vite-plugin-dts' +import * as path from 'path' +import { getReactProcessEnv } from '../../tools/getReactProcessEnv' + +export default defineConfig(({ mode }) => { + return { + define: { + ...getReactProcessEnv(mode), + }, + + cacheDir: '../../node_modules/.vite/common-utils', + + plugins: [ + dts({ + entryRoot: 'src', + tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'), + skipDiagnostics: true, + }), + react(), + viteTsConfigPaths({ + root: '../../', + }), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + lib: { + // Could also be a dictionary or array of multiple entry points. + entry: 'src/index.ts', + name: 'common-utils', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es', 'cjs'], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: ['react', 'react-dom', 'react/jsx-runtime'], + }, + }, + } +}) diff --git a/libs/core/.babelrc b/libs/core/.babelrc new file mode 100644 index 0000000000..ef4889c1ab --- /dev/null +++ b/libs/core/.babelrc @@ -0,0 +1,20 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [ + [ + "styled-components", + { + "pure": true, + "ssr": true + } + ] + ] +} diff --git a/libs/core/.eslintrc.json b/libs/core/.eslintrc.json new file mode 100644 index 0000000000..a39ac5d057 --- /dev/null +++ b/libs/core/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["plugin:@nx/react", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/core/README.md b/libs/core/README.md new file mode 100644 index 0000000000..3b616f93d9 --- /dev/null +++ b/libs/core/README.md @@ -0,0 +1 @@ +# Core diff --git a/libs/core/jest.config.ts b/libs/core/jest.config.ts new file mode 100644 index 0000000000..ae2ca52072 --- /dev/null +++ b/libs/core/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'core', + preset: '../../jest.preset.js', + transform: { + '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', + '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/libs/core', +} diff --git a/libs/core/package.json b/libs/core/package.json new file mode 100644 index 0000000000..9ca3cccdc7 --- /dev/null +++ b/libs/core/package.json @@ -0,0 +1,12 @@ +{ + "name": "@cowprotocol/core", + "version": "0.0.1", + "main": "./index.js", + "types": "./index.d.ts", + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.js" + } + } +} diff --git a/libs/core/project.json b/libs/core/project.json new file mode 100644 index 0000000000..fb33a1f5f1 --- /dev/null +++ b/libs/core/project.json @@ -0,0 +1,46 @@ +{ + "name": "@cowprotocol/core", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/core/src", + "projectType": "library", + "tags": [], + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/core/**/*.{ts,tsx,js,jsx}"] + } + }, + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/libs/core" + }, + "configurations": { + "development": { + "mode": "development" + }, + "production": { + "mode": "production" + } + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/core/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + } +} diff --git a/apps/cowswap-frontend/src/modules/gasPirce/index.ts b/libs/core/src/gasPirce/index.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/gasPirce/index.ts rename to libs/core/src/gasPirce/index.ts diff --git a/apps/cowswap-frontend/src/modules/gasPirce/state/gasPriceAtom.ts b/libs/core/src/gasPirce/state/gasPriceAtom.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/gasPirce/state/gasPriceAtom.ts rename to libs/core/src/gasPirce/state/gasPriceAtom.ts diff --git a/apps/cowswap-frontend/src/api/gnosisSafe/index.ts b/libs/core/src/gnosisSafe/index.ts similarity index 97% rename from apps/cowswap-frontend/src/api/gnosisSafe/index.ts rename to libs/core/src/gnosisSafe/index.ts index ee5b84cabf..c12a6531b9 100644 --- a/apps/cowswap-frontend/src/api/gnosisSafe/index.ts +++ b/libs/core/src/gnosisSafe/index.ts @@ -7,8 +7,6 @@ import { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-type // eslint-disable-next-line no-restricted-imports import { ethers } from 'ethers' -import { registerOnWindow } from 'legacy/utils/misc' - const SAFE_TRANSACTION_SERVICE_URL: Partial> = { [SupportedChainId.MAINNET]: 'https://safe-transaction-mainnet.safe.global', [SupportedChainId.GNOSIS_CHAIN]: 'https://safe-transaction-gnosis-chain.safe.global', @@ -100,5 +98,3 @@ export function getSafeInfo(chainId: number, safeAddress: string, library: Web3P return Promise.reject(error) } } - -registerOnWindow({ getSafeTransaction, getSafeInfo }) diff --git a/libs/core/src/index.ts b/libs/core/src/index.ts new file mode 100644 index 0000000000..7ec7c07d69 --- /dev/null +++ b/libs/core/src/index.ts @@ -0,0 +1,3 @@ +export * from './jotaiStore' +export * from './gasPirce' +export * from './gnosisSafe' diff --git a/apps/cowswap-frontend/src/jotaiStore.ts b/libs/core/src/jotaiStore.ts similarity index 100% rename from apps/cowswap-frontend/src/jotaiStore.ts rename to libs/core/src/jotaiStore.ts diff --git a/libs/core/tsconfig.json b/libs/core/tsconfig.json new file mode 100644 index 0000000000..bab74ff2e6 --- /dev/null +++ b/libs/core/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["vite/client"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/core/tsconfig.lib.json b/libs/core/tsconfig.lib.json new file mode 100644 index 0000000000..1b2b0c12df --- /dev/null +++ b/libs/core/tsconfig.lib.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node", "vite/client"] + }, + "files": ["../../node_modules/@nx/react/typings/cssmodule.d.ts", "../../node_modules/@nx/react/typings/image.d.ts"], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/core/tsconfig.spec.json b/libs/core/tsconfig.spec.json new file mode 100644 index 0000000000..26ef046ac5 --- /dev/null +++ b/libs/core/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/libs/core/vite.config.ts b/libs/core/vite.config.ts new file mode 100644 index 0000000000..5060b85db8 --- /dev/null +++ b/libs/core/vite.config.ts @@ -0,0 +1,49 @@ +/// +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' +import viteTsConfigPaths from 'vite-tsconfig-paths' +import dts from 'vite-plugin-dts' +import * as path from 'path' + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/core', + + plugins: [ + dts({ + entryRoot: 'src', + tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'), + skipDiagnostics: true, + }), + react(), + viteTsConfigPaths({ + root: '../../', + }), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + lib: { + // Could also be a dictionary or array of multiple entry points. + entry: 'src/index.ts', + name: 'core', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es', 'cjs'], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: ['react', 'react-dom', 'react/jsx-runtime'], + }, + }, +}) diff --git a/libs/ens/.babelrc b/libs/ens/.babelrc new file mode 100644 index 0000000000..ef4889c1ab --- /dev/null +++ b/libs/ens/.babelrc @@ -0,0 +1,20 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [ + [ + "styled-components", + { + "pure": true, + "ssr": true + } + ] + ] +} diff --git a/libs/ens/.eslintrc.json b/libs/ens/.eslintrc.json new file mode 100644 index 0000000000..a39ac5d057 --- /dev/null +++ b/libs/ens/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "extends": ["plugin:@nx/react", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/ens/README.md b/libs/ens/README.md new file mode 100644 index 0000000000..a20b45dc80 --- /dev/null +++ b/libs/ens/README.md @@ -0,0 +1 @@ +# ENS diff --git a/libs/ens/jest.config.ts b/libs/ens/jest.config.ts new file mode 100644 index 0000000000..35d3bf8180 --- /dev/null +++ b/libs/ens/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'ens', + preset: '../../jest.preset.js', + transform: { + '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', + '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/libs/ens', +} diff --git a/libs/ens/package.json b/libs/ens/package.json new file mode 100644 index 0000000000..089aca8f63 --- /dev/null +++ b/libs/ens/package.json @@ -0,0 +1,12 @@ +{ + "name": "@cowprotocol/ens", + "version": "0.0.1", + "main": "./index.js", + "types": "./index.d.ts", + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.js" + } + } +} diff --git a/libs/ens/project.json b/libs/ens/project.json new file mode 100644 index 0000000000..cf52dfa562 --- /dev/null +++ b/libs/ens/project.json @@ -0,0 +1,46 @@ +{ + "name": "@cowprotocol/ens", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/ens/src", + "projectType": "library", + "tags": [], + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/ens/**/*.{ts,tsx,js,jsx}"] + } + }, + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/libs/ens" + }, + "configurations": { + "development": { + "mode": "development" + }, + "production": { + "mode": "production" + } + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/ens/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + } +} diff --git a/apps/cowswap-frontend/src/legacy/hooks/useENS.ts b/libs/ens/src/hooks/useENS.ts similarity index 79% rename from apps/cowswap-frontend/src/legacy/hooks/useENS.ts rename to libs/ens/src/hooks/useENS.ts index 4011ca9cb3..a524ffaeb1 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useENS.ts +++ b/libs/ens/src/hooks/useENS.ts @@ -1,15 +1,15 @@ import { useMemo } from 'react' -import useENSAddress from './useENSAddress' -import useENSName from './useENSName' +import { isAddress } from '@cowprotocol/common-utils' -import { isAddress } from '../utils' +import { useENSAddress } from './useENSAddress' +import { useENSName } from './useENSName' /** * Given a name or address, does a lookup to resolve to an address and name * @param nameOrAddress ENS name or address */ -export default function useENS(nameOrAddress?: string | null): { +export function useENS(nameOrAddress?: string | null): { loading: boolean address: string | null name: string | null diff --git a/libs/ens/src/hooks/useENSAddress.ts b/libs/ens/src/hooks/useENSAddress.ts new file mode 100644 index 0000000000..617d88982d --- /dev/null +++ b/libs/ens/src/hooks/useENSAddress.ts @@ -0,0 +1,21 @@ +import { useMemo } from 'react' + +import { safeNamehash } from '@cowprotocol/common-utils' +import { useENSResolverMethod } from './useENSResolverMethod' + +/** + * Does a lookup for an ENS name to find its address. + */ +export function useENSAddress(ensName?: string | null): { loading: boolean; address: string | null } { + const ensNodeArgument = useMemo(() => (ensName === null ? undefined : safeNamehash(ensName)), [ensName]) + + const { data: addr, isLoading: addrLoading } = useENSResolverMethod('addr', ensNodeArgument) + + return useMemo( + () => ({ + address: addr ?? null, + loading: addrLoading, + }), + [addr, addrLoading] + ) +} diff --git a/libs/ens/src/hooks/useENSAvatar.ts b/libs/ens/src/hooks/useENSAvatar.ts new file mode 100644 index 0000000000..6c04dcd73e --- /dev/null +++ b/libs/ens/src/hooks/useENSAvatar.ts @@ -0,0 +1,198 @@ +import { useEffect, useMemo, useState } from 'react' + +import { safeNamehash, uriToHttp, isAddress, isZero, getContract } from '@cowprotocol/common-utils' +import { BigNumber } from '@ethersproject/bignumber' +import { hexZeroPad } from '@ethersproject/bytes' +import { namehash } from '@ethersproject/hash' + +import { useENSName } from './useENSName' +import { useENSResolverContract } from './useENSResolverContract' +import useSWR from 'swr' +import { useENSResolver } from './useENSResolver' +import { useWeb3React } from '@web3-react/core' +import { Erc1155, Erc1155Abi, Erc721, Erc721Abi } from '@cowprotocol/abis' + +/** + * Returns the ENS avatar URI, if available. + * Spec: https://gist.github.com/Arachnid/9db60bd75277969ee1689c8742b75182. + */ +export function useENSAvatar( + account: string | undefined, + enforceOwnership = true +): { avatar: string | null; loading: boolean } { + const node = useMemo(() => { + if (!account || !isAddress(account)) return undefined + return namehash(`${account.toLowerCase().substr(2)}.addr.reverse`) + }, [account]) + + const addressAvatar = useAvatarFromNode(node) + const ENSName = useENSName(account).ENSName + const nameAvatar = useAvatarFromNode(ENSName === null ? undefined : safeNamehash(ENSName)) + let avatar = addressAvatar.avatar || nameAvatar.avatar + + const nftAvatar = useAvatarFromNFT(account, avatar, enforceOwnership) + avatar = nftAvatar.avatar || avatar + + const http = avatar && uriToHttp(avatar)[0] + + return useMemo( + () => ({ + avatar: http ?? null, + loading: addressAvatar.loading || nameAvatar.loading || nftAvatar.loading, + }), + [addressAvatar.loading, http, nameAvatar.loading, nftAvatar.loading] + ) +} + +function useAvatarFromNode(node?: string): { avatar?: string; loading: boolean } { + const { data: resolverAddress } = useENSResolver(node) + + const resolverContract = useENSResolverContract( + resolverAddress && !isZero(resolverAddress) ? resolverAddress : undefined + ) + + const { data: avatar, isLoading } = useSWR(['useAvatarFromNode', node], async () => { + if (!resolverContract || !node) return undefined + + return resolverContract.callStatic.text(node, 'avatar') + }) + + return useMemo( + () => ({ + avatar: avatar, + loading: isLoading, + }), + [avatar, isLoading] + ) +} + +function useAvatarFromNFT( + account: string | undefined, + nftUri = '', + enforceOwnership: boolean +): { avatar?: string; loading: boolean } { + const parts = nftUri.toLowerCase().split(':') + const protocol = parts[0] + // ignore the chain from eip155 + // TODO: when we are able, pull only from the specified chain + const [, erc] = parts[1]?.split('/') ?? [] + const [contractAddress, id] = parts[2]?.split('/') ?? [] + const isERC721 = protocol === 'eip155' && erc === 'erc721' + const isERC1155 = protocol === 'eip155' && erc === 'erc1155' + const erc721 = useERC721Uri(account, isERC721 ? contractAddress : undefined, id, enforceOwnership) + const erc1155 = useERC1155Uri(account, isERC1155 ? contractAddress : undefined, id, enforceOwnership) + const uri = erc721.uri || erc1155.uri + const http = uri && uriToHttp(uri)[0] + + const [loading, setLoading] = useState(false) + const [avatar, setAvatar] = useState(undefined) + useEffect(() => { + setAvatar(undefined) + if (http) { + setLoading(true) + fetch(http) + .then((res) => res.json()) + .then(({ image }) => { + setAvatar(image) + }) + .catch((e) => console.warn(e)) + .finally(() => { + setLoading(false) + }) + } + }, [http]) + + return useMemo( + () => ({ avatar, loading: erc721.loading || erc1155.loading || loading }), + [avatar, erc1155.loading, erc721.loading, loading] + ) +} + +function useERC721Uri( + account: string | undefined, + contractAddress: string | undefined, + id: string | undefined, + enforceOwnership: boolean +): { uri?: string; loading: boolean } { + const contract = useERC721Contract(contractAddress) + + const { data, isLoading } = useSWR(['useERC721Uri', contract, id], async () => { + if (!contract || !account || !id) return undefined + + const [owner, uri] = await Promise.all([contract.callStatic.ownerOf(id), contract.callStatic.tokenURI(id)]) + + return { owner, uri } + }) + + return useMemo( + () => ({ + uri: !enforceOwnership || account === data?.owner ? data?.uri : undefined, + loading: isLoading, + }), + [account, enforceOwnership, data, isLoading] + ) +} + +function useERC1155Uri( + account: string | undefined, + contractAddress: string | undefined, + id: string | undefined, + enforceOwnership: boolean +): { uri?: string; loading: boolean } { + const contract = useERC1155Contract(contractAddress) + + const { data, isLoading } = useSWR(['useERC1155Uri', contract, id, account], async () => { + if (!contract || !account || !id) return undefined + + const [balance, uri] = await Promise.all([contract.callStatic.balanceOf(account, id), contract.callStatic.uri(id)]) + + return { balance, uri } + }) + + // ERC-1155 allows a generic {id} in the URL, so prepare to replace if relevant, + // in lowercase hexadecimal (with no 0x prefix) and leading zero padded to 64 hex characters. + const idHex = getIdHex(id) || '' + + return useMemo(() => { + return { + uri: + (!enforceOwnership || data?.balance?.gt(0) ? (data?.uri || '').replace(/{id}/g, idHex) : undefined) || + undefined, + loading: isLoading, + } + }, [enforceOwnership, idHex, data, isLoading]) +} + +function useERC721Contract(address: string | undefined): Erc721 | undefined { + const { provider, chainId } = useWeb3React() + + const { data } = useSWR(['useERC721Contract', provider, chainId, address], () => { + if (!chainId || !provider || !address) return undefined + + return getContract(address, Erc721Abi, provider) as Erc721 + }) + + return data +} + +function useERC1155Contract(address: string | undefined): Erc1155 | undefined { + const { provider, chainId } = useWeb3React() + + const { data } = useSWR(['useERC1155Contract', provider, chainId, address], () => { + if (!chainId || !provider || !address) return undefined + + return getContract(address, Erc1155Abi, provider) as Erc1155 + }) + + return data +} + +function getIdHex(id: string | undefined): string | undefined { + try { + return id ? hexZeroPad(BigNumber.from(id).toHexString(), 32).substring(2) : id + } catch (e) { + console.log(`Couldn't get id hex from id: ${id}`, e) + + return undefined + } +} diff --git a/libs/ens/src/hooks/useENSContentHash.ts b/libs/ens/src/hooks/useENSContentHash.ts new file mode 100644 index 0000000000..b239caba06 --- /dev/null +++ b/libs/ens/src/hooks/useENSContentHash.ts @@ -0,0 +1,21 @@ +import { useMemo } from 'react' + +import { safeNamehash } from '@cowprotocol/common-utils' +import { useENSResolverMethod } from './useENSResolverMethod' + +/** + * Does a lookup for an ENS name to find its contenthash. + */ +export function useENSContentHash(ensName?: string | null): { loading: boolean; contenthash: string | null } { + const ensNodeArgument = useMemo(() => (ensName === null ? undefined : safeNamehash(ensName)), [ensName]) + + const { data: contenthash, isLoading: hashLoading } = useENSResolverMethod('contenthash', ensNodeArgument) + + return useMemo( + () => ({ + contenthash: contenthash ?? null, + loading: hashLoading, + }), + [hashLoading, contenthash] + ) +} diff --git a/libs/ens/src/hooks/useENSName.ts b/libs/ens/src/hooks/useENSName.ts new file mode 100644 index 0000000000..eceb8cd295 --- /dev/null +++ b/libs/ens/src/hooks/useENSName.ts @@ -0,0 +1,36 @@ +import { useMemo } from 'react' + +import { isAddress } from '@cowprotocol/common-utils' +import { namehash } from '@ethersproject/hash' + +import { useENSAddress } from './useENSAddress' +import { useENSResolverMethod } from './useENSResolverMethod' + +/** + * Does a reverse lookup for an address to find its ENS name. + * Note this is not the same as looking up an ENS name to find an address. + */ +export function useENSName(address?: string): { ENSName: string | null; loading: boolean } { + const ensNodeArgument = useMemo(() => { + if (!address || !isAddress(address)) return undefined + + return namehash(`${address.toLowerCase().substr(2)}.addr.reverse`) + }, [address]) + + const { data: name, isLoading: nameLoading } = useENSResolverMethod('name', ensNodeArgument) + + /* ENS does not enforce that an address owns a .eth domain before setting it as a reverse proxy + and recommends that you perform a match on the forward resolution + see: https://docs.ens.domains/dapp-developer-guide/resolving-names#reverse-resolution + */ + const fwdAddr = useENSAddress(name) + const checkedName = address === fwdAddr?.address ? name : null + + return useMemo( + () => ({ + ENSName: checkedName ?? null, + loading: nameLoading, + }), + [checkedName, nameLoading] + ) +} diff --git a/libs/ens/src/hooks/useENSRegistrarContract.ts b/libs/ens/src/hooks/useENSRegistrarContract.ts new file mode 100644 index 0000000000..0788e0b3a7 --- /dev/null +++ b/libs/ens/src/hooks/useENSRegistrarContract.ts @@ -0,0 +1,21 @@ +import { getContract } from '@cowprotocol/common-utils' +import { ENS_REGISTRAR_ADDRESSES } from '@cowprotocol/common-const' +import { EnsAbi, EnsRegistrar } from '@cowprotocol/abis' +import { useWeb3React } from '@web3-react/core' +import useSWR from 'swr' + +export function useENSRegistrarContract(): EnsRegistrar | undefined { + const { provider, chainId } = useWeb3React() + + const { data } = useSWR(['useENSRegistrarContract', provider, chainId], () => { + if (!chainId || !provider) return undefined + + const address = ENS_REGISTRAR_ADDRESSES[chainId] + + if (!address) return undefined + + return getContract(address, EnsAbi, provider) as EnsRegistrar + }) + + return data +} diff --git a/libs/ens/src/hooks/useENSResolver.ts b/libs/ens/src/hooks/useENSResolver.ts new file mode 100644 index 0000000000..92baf08774 --- /dev/null +++ b/libs/ens/src/hooks/useENSResolver.ts @@ -0,0 +1,12 @@ +import useSWR, { SWRResponse } from 'swr' +import { useENSRegistrarContract } from './useENSRegistrarContract' + +export function useENSResolver(node: string | undefined): SWRResponse { + const registrarContract = useENSRegistrarContract() + + return useSWR(['useENSResolver', node], async () => { + if (!registrarContract || !node) return undefined + + return registrarContract.callStatic.resolver(node) + }) +} diff --git a/libs/ens/src/hooks/useENSResolverContract.ts b/libs/ens/src/hooks/useENSResolverContract.ts new file mode 100644 index 0000000000..47ae7aada8 --- /dev/null +++ b/libs/ens/src/hooks/useENSResolverContract.ts @@ -0,0 +1,16 @@ +import { getContract } from '@cowprotocol/common-utils' +import { EnsPublicResolver, EnsPublicResolverAbi } from '@cowprotocol/abis' +import { useWeb3React } from '@web3-react/core' +import useSWR from 'swr' + +export function useENSResolverContract(address: string | undefined): EnsPublicResolver | undefined { + const { provider, chainId } = useWeb3React() + + const { data } = useSWR(['useENSResolverContract', provider, chainId, address], () => { + if (!chainId || !provider || !address) return undefined + + return getContract(address, EnsPublicResolverAbi, provider) as EnsPublicResolver + }) + + return data +} diff --git a/libs/ens/src/hooks/useENSResolverMethod.ts b/libs/ens/src/hooks/useENSResolverMethod.ts new file mode 100644 index 0000000000..edbcb8b467 --- /dev/null +++ b/libs/ens/src/hooks/useENSResolverMethod.ts @@ -0,0 +1,29 @@ +import useSWR from 'swr' +import { useENSResolver } from './useENSResolver' +import { useENSResolverContract } from './useENSResolverContract' +import { isZero } from '@cowprotocol/common-utils' +import { useMemo } from 'react' + +export function useENSResolverMethod( + method: 'addr' | 'name' | 'contenthash', + ensNodeArgument: string | undefined +): { data: string | undefined; isLoading: boolean } { + const { data: resolverAddress, isLoading: resolverAddressLoading } = useENSResolver(ensNodeArgument) + + const resolverContract = useENSResolverContract( + resolverAddress && !isZero(resolverAddress) ? resolverAddress : undefined + ) + + const { data, isLoading } = useSWR(['useENSResolverMethod' + method, resolverContract, ensNodeArgument], async () => { + if (!resolverContract || !ensNodeArgument) return undefined + + return resolverContract.callStatic[method](ensNodeArgument) + }) + + return useMemo(() => { + return { + data, + isLoading: resolverAddressLoading || isLoading, + } + }, [data, resolverAddressLoading, isLoading]) +} diff --git a/libs/ens/src/index.ts b/libs/ens/src/index.ts new file mode 100644 index 0000000000..827a599b5b --- /dev/null +++ b/libs/ens/src/index.ts @@ -0,0 +1,5 @@ +export * from './hooks/useENS' +export * from './hooks/useENSAddress' +export * from './hooks/useENSAvatar' +export * from './hooks/useENSContentHash' +export * from './hooks/useENSName' diff --git a/libs/ens/tsconfig.json b/libs/ens/tsconfig.json new file mode 100644 index 0000000000..bab74ff2e6 --- /dev/null +++ b/libs/ens/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["vite/client"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/ens/tsconfig.lib.json b/libs/ens/tsconfig.lib.json new file mode 100644 index 0000000000..1b2b0c12df --- /dev/null +++ b/libs/ens/tsconfig.lib.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node", "vite/client"] + }, + "files": ["../../node_modules/@nx/react/typings/cssmodule.d.ts", "../../node_modules/@nx/react/typings/image.d.ts"], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/ens/tsconfig.spec.json b/libs/ens/tsconfig.spec.json new file mode 100644 index 0000000000..26ef046ac5 --- /dev/null +++ b/libs/ens/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/libs/ens/vite.config.ts b/libs/ens/vite.config.ts new file mode 100644 index 0000000000..59415ff872 --- /dev/null +++ b/libs/ens/vite.config.ts @@ -0,0 +1,49 @@ +/// +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' +import viteTsConfigPaths from 'vite-tsconfig-paths' +import dts from 'vite-plugin-dts' +import * as path from 'path' + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/ens', + + plugins: [ + dts({ + entryRoot: 'src', + tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'), + skipDiagnostics: true, + }), + react(), + viteTsConfigPaths({ + root: '../../', + }), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + lib: { + // Could also be a dictionary or array of multiple entry points. + entry: 'src/index.ts', + name: 'ens', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es', 'cjs'], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: ['react', 'react-dom', 'react/jsx-runtime'], + }, + }, +}) diff --git a/libs/snackbars/README.md b/libs/snackbars/README.md index f80124370c..19aa96ff19 100644 --- a/libs/snackbars/README.md +++ b/libs/snackbars/README.md @@ -7,7 +7,7 @@ ```tsx // Add the widget in the root component -import { SnackbarsWidget } from '@cowswap/snackbars' +import { SnackbarsWidget } from '@cowprotocol/snackbars' export function App() { return ( @@ -22,7 +22,7 @@ export function App() { ```tsx // Use the hook to add a snackbar -import { useAddSnackbar } from '@cowswap/snackbars' +import { useAddSnackbar } from '@cowprotocol/snackbars' export function MyComponent() { const addSnackbar = useAddSnackbar() diff --git a/libs/snackbars/package.json b/libs/snackbars/package.json index ada384c9d3..9c5660059c 100644 --- a/libs/snackbars/package.json +++ b/libs/snackbars/package.json @@ -1,5 +1,5 @@ { - "name": "@cowswap/snackbars", + "name": "@cowprotocol/snackbars", "version": "0.0.1", "main": "./index.js", "types": "./index.d.ts", diff --git a/libs/snackbars/project.json b/libs/snackbars/project.json index 748a6c5a84..c816183936 100644 --- a/libs/snackbars/project.json +++ b/libs/snackbars/project.json @@ -1,5 +1,5 @@ { - "name": "@cowswap/snackbars", + "name": "@cowprotocol/snackbars", "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "libs/snackbars/src", "projectType": "library", diff --git a/libs/snackbars/vite.config.ts b/libs/snackbars/vite.config.ts index 9238b65a24..ca362ed6c5 100644 --- a/libs/snackbars/vite.config.ts +++ b/libs/snackbars/vite.config.ts @@ -1,6 +1,6 @@ /// import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' +import react from '@vitejs/plugin-react-swc' import viteTsConfigPaths from 'vite-tsconfig-paths' import dts from 'vite-plugin-dts' import * as path from 'path' diff --git a/libs/ui/.eslintrc.json b/libs/ui/.eslintrc.json index 64b3b1932f..5b5e742133 100644 --- a/libs/ui/.eslintrc.json +++ b/libs/ui/.eslintrc.json @@ -3,6 +3,9 @@ // "extends": ["plugin:@nx/react"], "extends": ["../../.eslintrc.json"], "ignorePatterns": ["!**/*"], + "rules": { + "@typescript-eslint/no-explicit-any": "off" + }, "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], diff --git a/libs/ui/project.json b/libs/ui/project.json index 852b95fb5f..e9d0b37aaf 100644 --- a/libs/ui/project.json +++ b/libs/ui/project.json @@ -1,5 +1,5 @@ { - "name": "ui", + "name": "@cowprotocol/ui", "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "libs/ui/src", "projectType": "library", diff --git a/libs/ui/src/consts.ts b/libs/ui/src/consts.ts new file mode 100644 index 0000000000..2ff084b7c6 --- /dev/null +++ b/libs/ui/src/consts.ts @@ -0,0 +1 @@ +export const AMOUNTS_FORMATTING_FEATURE_FLAG = 'highlight-amounts-formatting' diff --git a/apps/cowswap-frontend/src/legacy/theme/enum.ts b/libs/ui/src/enum.ts similarity index 100% rename from apps/cowswap-frontend/src/legacy/theme/enum.ts rename to libs/ui/src/enum.ts diff --git a/libs/ui/src/index.ts b/libs/ui/src/index.ts index c8ce325a11..f4df9da04b 100644 --- a/libs/ui/src/index.ts +++ b/libs/ui/src/index.ts @@ -1 +1,12 @@ -export * from './lib/ui' +export * from './pure/Button' +export * from './pure/Loader' +export { loadingOpacityMixin, LoadingRows } from './pure/Loader/styled' +export * from './pure/Row' +export * from './pure/FiatAmount' +export * from './pure/TokenSymbol' +export * from './pure/TokenAmount' +export * from './pure/SelectDropdown' +export * from './pure/Tooltip' +export * from './pure/Popover' +export * from './pure/ExternalLink' +export * from './enum' diff --git a/libs/ui/src/lib/ui.spec.tsx b/libs/ui/src/lib/ui.spec.tsx deleted file mode 100644 index a5690cf131..0000000000 --- a/libs/ui/src/lib/ui.spec.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { render } from '@testing-library/react' - -import { PinkTitle } from './ui' - -describe('Ui', () => { - it('should render successfully', () => { - const { baseElement } = render() - expect(baseElement).toBeTruthy() - }) -}) diff --git a/libs/ui/src/lib/ui.tsx b/libs/ui/src/lib/ui.tsx deleted file mode 100644 index d3bb871bd5..0000000000 --- a/libs/ui/src/lib/ui.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { PropsWithChildren } from 'react' - -import { return5 } from '@cowswap/ui-utils' - -/* eslint-disable-next-line */ -export interface UiProps extends PropsWithChildren {} - -export function PinkTitle(props: UiProps) { - return ( -
-

- {props.children} (return5 = {return5()}) -

-
- ) -} diff --git a/apps/cowswap-frontend/src/legacy/components/Button/ButtonMod.tsx b/libs/ui/src/pure/Button/ButtonMod.tsx similarity index 83% rename from apps/cowswap-frontend/src/legacy/components/Button/ButtonMod.tsx rename to libs/ui/src/pure/Button/ButtonMod.tsx index 2d8d4f2559..b3cc7e1a1b 100644 --- a/apps/cowswap-frontend/src/legacy/components/Button/ButtonMod.tsx +++ b/libs/ui/src/pure/Button/ButtonMod.tsx @@ -1,13 +1,10 @@ import { darken } from 'polished' -import { Check, ChevronDown } from 'react-feather' +import { ChevronDown } from 'react-feather' import { Button as RebassButton, ButtonProps as ButtonPropsOriginal } from 'rebass/styled-components' -import styled from 'styled-components/macro' +import styled from 'styled-components' -import { RowBetween } from 'legacy/components/Row' -import useTheme from 'legacy/hooks/useTheme' -import { ButtonSize } from 'legacy/theme/enum' - -import { UI } from 'common/constants/theme' +import { RowBetween } from '../Row' +import { ButtonSize } from '../../enum' type ButtonProps = Omit @@ -105,7 +102,7 @@ export const ButtonLight = styled(BaseButton)` export const ButtonGray = styled(BaseButton)` background-color: ${({ theme }) => theme.bg3}; - color: var(${UI.COLOR_TEXT2}); + color: var(--cow-color-text2); font-size: 16px; // font-weight: 500; @@ -153,7 +150,7 @@ export const ButtonSecondary = styled(BaseButton)` export const ButtonOutlined = styled(BaseButton)` border: 1px solid ${({ theme }) => theme.bg2}; background-color: transparent; - color: var(${UI.COLOR_TEXT1}); + color: var(--cow-color-text1); &:focus { box-shadow: 0 0 0 1px ${({ theme }) => theme.bg4}; } @@ -236,13 +233,13 @@ export const ButtonText = styled(BaseButton)` export const ButtonConfirmedStyle = styled(BaseButton)` background-color: ${({ theme }) => theme.bg3}; - color: var(${UI.COLOR_TEXT1}); + color: var(--cow-color-text1); /* border: 1px solid ${({ theme }) => theme.green1}; */ &:disabled { /* opacity: 50%; */ background-color: ${({ theme }) => theme.bg2}; - color: var(${UI.COLOR_TEXT2}); + color: var(--cow-color-text2); cursor: auto; } ` @@ -312,57 +309,3 @@ export function ButtonDropdownLight({ disabled = false, children, ...rest }: { d ) } - -const ActiveOutlined = styled(ButtonOutlined)` - border: 1px solid; - border-color: ${({ theme }) => theme.primary1}; -` - -const Circle = styled.div` - height: 20px; - width: 20px; - border-radius: 50%; - background-color: ${({ theme }) => theme.primary1}; - display: flex; - align-items: center; - justify-content: center; -` - -const CheckboxWrapper = styled.div` - width: 30px; - padding: 0 10px; - position: absolute; - top: 10px; - right: 10px; -` - -const ResponsiveCheck = styled(Check)` - size: 13px; -` - -export function ButtonRadioChecked({ active = false, children, ...rest }: { active?: boolean } & ButtonProps) { - const theme = useTheme() - - if (!active) { - return ( - - {{children}} - - ) - } else { - return ( - - { - - {children} - - - - - - - } - - ) - } -} diff --git a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/Button.tsx b/libs/ui/src/pure/Button/__fixtures__/Button.tsx similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/Button.tsx rename to libs/ui/src/pure/Button/__fixtures__/Button.tsx diff --git a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonConfirmed.tsx b/libs/ui/src/pure/Button/__fixtures__/ButtonConfirmed.tsx similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonConfirmed.tsx rename to libs/ui/src/pure/Button/__fixtures__/ButtonConfirmed.tsx diff --git a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonDropdown.tsx b/libs/ui/src/pure/Button/__fixtures__/ButtonDropdown.tsx similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonDropdown.tsx rename to libs/ui/src/pure/Button/__fixtures__/ButtonDropdown.tsx diff --git a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonDropdownLight.tsx b/libs/ui/src/pure/Button/__fixtures__/ButtonDropdownLight.tsx similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonDropdownLight.tsx rename to libs/ui/src/pure/Button/__fixtures__/ButtonDropdownLight.tsx diff --git a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonError.tsx b/libs/ui/src/pure/Button/__fixtures__/ButtonError.tsx similarity index 100% rename from apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/ButtonError.tsx rename to libs/ui/src/pure/Button/__fixtures__/ButtonError.tsx diff --git a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/cosmos.decorator.tsx b/libs/ui/src/pure/Button/__fixtures__/cosmos.decorator.tsx similarity index 92% rename from apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/cosmos.decorator.tsx rename to libs/ui/src/pure/Button/__fixtures__/cosmos.decorator.tsx index 8d7181c304..07c95662b4 100644 --- a/apps/cowswap-frontend/src/legacy/components/Button/__fixtures__/cosmos.decorator.tsx +++ b/libs/ui/src/pure/Button/__fixtures__/cosmos.decorator.tsx @@ -2,7 +2,7 @@ import { ReactNode } from 'react' import { Box } from 'rebass' -import styled from 'styled-components/macro' +import styled from 'styled-components' type WrapperParams = { background?: string; children: ReactNode } diff --git a/apps/cowswap-frontend/src/legacy/components/Button/index.tsx b/libs/ui/src/pure/Button/index.tsx similarity index 92% rename from apps/cowswap-frontend/src/legacy/components/Button/index.tsx rename to libs/ui/src/pure/Button/index.tsx index c9ce823a1e..c1641b2a4e 100644 --- a/apps/cowswap-frontend/src/legacy/components/Button/index.tsx +++ b/libs/ui/src/pure/Button/index.tsx @@ -3,13 +3,10 @@ import { HTMLAttributes } from 'react' import { transparentize, darken, lighten } from 'polished' import { ChevronDown, Star } from 'react-feather' import { ButtonProps } from 'rebass/styled-components' -import styled from 'styled-components/macro' +import styled from 'styled-components' -import { RowBetween } from 'legacy/components/Row' -import useTheme from 'legacy/hooks/useTheme' -import { ButtonSize } from 'legacy/theme/enum' - -import { UI } from 'common/constants/theme' +import { RowBetween } from '../Row' +import { ButtonSize } from '../../enum' import { // Import only the basic buttons @@ -51,7 +48,7 @@ export const ButtonPrimary = styled(ButtonPrimaryMod)` } &:disabled { - background-color: var(${UI.COLOR_GREY}); + background-color: var(--cow-color-grey); color: ${({ theme }) => transparentize(0.4, theme.text1)}; background-image: none; border: 0; @@ -168,7 +165,7 @@ export const ButtonOutlined = styled(ButtonOutlinedMod)` export const ButtonConfirmedStyle = styled(ButtonConfirmedStyleMod)` // CSS overrides background-color: ${({ theme }) => theme.disabled}; - color: var(${UI.COLOR_TEXT1}); + color: var(--cow-color-text1); background-image: none; border: 0; cursor: auto; @@ -180,14 +177,14 @@ export const ButtonConfirmedStyle = styled(ButtonConfirmedStyleMod)` export const ButtonErrorStyle = styled(ButtonPrimary)` // CSS overrides background: ${({ theme }) => theme.red1}; - color: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(--cow-container-bg-01); transition: background 0.15s ease-in-out; &:focus, &:hover, &:active { background: ${({ theme }) => theme.red1}; - color: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(--cow-container-bg-01); } &:hover { @@ -270,10 +267,9 @@ export const ButtonStar = ({ stroke, ...rest }: { fill?: string; size?: string; stroke: string } & HTMLAttributes) => { - const theme = useTheme() return ( - + ) } diff --git a/libs/ui/src/pure/ExternalLink/index.tsx b/libs/ui/src/pure/ExternalLink/index.tsx new file mode 100644 index 0000000000..fcbc9e5574 --- /dev/null +++ b/libs/ui/src/pure/ExternalLink/index.tsx @@ -0,0 +1,112 @@ +import React, { HTMLProps } from 'react' +import { anonymizeLink } from '@cowprotocol/common-utils' +import { externalLinkAnalytics, outboundLink } from '@cowprotocol/analytics' +import styled from 'styled-components' +import { ExternalLink as LinkIconFeather } from 'react-feather' + +export const StyledLink = styled.a` + text-decoration: none; + cursor: pointer; + color: ${({ theme }) => theme.text3}; + font-weight: 500; + + :hover { + text-decoration: underline; + } + + :focus { + outline: none; + text-decoration: none; + } + + :active { + text-decoration: none; + } +` +const LinkIconWrapper = styled.a` + text-decoration: none; + cursor: pointer; + align-items: center; + justify-content: center; + display: flex; + + :hover { + text-decoration: none; + opacity: 0.7; + } + + :focus { + outline: none; + text-decoration: none; + } + + :active { + text-decoration: none; + } +` +export const LinkIcon = styled(LinkIconFeather)` + height: 16px; + width: 18px; + margin-left: 10px; + stroke: ${({ theme }) => theme.text3}; +` + +export function handleClickExternalLink(event: React.MouseEvent) { + const { target, href } = event.currentTarget + + const anonymizedHref = anonymizeLink(href) + + // don't prevent default, don't redirect if it's a new tab + if (target === '_blank' || event.ctrlKey || event.metaKey) { + outboundLink({ label: anonymizedHref }, () => { + console.debug('Fired outbound link event', anonymizedHref) + }) + } else { + event.preventDefault() + // send a ReactGA event and then trigger a location change + outboundLink({ label: anonymizedHref }, () => { + window.location.href = anonymizedHref + }) + } +} + +/** + * Outbound link that handles firing google analytics events + */ +export function ExternalLink({ + target = '_blank', + href, + rel = 'noopener noreferrer', + onClickOptional, + ...rest +}: Omit, 'as' | 'ref' | 'onClick'> & { + href: string + onClickOptional?: React.MouseEventHandler +}) { + return ( + { + if (onClickOptional) onClickOptional(event) + handleClickExternalLink(event) + externalLinkAnalytics(href) + }} + {...rest} + /> + ) +} + +export function ExternalLinkIcon({ + target = '_blank', + href, + rel = 'noopener noreferrer', + ...rest +}: Omit, 'as' | 'ref' | 'onClick'> & { href: string }) { + return ( + + + + ) +} diff --git a/apps/cowswap-frontend/src/common/pure/FiatAmount/index.tsx b/libs/ui/src/pure/FiatAmount/index.tsx similarity index 68% rename from apps/cowswap-frontend/src/common/pure/FiatAmount/index.tsx rename to libs/ui/src/pure/FiatAmount/index.tsx index eeefd629b4..197b0a1741 100644 --- a/apps/cowswap-frontend/src/common/pure/FiatAmount/index.tsx +++ b/libs/ui/src/pure/FiatAmount/index.tsx @@ -1,13 +1,8 @@ -import styled from 'styled-components/macro' -import { FractionLike, Nullish } from 'types' - -import { LONG_PRECISION } from 'legacy/constants' - -import { AMOUNTS_FORMATTING_FEATURE_FLAG } from 'common/constants/featureFlags' -import { formatFiatAmount } from 'utils/amountFormat' -import { FeatureFlag } from 'utils/featureFlags' -import { FractionUtils } from 'utils/fractionUtils' - +import styled from 'styled-components' +import { FeatureFlag, formatFiatAmount, FractionUtils } from '@cowprotocol/common-utils' +import { AMOUNTS_FORMATTING_FEATURE_FLAG } from '../../consts' +import { FractionLike, Nullish } from '../../types' +import { LONG_PRECISION } from '@cowprotocol/common-const' export interface FiatAmountProps { amount: Nullish accurate?: boolean diff --git a/apps/cowswap-frontend/src/legacy/components/Loader/index.tsx b/libs/ui/src/pure/Loader/index.tsx similarity index 82% rename from apps/cowswap-frontend/src/legacy/components/Loader/index.tsx rename to libs/ui/src/pure/Loader/index.tsx index e881d36747..35a2682f24 100644 --- a/apps/cowswap-frontend/src/legacy/components/Loader/index.tsx +++ b/libs/ui/src/pure/Loader/index.tsx @@ -1,4 +1,4 @@ -import styled, { keyframes } from 'styled-components/macro' +import styled, { keyframes } from 'styled-components' const rotate = keyframes` from { @@ -22,15 +22,7 @@ export const StyledSVG = styled.svg<{ size: string; stroke?: string }>` * Takes in custom size and stroke for circle color, default to primary color as fill, * need ...rest for layered styles on top */ -export default function Loader({ - size = '16px', - stroke, - ...rest -}: { - size?: string - stroke?: string - [k: string]: any -}) { +export function Loader({ size = '16px', stroke, ...rest }: { size?: string; stroke?: string; [k: string]: any }) { return ( ` visibility: ${(props) => (props.show ? 'visible' : 'hidden')}; opacity: ${(props) => (props.show ? 1 : 0)}; transition: visibility 150ms linear, opacity 150ms linear; - /* color: var(${UI.COLOR_TEXT2}); */ - /* MOD */ - color: var(${UI.COLOR_TEXT1}); - background: var(${UI.COLOR_CONTAINER_BG_01}); + color: var(--cow-color-text1); + background: var(--cow-container-bg-01); border: 1px solid ${({ theme }) => theme.bg3}; box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.9, theme.shadow1)}; border-radius: 8px; @@ -45,7 +38,7 @@ export const Arrow = styled.div` content: ''; border: 1px solid ${({ theme }) => theme.bg3}; transform: rotate(45deg); - background: var(${UI.COLOR_CONTAINER_BG_01}); + background: var(--cow-container-bg-01); } &.arrow-top { @@ -125,7 +118,14 @@ export default function Popover({ const updateCallback = useCallback(() => { update && update() }, [update]) - useInterval(updateCallback, show ? 100 : null) + + useEffect(() => { + if (!show) return + + const interval = setInterval(updateCallback, 100) + + return () => clearInterval(interval) + }, []) return ( <> diff --git a/apps/cowswap-frontend/src/legacy/components/Popover/index.tsx b/libs/ui/src/pure/Popover/index.tsx similarity index 96% rename from apps/cowswap-frontend/src/legacy/components/Popover/index.tsx rename to libs/ui/src/pure/Popover/index.tsx index 2ed7e6582e..9142cc2a6a 100644 --- a/apps/cowswap-frontend/src/legacy/components/Popover/index.tsx +++ b/libs/ui/src/pure/Popover/index.tsx @@ -1,5 +1,5 @@ import { transparentize } from 'polished' -import styled from 'styled-components/macro' +import styled from 'styled-components' import PopoverMod, { Arrow as ArrowMod, PopoverContainer as PopoverContainerMod } from './PopoverMod' import { PopoverProps } from './PopoverMod' diff --git a/apps/cowswap-frontend/src/legacy/components/Row/index.tsx b/libs/ui/src/pure/Row/index.tsx similarity index 91% rename from apps/cowswap-frontend/src/legacy/components/Row/index.tsx rename to libs/ui/src/pure/Row/index.tsx index e84ba5abce..d2412393a5 100644 --- a/apps/cowswap-frontend/src/legacy/components/Row/index.tsx +++ b/libs/ui/src/pure/Row/index.tsx @@ -1,7 +1,7 @@ import { Box } from 'rebass/styled-components' -import styled from 'styled-components/macro' +import styled from 'styled-components' -const Row = styled(Box)<{ +export const Row = styled(Box)<{ width?: string align?: string justify?: string @@ -42,5 +42,3 @@ export const RowFixed = styled(Row)<{ gap?: string; justify?: string }>` width: fit-content; margin: ${({ gap }) => gap && `-${gap}`}; ` - -export default Row diff --git a/libs/ui/src/pure/SelectDropdown/index.tsx b/libs/ui/src/pure/SelectDropdown/index.tsx new file mode 100644 index 0000000000..a3dca19c9c --- /dev/null +++ b/libs/ui/src/pure/SelectDropdown/index.tsx @@ -0,0 +1,29 @@ +import styled from 'styled-components' + +export const SelectDropdown = styled.select` + border-radius: 12px; + padding: 8px 34px 8px 8px; + border-radius: 12px; + appearance: none; + cursor: pointer; + transition: background 0.2s ease-in-out; + width: 100%; + outline: none; + border: 1px solid var(--cow-color-border); + color: var(--cow-color-text1); + background: linear-gradient(45deg, transparent 50%, var(--cow-color-lightBlue) 50%) calc(100% - 13px) calc(13px) / 5px + 5px no-repeat, + linear-gradient(135deg, var(--cow-color-lightBlue) 50%, transparent 50%) calc(100% - 8px) calc(13px) / 5px 5px + no-repeat, + linear-gradient(to right, var(--cow-color-lightBlue-opacity-90), var(--cow-color-lightBlue-opacity-90)) 100% 0 / + 26px 100% no-repeat; + + &:hover { + background: linear-gradient(45deg, transparent 50%, var(--cow-color-lightBlue) 50%) calc(100% - 13px) calc(13px) / + 5px 5px no-repeat, + linear-gradient(135deg, var(--cow-color-lightBlue) 50%, transparent 50%) calc(100% - 8px) calc(13px) / 5px 5px + no-repeat, + linear-gradient(to right, var(--cow-color-lightBlue-opacity-80), var(--cow-color-lightBlue-opacity-80)) 100% 0 / + 26px 100% no-repeat; + } +` diff --git a/apps/cowswap-frontend/src/common/pure/TokenAmount/index.tsx b/libs/ui/src/pure/TokenAmount/index.tsx similarity index 78% rename from apps/cowswap-frontend/src/common/pure/TokenAmount/index.tsx rename to libs/ui/src/pure/TokenAmount/index.tsx index 0709e42ad8..6046121b82 100644 --- a/apps/cowswap-frontend/src/common/pure/TokenAmount/index.tsx +++ b/libs/ui/src/pure/TokenAmount/index.tsx @@ -1,14 +1,12 @@ -import { darken, transparentize } from 'polished' -import styled from 'styled-components/macro' -import { FractionLike, Nullish } from 'types' - -import { LONG_PRECISION } from 'legacy/constants' +import { LONG_PRECISION } from '@cowprotocol/common-const' +import { formatTokenAmount, FractionUtils } from '@cowprotocol/common-utils' +import { FeatureFlag } from '@cowprotocol/common-utils' -import { AMOUNTS_FORMATTING_FEATURE_FLAG } from 'common/constants/featureFlags' -import { TokenSymbol, TokenSymbolProps } from 'common/pure/TokenSymbol' -import { formatTokenAmount } from 'utils/amountFormat' -import { FeatureFlag } from 'utils/featureFlags' -import { FractionUtils } from 'utils/fractionUtils' +import { darken, transparentize } from 'polished' +import styled from 'styled-components' +import { FractionLike, Nullish } from '../../types' +import { TokenSymbol, TokenSymbolProps } from '../TokenSymbol' +import { AMOUNTS_FORMATTING_FEATURE_FLAG } from '../../consts' export const Wrapper = styled.span<{ highlight: boolean; lowVolumeWarning?: boolean }>` background: ${({ highlight }) => (highlight ? 'rgba(196,18,255,0.4)' : '')}; diff --git a/apps/cowswap-frontend/src/common/pure/TokenSymbol/index.tsx b/libs/ui/src/pure/TokenSymbol/index.tsx similarity index 86% rename from apps/cowswap-frontend/src/common/pure/TokenSymbol/index.tsx rename to libs/ui/src/pure/TokenSymbol/index.tsx index 0ee331b0d0..9c18a579e9 100644 --- a/apps/cowswap-frontend/src/common/pure/TokenSymbol/index.tsx +++ b/libs/ui/src/pure/TokenSymbol/index.tsx @@ -1,8 +1,7 @@ import { Currency } from '@uniswap/sdk-core' -import { Nullish } from 'types' - -import { formatSymbol } from 'utils/format' +import { Nullish } from '../../types' +import { formatSymbol } from '@cowprotocol/common-utils' export type TokenSymbolProps = { token: Nullish> diff --git a/apps/cowswap-frontend/src/legacy/components/Tooltip/index.tsx b/libs/ui/src/pure/Tooltip/index.tsx similarity index 91% rename from apps/cowswap-frontend/src/legacy/components/Tooltip/index.tsx rename to libs/ui/src/pure/Tooltip/index.tsx index c93f8b714f..c5d1b41a1d 100644 --- a/apps/cowswap-frontend/src/legacy/components/Tooltip/index.tsx +++ b/libs/ui/src/pure/Tooltip/index.tsx @@ -1,8 +1,8 @@ import { ReactNode, useCallback, useState } from 'react' -import styled from 'styled-components/macro' +import styled from 'styled-components' -import Popover, { PopoverProps } from 'legacy/components/Popover' +import Popover, { PopoverProps } from '../Popover' export const TooltipContainer = styled.div` max-width: 300px; @@ -23,7 +23,7 @@ interface TooltipContentProps extends Omit{text}} {...rest} /> } diff --git a/libs/ui/src/types.ts b/libs/ui/src/types.ts new file mode 100644 index 0000000000..d607182ed4 --- /dev/null +++ b/libs/ui/src/types.ts @@ -0,0 +1,14 @@ +import { Currency, CurrencyAmount, Fraction, Price } from '@uniswap/sdk-core' + +export type Writeable = { -readonly [P in keyof T]: T[P] } + +export type Nullish = T | null | undefined + +export type FractionLike = Fraction | Price | CurrencyAmount + +export type ComposableCowInfo = { + id?: string + parentId?: string + isVirtualPart?: boolean + isTheLastPart?: boolean +} diff --git a/libs/ui/vite.config.ts b/libs/ui/vite.config.ts index 8f939a4cb4..15b6616ffe 100644 --- a/libs/ui/vite.config.ts +++ b/libs/ui/vite.config.ts @@ -1,14 +1,16 @@ /// import { joinPathFragments } from '@nx/devkit' -import react from '@vitejs/plugin-react' +import react from '@vitejs/plugin-react-swc' import { defineConfig } from 'vite' import dts from 'vite-plugin-dts' import viteTsConfigPaths from 'vite-tsconfig-paths' +import macrosPlugin from 'vite-plugin-babel-macros' export default defineConfig({ cacheDir: '../../../node_modules/.vite/ui', plugins: [ + macrosPlugin(), dts({ entryRoot: 'src', tsConfigFilePath: joinPathFragments(__dirname, 'tsconfig.lib.json'), diff --git a/libs/wallet/.babelrc b/libs/wallet/.babelrc new file mode 100644 index 0000000000..ef4889c1ab --- /dev/null +++ b/libs/wallet/.babelrc @@ -0,0 +1,20 @@ +{ + "presets": [ + [ + "@nx/react/babel", + { + "runtime": "automatic", + "useBuiltIns": "usage" + } + ] + ], + "plugins": [ + [ + "styled-components", + { + "pure": true, + "ssr": true + } + ] + ] +} diff --git a/libs/wallet/.eslintrc.json b/libs/wallet/.eslintrc.json new file mode 100644 index 0000000000..231aaa5f83 --- /dev/null +++ b/libs/wallet/.eslintrc.json @@ -0,0 +1,21 @@ +{ + "extends": ["plugin:@nx/react", "../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "rules": { + "@typescript-eslint/no-explicit-any": "off" + }, + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/libs/wallet/README.md b/libs/wallet/README.md new file mode 100644 index 0000000000..456644fc55 --- /dev/null +++ b/libs/wallet/README.md @@ -0,0 +1 @@ +# Wallet diff --git a/libs/wallet/jest.config.ts b/libs/wallet/jest.config.ts new file mode 100644 index 0000000000..aa0b14146f --- /dev/null +++ b/libs/wallet/jest.config.ts @@ -0,0 +1,11 @@ +/* eslint-disable */ +export default { + displayName: 'wallet', + preset: '../../jest.preset.js', + transform: { + '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', + '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/libs/wallet', +} diff --git a/libs/wallet/package.json b/libs/wallet/package.json new file mode 100644 index 0000000000..009a1fcbf3 --- /dev/null +++ b/libs/wallet/package.json @@ -0,0 +1,12 @@ +{ + "name": "@cowprotocol/wallet", + "version": "0.0.1", + "main": "./index.js", + "types": "./index.d.ts", + "exports": { + ".": { + "import": "./index.mjs", + "require": "./index.js" + } + } +} diff --git a/libs/wallet/project.json b/libs/wallet/project.json new file mode 100644 index 0000000000..f5415c7955 --- /dev/null +++ b/libs/wallet/project.json @@ -0,0 +1,46 @@ +{ + "name": "@cowprotocol/wallet", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/wallet/src", + "projectType": "library", + "tags": [], + "targets": { + "lint": { + "executor": "@nx/linter:eslint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/wallet/**/*.{ts,tsx,js,jsx}"] + } + }, + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "dist/libs/wallet" + }, + "configurations": { + "development": { + "mode": "development" + }, + "production": { + "mode": "production" + } + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/wallet/jest.config.ts", + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "codeCoverage": true + } + } + } + } +} diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/alpha.svg b/libs/wallet/src/api/assets/alpha.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/alpha.svg rename to libs/wallet/src/api/assets/alpha.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/ambire.svg b/libs/wallet/src/api/assets/ambire.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/ambire.svg rename to libs/wallet/src/api/assets/ambire.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/arrow-right-white.png b/libs/wallet/src/api/assets/arrow-right-white.png similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/arrow-right-white.png rename to libs/wallet/src/api/assets/arrow-right-white.png diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/arrow-right.svg b/libs/wallet/src/api/assets/arrow-right.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/arrow-right.svg rename to libs/wallet/src/api/assets/arrow-right.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/coinbase.svg b/libs/wallet/src/api/assets/coinbase.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/coinbase.svg rename to libs/wallet/src/api/assets/coinbase.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/keystone.svg b/libs/wallet/src/api/assets/keystone.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/keystone.svg rename to libs/wallet/src/api/assets/keystone.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/ledger.svg b/libs/wallet/src/api/assets/ledger.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/ledger.svg rename to libs/wallet/src/api/assets/ledger.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/metamask.png b/libs/wallet/src/api/assets/metamask.png similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/metamask.png rename to libs/wallet/src/api/assets/metamask.png diff --git a/libs/wallet/src/api/assets/safe-logo.svg b/libs/wallet/src/api/assets/safe-logo.svg new file mode 100644 index 0000000000..9044e15fc0 --- /dev/null +++ b/libs/wallet/src/api/assets/safe-logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/tally.svg b/libs/wallet/src/api/assets/tally.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/tally.svg rename to libs/wallet/src/api/assets/tally.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/trezor.svg b/libs/wallet/src/api/assets/trezor.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/trezor.svg rename to libs/wallet/src/api/assets/trezor.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/trust.svg b/libs/wallet/src/api/assets/trust.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/trust.svg rename to libs/wallet/src/api/assets/trust.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/wallet-connect-v2.png b/libs/wallet/src/api/assets/wallet-connect-v2.png similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/wallet-connect-v2.png rename to libs/wallet/src/api/assets/wallet-connect-v2.png diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/walletConnectIcon.svg b/libs/wallet/src/api/assets/walletConnectIcon.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/walletConnectIcon.svg rename to libs/wallet/src/api/assets/walletConnectIcon.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/assets/zengo.svg b/libs/wallet/src/api/assets/zengo.svg similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/assets/zengo.svg rename to libs/wallet/src/api/assets/zengo.svg diff --git a/apps/cowswap-frontend/src/modules/wallet/api/container/Identicon/index.tsx b/libs/wallet/src/api/container/Identicon/index.tsx similarity index 86% rename from apps/cowswap-frontend/src/modules/wallet/api/container/Identicon/index.tsx rename to libs/wallet/src/api/container/Identicon/index.tsx index e395c71c2f..0affb6aac9 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/container/Identicon/index.tsx +++ b/libs/wallet/src/api/container/Identicon/index.tsx @@ -1,12 +1,11 @@ import React from 'react' import { useLayoutEffect, useMemo, useRef, useState } from 'react' -import jazzicon from '@metamask/jazzicon' - -import useENSAvatar from 'legacy/hooks/useENSAvatar' +import { useWalletInfo } from '../../hooks' +import { Identicon as IdenticonPure } from '../../pure/Identicon' +import { useENSAvatar } from '@cowprotocol/ens' -import { useWalletInfo } from 'modules/wallet' -import { Identicon as IdenticonPure } from 'modules/wallet/api/pure/Identicon' +import jazzicon from '@metamask/jazzicon' export interface IdenticonProps { size?: number diff --git a/apps/cowswap-frontend/src/modules/wallet/api/hooks.ts b/libs/wallet/src/api/hooks.ts similarity index 85% rename from apps/cowswap-frontend/src/modules/wallet/api/hooks.ts rename to libs/wallet/src/api/hooks.ts index a39f16ae0e..d1a0f3d90d 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/hooks.ts +++ b/libs/wallet/src/api/hooks.ts @@ -1,8 +1,9 @@ import { useAtomValue } from 'jotai' -import { GnosisSafeInfo, useIsSafeApp, WalletDetails, WalletInfo } from 'modules/wallet' - import { gnosisSafeInfoAtom, walletDetailsAtom, walletDisplayedAddress, walletInfoAtom } from './state' +import { GnosisSafeInfo, WalletDetails, WalletInfo } from './types' + +import { useIsSafeApp } from '../web3-react/hooks/useWalletMetadata' export function useWalletInfo(): WalletInfo { return useAtomValue(walletInfoAtom) diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/ConnectWalletOption/index.tsx b/libs/wallet/src/api/pure/ConnectWalletOption/index.tsx similarity index 95% rename from apps/cowswap-frontend/src/modules/wallet/api/pure/ConnectWalletOption/index.tsx rename to libs/wallet/src/api/pure/ConnectWalletOption/index.tsx index dcda3ee218..8930e6def5 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/ConnectWalletOption/index.tsx +++ b/libs/wallet/src/api/pure/ConnectWalletOption/index.tsx @@ -3,10 +3,7 @@ import React from 'react' import { darken, lighten } from 'polished' import styled from 'styled-components/macro' -import { MouseoverTooltip } from 'legacy/components/Tooltip' -import { ExternalLink } from 'legacy/theme' - -import { UI } from 'common/constants/theme' +import { MouseoverTooltip, ExternalLink } from '@cowprotocol/ui' const InfoCard = styled.button<{ isActive?: boolean }>` background-color: ${({ theme, isActive }) => (isActive ? theme.bg3 : theme.bg2)}; @@ -86,7 +83,7 @@ export const HeaderText = styled.div` ` const SubHeader = styled.div` - color: var(${UI.COLOR_TEXT1}); + color: var(--cow-color-text1); margin-top: 10px; font-size: 12px; ` diff --git a/apps/cowswap-frontend/src/modules/wallet/api/pure/Identicon/index.tsx b/libs/wallet/src/api/pure/Identicon/index.tsx similarity index 91% rename from apps/cowswap-frontend/src/modules/wallet/api/pure/Identicon/index.tsx rename to libs/wallet/src/api/pure/Identicon/index.tsx index 0a868e7987..cc9fe088f9 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/pure/Identicon/index.tsx +++ b/libs/wallet/src/api/pure/Identicon/index.tsx @@ -2,14 +2,12 @@ import React from 'react' import styled from 'styled-components/macro' -import { UI } from 'common/constants/theme' - export const StyledIdenticon = styled.div` height: 1rem; width: 1rem; border-radius: 1.125rem; // background-color: ${({ theme }) => theme.bg4}; - background-color: var(${UI.COLOR_CONTAINER_BG_01}); // MOD + background-color: var(--cow-container-bg-01); // MOD font-size: initial; ` diff --git a/apps/cowswap-frontend/src/modules/wallet/api/state.ts b/libs/wallet/src/api/state.ts similarity index 87% rename from apps/cowswap-frontend/src/modules/wallet/api/state.ts rename to libs/wallet/src/api/state.ts index 3246caa096..e0d6251bf0 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/state.ts +++ b/libs/wallet/src/api/state.ts @@ -1,11 +1,8 @@ import { atom } from 'jotai' import { atomWithStorage } from 'jotai/utils' -import { shortenAddress } from 'legacy/utils' - -import { getCurrentChainIdFromUrl } from 'utils/getCurrentChainIdFromUrl' - import { GnosisSafeInfo, WalletDetails, WalletInfo } from './types' +import { getCurrentChainIdFromUrl, shortenAddress } from '@cowprotocol/common-utils' export const walletInfoAtom = atom({ chainId: getCurrentChainIdFromUrl() }) diff --git a/apps/cowswap-frontend/src/modules/wallet/api/types.ts b/libs/wallet/src/api/types.ts similarity index 97% rename from apps/cowswap-frontend/src/modules/wallet/api/types.ts rename to libs/wallet/src/api/types.ts index c0e936ce63..191afa122f 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/types.ts +++ b/libs/wallet/src/api/types.ts @@ -7,7 +7,6 @@ export enum ConnectionType { COINBASE_WALLET = 'COINBASE_WALLET', WALLET_CONNECT = 'WALLET_CONNECT', WALLET_CONNECT_V2 = 'WALLET_CONNECT_V2', - FORTMATIC = 'FORTMATIC', NETWORK = 'NETWORK', GNOSIS_SAFE = 'GNOSIS_SAFE', ZENGO = 'ZENGO', diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/accountsLoaders.ts b/libs/wallet/src/api/utils/accountsLoaders.ts similarity index 66% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/accountsLoaders.ts rename to libs/wallet/src/api/utils/accountsLoaders.ts index b25ed641fb..d31813c446 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/AccountSelectorModal/accountsLoaders.ts +++ b/libs/wallet/src/api/utils/accountsLoaders.ts @@ -1,6 +1,6 @@ -import { ConnectionType } from '../../../api/types' -import { HardWareWallet } from '../../connection' -import { trezorConnection } from '../../connection/trezor' +import { trezorConnection } from '../../web3-react/connection/trezor' +import { HardWareWallet } from '../../web3-react/utils/getIsHardWareWallet' +import { ConnectionType } from '../../api/types' interface WalletAccountsLoader { getAccounts(): string[] | null diff --git a/apps/cowswap-frontend/src/modules/wallet/api/utils/connection.ts b/libs/wallet/src/api/utils/connection.ts similarity index 94% rename from apps/cowswap-frontend/src/modules/wallet/api/utils/connection.ts rename to libs/wallet/src/api/utils/connection.ts index 3c8396afe5..0c67be1adc 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/utils/connection.ts +++ b/libs/wallet/src/api/utils/connection.ts @@ -1,5 +1,4 @@ import CoinbaseWalletIcon from '../assets/coinbase.svg' -import FortmaticIcon from '../assets/formatic.png' import KeystoneImage from '../assets/keystone.svg' import LedgerIcon from '../assets/ledger.svg' import TallyIcon from '../assets/tally.svg' @@ -14,7 +13,6 @@ const connectionTypeToName: Record = { [ConnectionType.COINBASE_WALLET]: 'Coinbase Wallet', [ConnectionType.WALLET_CONNECT]: 'WalletConnect', [ConnectionType.WALLET_CONNECT_V2]: 'WalletConnect v2', - [ConnectionType.FORTMATIC]: 'Fortmatic', [ConnectionType.NETWORK]: 'Network', [ConnectionType.GNOSIS_SAFE]: 'Safe', [ConnectionType.ZENGO]: 'Zengo', @@ -38,7 +36,6 @@ const connectionTypeToIcon: Record = { [ConnectionType.AMBIRE]: IDENTICON_KEY, [ConnectionType.ALPHA]: IDENTICON_KEY, [ConnectionType.COINBASE_WALLET]: CoinbaseWalletIcon, - [ConnectionType.FORTMATIC]: FortmaticIcon, [ConnectionType.TRUST]: TrustIcon, [ConnectionType.TALLY]: TallyIcon, [ConnectionType.LEDGER]: LedgerIcon, @@ -66,7 +63,7 @@ export function getIsMetaMask(): boolean { } export function getIsCoinbaseWallet(): boolean { - return window.ethereum?.isCoinbaseWallet ?? false + return (window.ethereum as { isCoinbaseWallet: boolean })?.isCoinbaseWallet ?? false } export function getIsAmbireWallet(name: string | undefined): boolean { diff --git a/apps/cowswap-frontend/src/modules/wallet/api/utils/getHwAccount.ts b/libs/wallet/src/api/utils/getHwAccount.ts similarity index 86% rename from apps/cowswap-frontend/src/modules/wallet/api/utils/getHwAccount.ts rename to libs/wallet/src/api/utils/getHwAccount.ts index 9c61de9b53..37780bfa50 100644 --- a/apps/cowswap-frontend/src/modules/wallet/api/utils/getHwAccount.ts +++ b/libs/wallet/src/api/utils/getHwAccount.ts @@ -1,4 +1,4 @@ -import { jotaiStore } from 'jotaiStore' +import { jotaiStore } from '@cowprotocol/core' import { hwAccountIndexAtom } from '../state' diff --git a/apps/cowswap-frontend/src/modules/wallet/api/utils/getWalletType.ts b/libs/wallet/src/api/utils/getWalletType.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/utils/getWalletType.ts rename to libs/wallet/src/api/utils/getWalletType.ts diff --git a/apps/cowswap-frontend/src/modules/wallet/api/utils/getWalletTypeLabel.ts b/libs/wallet/src/api/utils/getWalletTypeLabel.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/api/utils/getWalletTypeLabel.ts rename to libs/wallet/src/api/utils/getWalletTypeLabel.ts diff --git a/libs/wallet/src/assets.ts b/libs/wallet/src/assets.ts new file mode 100644 index 0000000000..086a83a452 --- /dev/null +++ b/libs/wallet/src/assets.ts @@ -0,0 +1,5 @@ +import CoinbaseWalletIcon from './api/assets/coinbase.svg' +import WalletConnectIcon from './api/assets/walletConnectIcon.svg' +import MetaMaskLogo from './api/assets/metamask.png' + +export { CoinbaseWalletIcon, WalletConnectIcon, MetaMaskLogo } diff --git a/apps/cowswap-frontend/src/modules/wallet/constants.ts b/libs/wallet/src/constants.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/constants.ts rename to libs/wallet/src/constants.ts diff --git a/libs/wallet/src/index.ts b/libs/wallet/src/index.ts new file mode 100644 index 0000000000..a7c359114e --- /dev/null +++ b/libs/wallet/src/index.ts @@ -0,0 +1,59 @@ +import './types.d.ts' + +export * from './api/types' +export * from './web3-react/types' +export * from './assets' + +// Hooks +export * from './api/hooks' +export * from './web3-react/hooks/useWalletMetadata' +export * from './web3-react/hooks/useIsWalletConnect' +export * from './web3-react/hooks/useSafeAppsSdk' +export * from './web3-react/hooks/useIsSmartContractWallet' + +// Updater +export * from './web3-react/updater' + +// Components +export * from './api/container/Identicon' +export * from './web3-react/pure/AccountIndexSelect' + +// Utils +export * from './api/utils/connection' +export * from './web3-react/utils/getIsHardWareWallet' +export { accountsLoaders } from './api/utils/accountsLoaders' +export { isChainAllowed } from './web3-react/utils/isChainAllowed' +export { getWeb3ReactConnection } from './web3-react/utils/getWeb3ReactConnection' +export { switchChain } from './web3-react/utils/switchChain' + +// Connectors +export { injectedWidgetConnection } from './web3-react/connection/injectedWidget' +export { networkConnection } from './web3-react/connection/network' +export { gnosisSafeConnection } from './web3-react/connection/safe' + +// Connect options +export { + InjectedOption, + InstallMetaMaskOption, + MetaMaskOption, + OpenMetaMaskMobileOption, +} from './web3-react/connection/injected' + +export { InstallKeystoneOption, KeystoneOption } from './web3-react/connection/keystone' +export { LedgerOption } from './web3-react/connection/ledger' +export { TrezorOption } from './web3-react/connection/trezor' +export { TrustWalletOption } from './web3-react/connection/trust' +export { WalletConnectOption } from './web3-react/connection/walletConnect' +export { WalletConnectV2Option } from './web3-react/connection/walletConnectV2' +export { AlphaOption } from './web3-react/connection/alpha' +export { AmbireOption } from './web3-react/connection/ambire' +export { CoinbaseWalletOption } from './web3-react/connection/coinbase' + +// State +// TODO: this export is discussable, however it's already used outside +export * from './api/state' +export * from './api/state' + +// Connections +export { injectedConnection } from './web3-react/connection/injected' +export { walletConnectConnection } from './web3-react/connection/walletConnect' diff --git a/libs/wallet/src/types.d.ts b/libs/wallet/src/types.d.ts new file mode 100644 index 0000000000..a3faf97029 --- /dev/null +++ b/libs/wallet/src/types.d.ts @@ -0,0 +1,3 @@ +declare module '@metamask/jazzicon' { + export default function (diameter: number, seed: number): HTMLElement +} diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/alpha.tsx b/libs/wallet/src/web3-react/connection/alpha.tsx similarity index 58% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/connection/alpha.tsx rename to libs/wallet/src/web3-react/connection/alpha.tsx index f876343bdf..6226b8ad17 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/alpha.tsx +++ b/libs/wallet/src/web3-react/connection/alpha.tsx @@ -1,10 +1,8 @@ -import { default as AlphaImage } from 'modules/wallet/api/assets/alpha.svg' -import { getIsAlphaWallet } from 'modules/wallet/api/utils/connection' - +import { default as AlphaImage } from '../../api/assets/alpha.svg' import { ConnectionType } from '../../api/types' +import { getIsAlphaWallet } from '../../api/utils/connection' import { WalletConnectLabeledOption } from '../containers/WalletConnectLabeledOption' - -import { TryActivation } from '.' +import { ConnectionOptionProps } from '../types' const alphaOption = { color: '#4196FC', @@ -12,9 +10,10 @@ const alphaOption = { id: 'alpha', } -export function AlphaOption({ tryActivation }: { tryActivation: TryActivation }) { +export function AlphaOption({ selectedWallet, tryActivation }: ConnectionOptionProps) { return ( ( (actions) => new AsyncConnector( @@ -57,14 +48,8 @@ export const coinbaseWalletConnection: Web3ReactConnection = { type: ConnectionType.COINBASE_WALLET, } -export function OpenCoinbaseWalletOption() { - const selectedWallet = useSelectedWallet() - const isActive = selectedWallet === ConnectionType.COINBASE_WALLET - return -} - -export function CoinbaseWalletOption({ tryActivation }: { tryActivation: TryActivation }) { - const isActive = useIsActiveWallet(coinbaseWalletConnection) +export function CoinbaseWalletOption({ tryActivation, selectedWallet }: ConnectionOptionProps) { + const isActive = useIsActiveConnection(selectedWallet, coinbaseWalletConnection) return ( MetaMask} - link={METAMASK_DEEP_LINK + window.location} - /> + ) } -export function MetaMaskOption({ tryActivation }: { tryActivation: TryActivation }) { - // const isActive = injectedConnection.hooks.useIsActive() - const isActive = useIsActiveWallet(injectedConnection) // MOD +export function MetaMaskOption({ selectedWallet, tryActivation }: ConnectionOptionProps) { + const isActive = useIsActiveConnection(selectedWallet, injectedConnection) return ( } -export function KeystoneOption({ tryActivation }: { tryActivation: TryActivation }) { - const isActive = useIsActiveWallet(keystoneConnection) +export function KeystoneOption({ selectedWallet, tryActivation }: ConnectionOptionProps) { + const isActive = useIsActiveConnection(selectedWallet, keystoneConnection) return ( void }) { - const isActive = useIsActiveWallet(ledgerConnection) +export function LedgerOption({ selectedWallet, tryActivation }: ConnectionOptionProps) { + const isActive = useIsActiveConnection(selectedWallet, ledgerConnection) return ( ( diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/tally.tsx b/libs/wallet/src/web3-react/connection/tally.tsx similarity index 58% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/connection/tally.tsx rename to libs/wallet/src/web3-react/connection/tally.tsx index 614ce529c5..2692c041da 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connection/tally.tsx +++ b/libs/wallet/src/web3-react/connection/tally.tsx @@ -1,15 +1,13 @@ import { initializeConnector } from '@web3-react/core' import { Connector } from '@web3-react/types' -import { useIsActiveWallet } from 'legacy/hooks/useIsActiveWallet' - -import { ConnectionType } from 'modules/wallet' -import { default as TallyImage } from 'modules/wallet/api/assets/tally.svg' -import { ConnectWalletOption } from 'modules/wallet/api/pure/ConnectWalletOption' -import { getConnectionName } from 'modules/wallet/api/utils/connection' -import { InjectedWallet } from 'modules/wallet/web3-react/connectors/Injected' - -import { Web3ReactConnection } from '../types' +import { default as TallyImage } from '../../api/assets/tally.svg' +import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' +import { ConnectionType } from '../../api/types' +import { getConnectionName } from '../../api/utils/connection' +import { InjectedWallet } from '../connectors/Injected' +import { ConnectionOptionProps, Web3ReactConnection } from '../types' +import { useIsActiveConnection } from '../hooks/useIsActiveConnection' const WALLET_LINK = 'https://chrome.google.com/webstore/detail/taho/eajafomhmkipbjmfmhebemolkcicgfmd' const BASE_PROPS = { @@ -32,8 +30,8 @@ export const tallyWalletConnection: Web3ReactConnection = { type: ConnectionType.TALLY, } -export function TallyWalletOption({ tryActivation }: { tryActivation: (connector: Connector) => void }) { - const isActive = useIsActiveWallet(tallyWalletConnection) +export function TallyWalletOption({ selectedWallet, tryActivation }: ConnectionOptionProps) { + const isActive = useIsActiveConnection(selectedWallet, tallyWalletConnection) return ( = { type: ConnectionType.TREZOR, } -export function TrezorOption({ tryActivation }: { tryActivation: (connector: Connector) => void }) { - const isActive = useIsActiveWallet(trezorConnection) +export function TrezorOption({ selectedWallet, tryActivation }: ConnectionOptionProps) { + const isActive = useIsActiveConnection(selectedWallet, trezorConnection) return ( void }) { - const isActive = useIsActiveWallet(trustWalletConnection) +export function TrustWalletInjectedOption({ selectedWallet, tryActivation }: ConnectionOptionProps) { + const isActive = useIsActiveConnection(selectedWallet, trustWalletConnection) return ( void }) { +export function TrustWalletWCOption({ selectedWallet, tryActivation }: ConnectionOptionProps) { return ( boolean diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/LedgerConnector.tsx b/libs/wallet/src/web3-react/connectors/LedgerConnector.tsx similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/LedgerConnector.tsx rename to libs/wallet/src/web3-react/connectors/LedgerConnector.tsx diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/TrezorProvider.ts b/libs/wallet/src/web3-react/connectors/TrezorConnector/TrezorProvider.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/TrezorProvider.ts rename to libs/wallet/src/web3-react/connectors/TrezorConnector/TrezorProvider.ts diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/getAccountsList.ts b/libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts similarity index 97% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/getAccountsList.ts rename to libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts index f08d0deae1..be5123c9a3 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/getAccountsList.ts +++ b/libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts @@ -1,7 +1,7 @@ import { publicToAddress } from 'ethereumjs-util' import HDNode from 'hdkey' -import { TREZOR_DERIVATION_PATH } from 'modules/wallet/api/utils/getHwAccount' +import { TREZOR_DERIVATION_PATH } from '../../../api/utils/getHwAccount' import type { TrezorConnect } from '@trezor/connect-web' diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/index.ts b/libs/wallet/src/web3-react/connectors/TrezorConnector/index.ts similarity index 97% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/index.ts rename to libs/wallet/src/web3-react/connectors/TrezorConnector/index.ts index 5091f5a351..719b0b33b5 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/index.ts +++ b/libs/wallet/src/web3-react/connectors/TrezorConnector/index.ts @@ -1,16 +1,14 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Connector } from '@web3-react/types' -import { RPC_URLS } from 'legacy/constants/networks' - -import { getCurrentChainIdFromUrl } from 'utils/getCurrentChainIdFromUrl' - import { TrezorProvider } from './TrezorProvider' import { getHwAccount } from '../../../api/utils/getHwAccount' import type transformTypedData from '@trezor/connect-plugin-ethereum' import type { TrezorConnect } from '@trezor/connect-web' +import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' +import { RPC_URLS } from '@cowprotocol/common-const' const defaultChainId = getCurrentChainIdFromUrl() diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts b/libs/wallet/src/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts similarity index 95% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts rename to libs/wallet/src/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts index 4dd13e7c77..a0d0e6f834 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts +++ b/libs/wallet/src/web3-react/connectors/TrezorConnector/sendTransactionHandler.ts @@ -3,13 +3,10 @@ import { JsonRpcProvider } from '@ethersproject/providers' import { serialize } from '@ethersproject/transactions' import { EthereumTransaction } from '@trezor/connect' -import { jotaiStore } from 'jotaiStore' - -import { gasPriceAtom } from 'modules/gasPirce' - import { getHwAccount } from '../../../api/utils/getHwAccount' import type { TrezorConnect } from '@trezor/connect-web' +import { gasPriceAtom, jotaiStore } from '@cowprotocol/core' // TODO: use API or Oracle for gas price const DEFAULT_GOERLI_GAS_PRICE = 40 * 10 ** 9 // 40 GWEI diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/signTypedDataHandler.ts b/libs/wallet/src/web3-react/connectors/TrezorConnector/signTypedDataHandler.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/TrezorConnector/signTypedDataHandler.ts rename to libs/wallet/src/web3-react/connectors/TrezorConnector/signTypedDataHandler.ts diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/WalletConnectV2Connector/index.tsx b/libs/wallet/src/web3-react/connectors/WalletConnectV2Connector/index.tsx similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/connectors/WalletConnectV2Connector/index.tsx rename to libs/wallet/src/web3-react/connectors/WalletConnectV2Connector/index.tsx diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/WalletConnectLabeledOption/index.tsx b/libs/wallet/src/web3-react/containers/WalletConnectLabeledOption/index.tsx similarity index 77% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/containers/WalletConnectLabeledOption/index.tsx rename to libs/wallet/src/web3-react/containers/WalletConnectLabeledOption/index.tsx index 3ad6efbb26..90ef09e0c9 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/containers/WalletConnectLabeledOption/index.tsx +++ b/libs/wallet/src/web3-react/containers/WalletConnectLabeledOption/index.tsx @@ -1,20 +1,21 @@ -import { useIsActiveWallet } from 'legacy/hooks/useIsActiveWallet' - -import { useFeatureFlags } from 'common/hooks/featureFlags/useFeatureFlags' - import { ConnectWalletOption } from '../../../api/pure/ConnectWalletOption' import { ConnectionType } from '../../../api/types' import { getConnectionName } from '../../../api/utils/connection' import { WC_DISABLED_TEXT } from '../../../constants' -import { TryActivation } from '../../connection' import { walletConnectConnection } from '../../connection/walletConnect' import { walletConnectConnectionV2 } from '../../connection/walletConnectV2' import { useWalletMetaData } from '../../hooks/useWalletMetadata' +import { useFlags } from 'launchdarkly-react-client-sdk' +import { Connector } from '@web3-react/types' +import { useIsActiveConnection } from '../../hooks/useIsActiveConnection' + +type TryActivation = (connector: Connector) => void interface WalletConnectLabeledOptionProps { connectionType: ConnectionType tryActivation: TryActivation checkWalletName(walletName: string | undefined): boolean + selectedWallet: string | undefined options: { color: string icon: string @@ -27,13 +28,14 @@ export function WalletConnectLabeledOption({ tryActivation, checkWalletName, options, + selectedWallet, }: WalletConnectLabeledOptionProps) { const { walletName } = useWalletMetaData() - const { walletConnectV1Enabled } = useFeatureFlags() + const { walletConnectV1Enabled } = useFlags() const connection = walletConnectV1Enabled ? walletConnectConnection : walletConnectConnectionV2 - const isWalletConnect = useIsActiveWallet(connection) + const isWalletConnect = useIsActiveConnection(selectedWallet, connection) const isActive = isWalletConnect && checkWalletName(walletName) const tooltipText = !isActive && isWalletConnect ? WC_DISABLED_TEXT : null diff --git a/libs/wallet/src/web3-react/hooks/useIsActiveConnection.ts b/libs/wallet/src/web3-react/hooks/useIsActiveConnection.ts new file mode 100644 index 0000000000..211429411b --- /dev/null +++ b/libs/wallet/src/web3-react/hooks/useIsActiveConnection.ts @@ -0,0 +1,16 @@ +import { Web3ReactConnection } from '../types' +import { useWeb3React } from '@web3-react/core' + +export const useIsActiveConnection = (selectedWallet: string | undefined, connection: Web3ReactConnection) => { + const { account } = useWeb3React() + + const isActive = connection.hooks.useIsActive() + + if (!isActive) { + return false + } else if (isActive && !selectedWallet && account) { + return true + } else { + return selectedWallet === connection.type + } +} diff --git a/libs/wallet/src/web3-react/hooks/useIsSmartContractWallet.ts b/libs/wallet/src/web3-react/hooks/useIsSmartContractWallet.ts new file mode 100644 index 0000000000..ae423d2e22 --- /dev/null +++ b/libs/wallet/src/web3-react/hooks/useIsSmartContractWallet.ts @@ -0,0 +1,87 @@ +import { useState, useEffect, useMemo } from 'react' + +import { useWeb3React } from '@web3-react/core' + +import useSWR from 'swr' +import { useAsyncMemo } from 'use-async-memo' +import { useWalletInfo } from '../../api/hooks' +import { useWalletMetaData } from './useWalletMetadata' +import { getIsAmbireWallet } from '../../api/utils/connection' +import { Contract } from '@ethersproject/contracts' +import { getProviderOrSigner } from '@cowprotocol/common-utils' +import { ARGENT_WALLET_DETECTOR_ADDRESS } from '@cowprotocol/common-const' +import { ArgentWalletDetectorAbi } from '@cowprotocol/abis' + +function useCheckIsSmartContract(): boolean | undefined { + const { provider } = useWeb3React() + const { account } = useWalletInfo() + + const { data } = useSWR(['isSmartContract', account, provider], async () => { + if (!account || !provider) { + return false + } + + try { + const code = await provider.getCode(account) + return code !== '0x' + } catch (e: any) { + console.debug(`checkIsSmartContractWallet: failed to check address ${account}`, e.message) + return false + } + }) + + return data +} + +export function useIsSmartContractWallet(): boolean { + const [isSmartContractWallet, setIsSmartContractWallet] = useState(false) + + const { account } = useWalletInfo() + + const isArgentWallet = useIsArgentWallet() + const isSmartContract = useCheckIsSmartContract() + const isAmbireWallet = useIsAmbireWallet() + + useEffect(() => { + if (!account) { + setIsSmartContractWallet(false) + return + } + + if (isAmbireWallet || isArgentWallet || isSmartContract) { + setIsSmartContractWallet(true) + } + }, [account, isAmbireWallet, isArgentWallet, isSmartContract]) + + return isSmartContractWallet +} + +function useIsArgentWallet(): boolean { + const { provider } = useWeb3React() + const { account, chainId } = useWalletInfo() + const argentWalletContract = useMemo(() => { + if (!provider) return null + + const address = ARGENT_WALLET_DETECTOR_ADDRESS[chainId] + + if (!address) return null + + return new Contract(address, ArgentWalletDetectorAbi, getProviderOrSigner(provider, account)) + }, [chainId, account, provider]) + + return useAsyncMemo( + () => { + if (!argentWalletContract || !account) return Promise.resolve(false) + + return argentWalletContract.callStatic.isArgentWallet(account) + }, + [argentWalletContract], + false + ) +} + +function useIsAmbireWallet(): boolean { + const { walletName } = useWalletMetaData() + + return getIsAmbireWallet(walletName) +} diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useIsWalletConnect.ts b/libs/wallet/src/web3-react/hooks/useIsWalletConnect.ts similarity index 88% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useIsWalletConnect.ts rename to libs/wallet/src/web3-react/hooks/useIsWalletConnect.ts index 257f02da17..160a94d858 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useIsWalletConnect.ts +++ b/libs/wallet/src/web3-react/hooks/useIsWalletConnect.ts @@ -4,7 +4,7 @@ import { useWeb3React } from '@web3-react/core' import { Connector } from '@web3-react/types' import { ConnectionType } from '../../api/types' -import { getWeb3ReactConnection } from '../connection' +import { getWeb3ReactConnection } from '../utils/getWeb3ReactConnection' export function useIsWalletConnect(): boolean { const { connector } = useWeb3React() diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useSafeAppsSdk.ts b/libs/wallet/src/web3-react/hooks/useSafeAppsSdk.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useSafeAppsSdk.ts rename to libs/wallet/src/web3-react/hooks/useSafeAppsSdk.ts diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useSafeAppsSdkInfo.test.tsx b/libs/wallet/src/web3-react/hooks/useSafeAppsSdkInfo.test.tsx similarity index 100% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useSafeAppsSdkInfo.test.tsx rename to libs/wallet/src/web3-react/hooks/useSafeAppsSdkInfo.test.tsx diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useSafeAppsSdkInfo.ts b/libs/wallet/src/web3-react/hooks/useSafeAppsSdkInfo.ts similarity index 87% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useSafeAppsSdkInfo.ts rename to libs/wallet/src/web3-react/hooks/useSafeAppsSdkInfo.ts index b13ddedfb9..184f6be051 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useSafeAppsSdkInfo.ts +++ b/libs/wallet/src/web3-react/hooks/useSafeAppsSdkInfo.ts @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react' import type { SafeInfo } from '@safe-global/safe-apps-sdk' -import { useSafeAppsSdk } from 'modules/wallet/web3-react/hooks/useSafeAppsSdk' +import { useSafeAppsSdk } from './useSafeAppsSdk' export type GnosisSafeSdkInfo = SafeInfo diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useWalletMetadata.ts b/libs/wallet/src/web3-react/hooks/useWalletMetadata.ts similarity index 92% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useWalletMetadata.ts rename to libs/wallet/src/web3-react/hooks/useWalletMetadata.ts index c6bb20f608..b9d401fb70 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/useWalletMetadata.ts +++ b/libs/wallet/src/web3-react/hooks/useWalletMetadata.ts @@ -2,10 +2,10 @@ import { useMemo } from 'react' import { useWeb3React } from '@web3-react/core' -import { ConnectionType } from 'modules/wallet' -import { default as AlphaImage } from 'modules/wallet/api/assets/alpha.svg' -import { getIsAlphaWallet } from 'modules/wallet/api/utils/connection' -import { getWeb3ReactConnection } from 'modules/wallet/web3-react/connection' +import { default as AlphaImage } from '../../api/assets/alpha.svg' +import { ConnectionType } from '../../api/types' +import { getIsAlphaWallet } from '../../api/utils/connection' +import { getWeb3ReactConnection } from '../utils/getWeb3ReactConnection' const WC_DESKTOP_GNOSIS_SAFE_APP_NAME = 'WalletConnect Safe App' const WC_MOBILE_GNOSIS_SAFE_APP_NAME = 'Safe' diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/index.cosmos.tsx b/libs/wallet/src/web3-react/pure/AccountIndexSelect/index.cosmos.tsx similarity index 89% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/index.cosmos.tsx rename to libs/wallet/src/web3-react/pure/AccountIndexSelect/index.cosmos.tsx index 81fbcb01b6..98c54b5463 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/index.cosmos.tsx +++ b/libs/wallet/src/web3-react/pure/AccountIndexSelect/index.cosmos.tsx @@ -1,11 +1,8 @@ +import { WETH_GOERLI } from '@cowprotocol/common-const' import { CurrencyAmount } from '@uniswap/sdk-core' import styled from 'styled-components/macro' -import { WETH_GOERLI } from 'legacy/utils/goerli/constants' - -import { UI } from 'common/constants/theme' - import { AccountIndexSelect } from './index' const accountsList = [ @@ -27,7 +24,7 @@ const Wrapper = styled.div` margin: 100px auto; padding: 20px; - background: var(${UI.COLOR_CONTAINER_BG_01}); + background: var(--cow-container-bg-01); ` const Fixtures = { diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/index.tsx b/libs/wallet/src/web3-react/pure/AccountIndexSelect/index.tsx similarity index 83% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/index.tsx rename to libs/wallet/src/web3-react/pure/AccountIndexSelect/index.tsx index c5414dfff3..a3e1fc4736 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/index.tsx +++ b/libs/wallet/src/web3-react/pure/AccountIndexSelect/index.tsx @@ -2,14 +2,8 @@ import { useCallback, useRef, useState } from 'react' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { Trans } from '@lingui/macro' - -import { ButtonPrimary } from 'legacy/components/Button' -import Loader from 'legacy/components/Loader' -import { shortenAddress } from 'legacy/utils' - -import { SelectDropdown } from 'common/pure/SelectDropdown' -import { TokenAmount } from 'common/pure/TokenAmount' +import { ButtonPrimary, Loader, SelectDropdown, TokenAmount } from '@cowprotocol/ui' +import { shortenAddress } from '@cowprotocol/common-utils' import * as styledEl from './styled' @@ -50,8 +44,7 @@ export function AccountIndexSelect(props: AccountIndexSelectProps) { <> - Please select which account you would like to use: - + Please select which account you would like to use: {accountsList.map((address, index) => { @@ -75,17 +68,17 @@ export function AccountIndexSelect(props: AccountIndexSelectProps) { {loadingAccounts ? ( <> - Loading... + Loading... ) : ( - Load more + 'Load more' )} - Connect selected account + Connect selected account diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/styled.tsx b/libs/wallet/src/web3-react/pure/AccountIndexSelect/styled.tsx similarity index 88% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/styled.tsx rename to libs/wallet/src/web3-react/pure/AccountIndexSelect/styled.tsx index e941c67de6..a1e0d7d32d 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/pure/AccountIndexSelect/styled.tsx +++ b/libs/wallet/src/web3-react/pure/AccountIndexSelect/styled.tsx @@ -1,7 +1,6 @@ import styled from 'styled-components/macro' -import { UI } from 'common/constants/theme' -import { ButtonSecondary } from 'common/pure/ButtonSecondary' +import { ButtonSecondary } from '@cowprotocol/ui' export const Wrapper = styled.div` ${({ theme }) => theme.flexColumnNoWrap}; @@ -18,7 +17,7 @@ export const LoaderContainer = styled(ButtonSecondary)` &[disabled] { cursor: default; - background: var(${UI.COLOR_LIGHT_BLUE_OPACITY_90}); + background: var(--cow-color-lightBlue-opacity-90); } ` diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/types.ts b/libs/wallet/src/web3-react/types.ts similarity index 58% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/types.ts rename to libs/wallet/src/web3-react/types.ts index 304e1dcee5..0f92a8de1e 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/types.ts +++ b/libs/wallet/src/web3-react/types.ts @@ -2,7 +2,7 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Web3ReactHooks } from '@web3-react/core' import { Connector } from '@web3-react/types' -import { ConnectionType } from 'modules/wallet' +import { ConnectionType } from '../api/types' export interface Web3ReactConnection { connector: T @@ -10,3 +10,11 @@ export interface Web3ReactConnection { type: ConnectionType overrideActivate?: (chainId: SupportedChainId) => boolean } + +export type TryActivation = (connector: Connector) => void + +export interface ConnectionOptionProps { + darkMode: boolean + selectedWallet: string | undefined + tryActivation: TryActivation +} diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/updater.ts b/libs/wallet/src/web3-react/updater.ts similarity index 84% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/updater.ts rename to libs/wallet/src/web3-react/updater.ts index 809f64259f..dbfc009891 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/updater.ts +++ b/libs/wallet/src/web3-react/updater.ts @@ -3,22 +3,22 @@ import { useEffect, useMemo, useState } from 'react' import { useWeb3React } from '@web3-react/core' -import { UNSUPPORTED_WC_WALLETS } from 'legacy/constants' -import useENSName from 'legacy/hooks/useENSName' - -import { useIsSafeWallet, useWalletMetaData } from 'modules/wallet' -import { getWalletType } from 'modules/wallet/api/utils/getWalletType' - -import { getSafeInfo } from 'api/gnosisSafe' -import { useIsProviderNetworkUnsupported } from 'common/hooks/useIsProviderNetworkUnsupported' -import { useIsSmartContractWallet } from 'common/hooks/useIsSmartContractWallet' -import { getCurrentChainIdFromUrl } from 'utils/getCurrentChainIdFromUrl' +import { getSafeInfo } from '@cowprotocol/core' +import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' import { useSafeAppsSdkInfo } from './hooks/useSafeAppsSdkInfo' +import { useIsSafeWallet, useWalletMetaData } from './hooks/useWalletMetadata' import { gnosisSafeInfoAtom, walletDetailsAtom, walletInfoAtom } from '../api/state' import { GnosisSafeInfo, WalletDetails, WalletInfo } from '../api/types' +import { getWalletType } from '../api/utils/getWalletType' import { getWalletTypeLabel } from '../api/utils/getWalletTypeLabel' +import { useIsSmartContractWallet } from './hooks/useIsSmartContractWallet' +import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useENSName } from '@cowprotocol/ens' + +// Smart contract wallets are filtered out by default, no need to add them to this list +const UNSUPPORTED_WC_WALLETS = new Set(['DeFi Wallet', 'WallETH']) function _checkIsSupportedWallet(walletName?: string): boolean { return !(walletName && UNSUPPORTED_WC_WALLETS.has(walletName)) @@ -26,7 +26,7 @@ function _checkIsSupportedWallet(walletName?: string): boolean { function _useWalletInfo(): WalletInfo { const { account, chainId, isActive: active } = useWeb3React() - const isChainIdUnsupported = useIsProviderNetworkUnsupported() + const isChainIdUnsupported = !!chainId && !(chainId in SupportedChainId) return useMemo( () => ({ diff --git a/libs/wallet/src/web3-react/utils/getIsHardWareWallet.ts b/libs/wallet/src/web3-react/utils/getIsHardWareWallet.ts new file mode 100644 index 0000000000..ec20354da7 --- /dev/null +++ b/libs/wallet/src/web3-react/utils/getIsHardWareWallet.ts @@ -0,0 +1,9 @@ +import { ConnectionType } from '../../api/types' + +// TODO: add others +export const HARDWARE_WALLETS = [ConnectionType.TREZOR] as const + +export type HardWareWallet = (typeof HARDWARE_WALLETS)[number] + +export const getIsHardWareWallet = (connectionType: ConnectionType) => + HARDWARE_WALLETS.includes(connectionType as HardWareWallet) diff --git a/libs/wallet/src/web3-react/utils/getWeb3ReactConnection.ts b/libs/wallet/src/web3-react/utils/getWeb3ReactConnection.ts new file mode 100644 index 0000000000..a2506a3a29 --- /dev/null +++ b/libs/wallet/src/web3-react/utils/getWeb3ReactConnection.ts @@ -0,0 +1,47 @@ +import { Connector } from '@web3-react/types' + +import { ConnectionType } from '../../api/types' +import { coinbaseWalletConnection } from '../connection/coinbase' +import { injectedConnection } from '../connection/injected' +import { injectedWidgetConnection } from '../connection/injectedWidget' +import { keystoneConnection } from '../connection/keystone' +import { ledgerConnection } from '../connection/ledger' +import { networkConnection } from '../connection/network' +import { gnosisSafeConnection } from '../connection/safe' +import { tallyWalletConnection } from '../connection/tally' +import { trezorConnection } from '../connection/trezor' +import { trustWalletConnection } from '../connection/trust' +import { walletConnectConnection } from '../connection/walletConnect' +import { walletConnectConnectionV2 } from '../connection/walletConnectV2' +import { Web3ReactConnection } from '../types' + +const connectionTypeToConnection: Record = { + [ConnectionType.INJECTED]: injectedConnection, + [ConnectionType.COINBASE_WALLET]: coinbaseWalletConnection, + [ConnectionType.WALLET_CONNECT]: walletConnectConnection, + [ConnectionType.WALLET_CONNECT_V2]: walletConnectConnectionV2, + [ConnectionType.ZENGO]: walletConnectConnection, + [ConnectionType.NETWORK]: networkConnection, + [ConnectionType.GNOSIS_SAFE]: gnosisSafeConnection, + [ConnectionType.AMBIRE]: walletConnectConnection, + [ConnectionType.ALPHA]: walletConnectConnection, + [ConnectionType.TALLY]: tallyWalletConnection, + [ConnectionType.TRUST]: trustWalletConnection, + [ConnectionType.LEDGER]: ledgerConnection, + [ConnectionType.KEYSTONE]: keystoneConnection, + [ConnectionType.INJECTED_WIDGET]: injectedWidgetConnection, + [ConnectionType.TREZOR]: trezorConnection, +} +const CONNECTIONS: Web3ReactConnection[] = Object.values(connectionTypeToConnection) + +export function getWeb3ReactConnection(c: Connector | ConnectionType): Web3ReactConnection { + if (c instanceof Connector) { + const connection = CONNECTIONS.find((connection) => connection.connector === c) + if (!connection) { + throw Error('unsupported connector') + } + return connection + } + + return connectionTypeToConnection[c] +} diff --git a/libs/wallet/src/web3-react/utils/isChainAllowed.ts b/libs/wallet/src/web3-react/utils/isChainAllowed.ts new file mode 100644 index 0000000000..56abdae9ec --- /dev/null +++ b/libs/wallet/src/web3-react/utils/isChainAllowed.ts @@ -0,0 +1,30 @@ +import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from '@cowprotocol/cow-sdk' +import { Connector } from '@web3-react/types' + +import { getWeb3ReactConnection } from './getWeb3ReactConnection' + +import { ConnectionType } from '../../api/types' + +const allowedChainsByWallet: Record = { + [ConnectionType.INJECTED]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.INJECTED_WIDGET]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.COINBASE_WALLET]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.WALLET_CONNECT]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.WALLET_CONNECT_V2]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.NETWORK]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.GNOSIS_SAFE]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.TALLY]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.TRUST]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.LEDGER]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.TREZOR]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.KEYSTONE]: ALL_SUPPORTED_CHAIN_IDS, + [ConnectionType.ALPHA]: [], + [ConnectionType.AMBIRE]: [], + [ConnectionType.ZENGO]: [], +} + +export function isChainAllowed(connector: Connector, chainId: number): boolean { + const connection = getWeb3ReactConnection(connector) + + return allowedChainsByWallet[connection.type].includes(chainId) +} diff --git a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/switchChain.ts b/libs/wallet/src/web3-react/utils/switchChain.ts similarity index 84% rename from apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/switchChain.ts rename to libs/wallet/src/web3-react/utils/switchChain.ts index cc71d43534..66f9dd2758 100644 --- a/apps/cowswap-frontend/src/modules/wallet/web3-react/hooks/switchChain.ts +++ b/libs/wallet/src/web3-react/utils/switchChain.ts @@ -1,13 +1,12 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' import { Connector } from '@web3-react/types' -import { getChainInfo } from 'legacy/constants/chainInfo' -import { RPC_URLS } from 'legacy/constants/networks' - -import { getIsWalletConnect } from './useIsWalletConnect' +import { getWeb3ReactConnection } from './getWeb3ReactConnection' +import { isChainAllowed } from './isChainAllowed' import { ConnectionType } from '../../api/types' -import { getWeb3ReactConnection, isChainAllowed } from '../connection' +import { getIsWalletConnect } from '../hooks/useIsWalletConnect' +import { getChainInfo, RPC_URLS } from '@cowprotocol/common-const' function getRpcUrls(chainId: SupportedChainId): [string] { switch (chainId) { diff --git a/libs/wallet/tsconfig.json b/libs/wallet/tsconfig.json new file mode 100644 index 0000000000..bab74ff2e6 --- /dev/null +++ b/libs/wallet/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["vite/client"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/wallet/tsconfig.lib.json b/libs/wallet/tsconfig.lib.json new file mode 100644 index 0000000000..1b2b0c12df --- /dev/null +++ b/libs/wallet/tsconfig.lib.json @@ -0,0 +1,19 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": ["node", "vite/client"] + }, + "files": ["../../node_modules/@nx/react/typings/cssmodule.d.ts", "../../node_modules/@nx/react/typings/image.d.ts"], + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/wallet/tsconfig.spec.json b/libs/wallet/tsconfig.spec.json new file mode 100644 index 0000000000..26ef046ac5 --- /dev/null +++ b/libs/wallet/tsconfig.spec.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} diff --git a/libs/wallet/vite.config.ts b/libs/wallet/vite.config.ts new file mode 100644 index 0000000000..070d48d360 --- /dev/null +++ b/libs/wallet/vite.config.ts @@ -0,0 +1,49 @@ +/// +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' +import viteTsConfigPaths from 'vite-tsconfig-paths' +import dts from 'vite-plugin-dts' +import * as path from 'path' + +export default defineConfig({ + cacheDir: '../../node_modules/.vite/wallet', + + plugins: [ + dts({ + entryRoot: 'src', + tsConfigFilePath: path.join(__dirname, 'tsconfig.lib.json'), + skipDiagnostics: true, + }), + react(), + viteTsConfigPaths({ + root: '../../', + }), + ], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ + // viteTsConfigPaths({ + // root: '../../', + // }), + // ], + // }, + + // Configuration for building your library. + // See: https://vitejs.dev/guide/build.html#library-mode + build: { + lib: { + // Could also be a dictionary or array of multiple entry points. + entry: 'src/index.ts', + name: 'wallet', + fileName: 'index', + // Change this to the formats you want to support. + // Don't forget to update your package.json as well. + formats: ['es', 'cjs'], + }, + rollupOptions: { + // External packages that should not be bundled into your library. + external: ['react', 'react-dom', 'react/jsx-runtime'], + }, + }, +}) diff --git a/libs/widget-lib/README.md b/libs/widget-lib/README.md index e917261a5b..eadb59aee9 100644 --- a/libs/widget-lib/README.md +++ b/libs/widget-lib/README.md @@ -21,7 +21,7 @@ Create an empty div somewhere in your website: Import the widget and initialise it: ```js -import { cowSwapWidget } from '@cowswap/widget-lib' +import { cowSwapWidget } from '@cowprotocol/widget-lib' // Initialise the widget const widgetContainer = document.getElementById('cowswap-widget') diff --git a/libs/widget-lib/docs/README.md b/libs/widget-lib/docs/README.md index 85b6cd1c38..57860a98de 100644 --- a/libs/widget-lib/docs/README.md +++ b/libs/widget-lib/docs/README.md @@ -21,7 +21,7 @@ npm install @cowprotocol/widget-lib ## Quick start ```typescript -import { cowSwapWidget, CowSwapWidgetParams, CowSwapWidgetSettings } from '@cowswap/widget-lib' +import { cowSwapWidget, CowSwapWidgetParams, CowSwapWidgetSettings } from '@cowprotocol/widget-lib' // Initialise the widget const widgetContainer = document.getElementById('cowswap-widget') @@ -70,7 +70,7 @@ interface JsonRpcRequest { An example of connecting a widget to Metamask: ```typescript -import { cowSwapWidget, CowSwapWidgetParams } from '@cowswap/widget-lib' +import { cowSwapWidget, CowSwapWidgetParams } from '@cowprotocol/widget-lib' const params: CowSwapWidgetParams = { container: document.getElementById('cowswap-widget'), @@ -137,7 +137,7 @@ export interface TradeAssets { You can change all possible widget options on the fly: ```typescript -import { cowSwapWidget, CowSwapWidgetParams, CowSwapWidgetSettings } from '@cowswap/widget-lib' +import { cowSwapWidget, CowSwapWidgetParams, CowSwapWidgetSettings } from '@cowprotocol/widget-lib' const params: CowSwapWidgetParams = { container: document.getElementById('cowswap-widget'), diff --git a/libs/widget-react/README.md b/libs/widget-react/README.md index 405b0776ae..637a2031d7 100644 --- a/libs/widget-react/README.md +++ b/libs/widget-react/README.md @@ -17,7 +17,7 @@ yarn add @cowprotocol/widget-react Import component and some convenient types ```ts -import { CowSwapWidgetSettings } from '@cowswap/widget-lib' +import { CowSwapWidgetSettings } from '@cowprotocol/widget-lib' import { CowSwapWidget, CowSwapWidgetParams } from '@cowprotocol/widget-react' ``` diff --git a/libs/widget-react/src/lib/CowSwapWidget.tsx b/libs/widget-react/src/lib/CowSwapWidget.tsx index c0212ea4c2..d95f8609f6 100644 --- a/libs/widget-react/src/lib/CowSwapWidget.tsx +++ b/libs/widget-react/src/lib/CowSwapWidget.tsx @@ -4,7 +4,7 @@ import { cowSwapWidget, CowSwapWidgetParams as CowSwapWidgetParamsAux, CowSwapWidgetSettings, -} from '@cowswap/widget-lib' +} from '@cowprotocol/widget-lib' export type CowSwapWidgetParams = Omit export interface CowSwapWidgetProps { diff --git a/libs/widget-react/vite.config.ts b/libs/widget-react/vite.config.ts index 82a40dd645..d6f035e1b7 100644 --- a/libs/widget-react/vite.config.ts +++ b/libs/widget-react/vite.config.ts @@ -1,6 +1,6 @@ /// import { joinPathFragments } from '@nx/devkit' -import react from '@vitejs/plugin-react' +import react from '@vitejs/plugin-react-swc' import { defineConfig } from 'vite' import dts from 'vite-plugin-dts' import viteTsConfigPaths from 'vite-tsconfig-paths' diff --git a/nx.json b/nx.json index 9cddd6252b..b02e49fd75 100644 --- a/nx.json +++ b/nx.json @@ -1,18 +1,20 @@ { "$schema": "./node_modules/nx/schemas/nx-schema.json", + "affected": { + "defaultBase": "develop" + }, "tasksRunnerOptions": { "default": { - "runner": "nx/tasks-runners/default", + "runner": "nx-cloud", "options": { "cacheableOperations": ["build", "lint", "test", "e2e"], - "accessToken": "YmVmZTg2ZTQtOGNjMi00ZjQzLTk1Y2EtZTA0MDNjY2ExNDZifHJlYWQtd3JpdGU=" + "accessToken": "M2U1ZmI5MTEtZmY3MS00YzRjLTkxYmQtZDhkM2QzZTBkNTVhfHJlYWQ=" } } }, "targetDefaults": { "build": { - "dependsOn": ["^build"], - "inputs": ["production", "^production"] + "inputs": ["default", "production", "^production"] }, "e2e": { "inputs": ["default", "^production"] diff --git a/package.json b/package.json index 0f6dab69a7..89d86aa006 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,12 @@ "scripts": { "start": "nx run cowswap-frontend:serve", "preview": "nx run cowswap-frontend:preview", - "test": "nx run-many -t test -p $npm_package_config_enabledApps", - "e2e": "nx run-many -t e2e -p $npm_package_config_enabledApps", - "lint": "nx run-many -t lint -p $npm_package_config_enabledApps", - "build": "cross-env NODE_OPTIONS=--max-old-space-size=32768 nx run cowswap-frontend:build", - "cosmos:export": "cross-env NODE_OPTIONS=--max-old-space-size=32768 nx run cowswap-frontend:cosmos:export", + "cosmos:export": "nx run cowswap-frontend:cosmos:export", + "test": "nx run-many -t test --output-style=stream", + "e2e": "nx run-many -t e2e", + "lint": "nx run-many -t lint", "prebuild": "nx run cowswap-frontend:i18n", - "postbuild": "rm -rf build && mkdir build && mv dist/apps/cowswap-frontend/* build", + "build": "nx build cowswap-frontend", "prepare": "husky install", "postinstall": "yarn run patch-package", "analyze-build": "cross-env ANALYZE_BUNDLE=true ANALYZE_BUNDLE_TEMPLATE=sunburst yarn build" @@ -250,65 +249,10 @@ "vite": "~4.3.9", "vite-plugin-babel-macros": "^1.0.6", "vite-plugin-dts": "~2.3.0", - "vite-plugin-node-polyfills": "^0.11.1", + "vite-plugin-node-polyfills": "^0.12.0", "vite-plugin-pwa": "^0.16.4", "vite-plugin-svgr": "^3.2.0", "vite-tsconfig-paths": "~4.2.0", "vitest": "~0.32.0" - }, - "nx": { - "targets": { - "build": { - "outputs": [ - "{projectRoot}/build", - "{projectRoot}/src/locales" - ] - }, - "build:analyze": { - "outputs": [ - "{projectRoot}/build" - ] - }, - "ipfs:build": { - "outputs": [ - "{projectRoot}/build" - ] - }, - "optimize-bundle": { - "outputs": [ - "{projectRoot}/../node_modules/@ethereumjs/common/dist.browser/genesisStates/mainnet.json" - ] - }, - "i18n:extract": { - "outputs": [ - "{projectRoot}/src/locales" - ] - }, - "i18n": { - "outputs": [ - "{projectRoot}/src/locales" - ] - }, - "i18n:pseudo": { - "outputs": [ - "{projectRoot}/src/locales" - ] - }, - "cosmos:export": { - "outputs": [ - "{projectRoot}/public/cosmos" - ] - }, - "sitemap": { - "outputs": [ - "{projectRoot}/public/sitemap.xml" - ] - }, - "writeVersion": { - "outputs": [ - "{projectRoot}/public/version.json" - ] - } - } } } diff --git a/apps/cowswap-frontend/testing/imgMock.js b/testing/imgMock.js similarity index 100% rename from apps/cowswap-frontend/testing/imgMock.js rename to testing/imgMock.js diff --git a/apps/cowswap-frontend/testing/svgrMock.js b/testing/svgrMock.js similarity index 100% rename from apps/cowswap-frontend/testing/svgrMock.js rename to testing/svgrMock.js diff --git a/tools/getReactProcessEnv.ts b/tools/getReactProcessEnv.ts new file mode 100644 index 0000000000..4c9a3dc0f3 --- /dev/null +++ b/tools/getReactProcessEnv.ts @@ -0,0 +1,13 @@ +import { loadEnv } from 'vite' + +export function getReactProcessEnv(mode: string): { [key: string]: string } { + const env = loadEnv(mode, process.cwd(), ['REACT_APP_']) + + // expose .env as process.env instead of import.meta since jest does not import meta yet + return Object.entries(env).reduce((prev, [key, val]) => { + return { + ...prev, + ['process.env.' + key]: JSON.stringify(val), + } + }, {}) +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 8b32512a7e..dfa00a1964 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -31,12 +31,20 @@ "allowSyntheticDefaultImports": true, "baseUrl": ".", "paths": { - "@cowswap/abis": ["libs/abis/src/index.ts"], - "@cowswap/ui": ["libs/ui/src/index.ts"], - "@cowswap/ui-utils": ["libs/ui-utils/src/index.ts"], - "@cowswap/widget-lib": ["libs/widget-lib/src/index.ts"], - "@cowswap/widget-react": ["libs/widget-react/src/index.ts"], - "@cowswap/snackbars": ["libs/snackbars/src/index.ts"] + "@cowprotocol/abis": ["libs/abis/src/index.ts"], + "@cowprotocol/analytics": ["libs/analytics/src/index.ts"], + "@cowprotocol/assets/*": ["libs/assets/src/*"], + "@cowprotocol/common-const": ["libs/common-const/src/index.ts"], + "@cowprotocol/common-hooks": ["libs/common-hooks/src/index.ts"], + "@cowprotocol/common-utils": ["libs/common-utils/src/index.ts"], + "@cowprotocol/core": ["libs/core/src/index.ts"], + "@cowprotocol/ens": ["libs/ens/src/index.ts"], + "@cowprotocol/snackbars": ["libs/snackbars/src/index.ts"], + "@cowprotocol/ui": ["libs/ui/src/index.ts"], + "@cowprotocol/ui-utils": ["libs/ui-utils/src/index.ts"], + "@cowprotocol/wallet": ["libs/wallet/src/index.ts"], + "@cowprotocol/widget-lib": ["libs/widget-lib/src/index.ts"], + "@cowprotocol/widget-react": ["libs/widget-react/src/index.ts"] } }, "exclude": ["node_modules", "tmp"] diff --git a/yarn.lock b/yarn.lock index 690b3eb08a..e7e2220bf9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19177,16 +19177,16 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -"process-polyfill@npm:process@^0.11.10", process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - process-warning@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -23028,15 +23028,15 @@ vite-plugin-dts@~2.3.0: magic-string "^0.29.0" ts-morph "18.0.0" -vite-plugin-node-polyfills@^0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.11.1.tgz#5f947258a7025d9f22b72f45075fabc6763ed61b" - integrity sha512-9bIZGzMhaGk2s/UC0fpDyIsPo5e33xAUAgZOav2GMgxC5KD48lgTecMmWgL326idrXmLGI12ef52CsKHSvSV6Q== +vite-plugin-node-polyfills@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.12.0.tgz#f97606cb9bdfa66e71d83738e5e05a409096321f" + integrity sha512-xZfpD81aNhwEbIjccEiy8Q/hDdnlYqBSeEaUMIukOpGHuMaz65jqrC2lmnF/FXnliovISy2L1n92da0JOvk36A== dependencies: "@rollup/plugin-inject" "^5.0.3" buffer-polyfill "npm:buffer@^6.0.3" node-stdlib-browser "^1.2.0" - process-polyfill "npm:process@^0.11.10" + process "^0.11.10" vite-plugin-pwa@^0.16.4: version "0.16.4" From 6a3a79a05c0782e45f8a9e79064547ae92e84d25 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Thu, 21 Sep 2023 18:26:48 +0300 Subject: [PATCH 09/36] feat(wallet-connect-2): lazy loading for wc1 and wc2 (#3136) * feat(wallet-connect-2): load wc2 connector async-ly * feat: wallet connect v1 lazy loading * chore: fix import * chore: merge develop * chore: fix imports --- apps/cowswap-frontend/vite.config.ts | 1 - .../web3-react/connection/asyncConnector.ts | 31 ++++++-- .../web3-react/connection/walletConnect.tsx | 43 +++++++----- .../web3-react/connection/walletConnectV2.tsx | 70 ++++++++++++------- 4 files changed, 97 insertions(+), 48 deletions(-) diff --git a/apps/cowswap-frontend/vite.config.ts b/apps/cowswap-frontend/vite.config.ts index 6c557ded36..8544e0343b 100644 --- a/apps/cowswap-frontend/vite.config.ts +++ b/apps/cowswap-frontend/vite.config.ts @@ -127,7 +127,6 @@ export default defineConfig(({ mode }) => { if (id.includes('@safe-global') || id.includes('viem')) return '@safe-global' if (id.includes('@sentry')) return '@sentry' if (id.includes('@uniswap')) return '@uniswap' - if (id.includes('@walletconnect')) return '@walletconnect' if (id.includes('crypto-es/lib')) return 'crypto-es' if (id.includes('web3/dist')) return 'web3' }, diff --git a/libs/wallet/src/web3-react/connection/asyncConnector.ts b/libs/wallet/src/web3-react/connection/asyncConnector.ts index dc2e46961e..566d6d4759 100644 --- a/libs/wallet/src/web3-react/connection/asyncConnector.ts +++ b/libs/wallet/src/web3-react/connection/asyncConnector.ts @@ -1,27 +1,50 @@ +import { Web3Provider } from '@ethersproject/providers' import { Actions, Connector } from '@web3-react/types' +import EventEmitter from 'events' + +export const ASYNC_CUSTOM_PROVIDER_EVENT = 'customProvider' + +function initCustomProvider(self: AsyncConnector, connector: Connector, chainId: number) { + if (connector.provider && !connector.customProvider) { + self.customProvider = new Web3Provider(connector.provider, chainId) + } + + self.events.emit(ASYNC_CUSTOM_PROVIDER_EVENT, self.customProvider) +} + /** * To avoid including external libs for wallet connection in the bundle * We load them in runtime by demand */ export class AsyncConnector extends Connector { + readonly events = new EventEmitter() + constructor(private loader: () => Promise, actions: Actions, onError?: (error: Error) => void) { super(actions, onError) } - activate(...args: unknown[]): Promise | void { + activate(chainId: number): Promise | void { return this.loader().then((connector) => { // There is a magic - we change async-connector prototype to the loaded connector ;(this as any).__proto__ = connector - return connector.activate(...args) + + return (connector.activate(chainId) || Promise.resolve()).then(() => { + initCustomProvider(this, connector, chainId) + }) }) } - async connectEagerly(...args: unknown[]) { + async connectEagerly(chainId: number) { return this.loader().then((connector) => { // There is a magic - we change async-connector prototype to the loaded connector ;(this as any).__proto__ = connector - return connector.connectEagerly?.(...args) + + const activation = connector.connectEagerly?.(chainId) || Promise.resolve() + + return activation.then(() => { + initCustomProvider(this, connector, chainId) + }) }) } } diff --git a/libs/wallet/src/web3-react/connection/walletConnect.tsx b/libs/wallet/src/web3-react/connection/walletConnect.tsx index 459be8b0b4..1ae9ecc339 100644 --- a/libs/wallet/src/web3-react/connection/walletConnect.tsx +++ b/libs/wallet/src/web3-react/connection/walletConnect.tsx @@ -1,11 +1,17 @@ import { useMemo } from 'react' +import { RPC_URLS } from '@cowprotocol/common-const' + import { initializeConnector } from '@web3-react/core' -import { WalletConnect } from '@web3-react/walletconnect' +import { useFlags } from 'launchdarkly-react-client-sdk' import { default as WalletConnectImage } from '../../api/assets/walletConnectIcon.svg' -import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' + +import { AsyncConnector } from './asyncConnector' +import { ConnectionOptionProps, Web3ReactConnection } from '../types' +import { onError } from './onError' import { ConnectionType } from '../../api/types' +import { useWalletMetaData } from '../hooks/useWalletMetadata' import { getConnectionName, getIsAlphaWallet, @@ -14,13 +20,8 @@ import { getIsZengoWallet, } from '../../api/utils/connection' import { WC_DISABLED_TEXT } from '../../constants' -import { useWalletMetaData } from '../hooks/useWalletMetadata' -import { ConnectionOptionProps, Web3ReactConnection } from '../types' - +import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' import { useIsActiveConnection } from '../hooks/useIsActiveConnection' -import { RPC_URLS } from '@cowprotocol/common-const' -import { onError } from './onError' -import { useFlags } from 'launchdarkly-react-client-sdk' const WC_SUNSET_LINK = 'https://medium.com/walletconnect/weve-reset-the-clock-on-the-walletconnect-v1-0-shutdown-now-scheduled-for-june-28-2023-ead2d953b595' @@ -33,17 +34,25 @@ export const walletConnectOption = { id: 'wallet-connect', } -const [web3WalletConnect, web3WalletConnectHooks] = initializeConnector( +const [web3WalletConnect, web3WalletConnectHooks] = initializeConnector( (actions) => - new WalletConnect({ + new AsyncConnector( + () => + import('@web3-react/walletconnect').then( + (m) => + new m.WalletConnect({ + actions, + options: { + rpc: RPC_URLS, + qrcode: true, + bridge: process.env.REACT_APP_WALLET_CONNECT_V1_BRIDGE || 'https://safe-walletconnect.safe.global', + }, + onError, + }) + ), actions, - options: { - rpc: RPC_URLS, - qrcode: true, - bridge: process.env.REACT_APP_WALLET_CONNECT_V1_BRIDGE || 'https://safe-walletconnect.safe.global', - }, - onError, - }) + onError + ) ) export const walletConnectConnection: Web3ReactConnection = { connector: web3WalletConnect, diff --git a/libs/wallet/src/web3-react/connection/walletConnectV2.tsx b/libs/wallet/src/web3-react/connection/walletConnectV2.tsx index 60845161b5..6d47b9a281 100644 --- a/libs/wallet/src/web3-react/connection/walletConnectV2.tsx +++ b/libs/wallet/src/web3-react/connection/walletConnectV2.tsx @@ -1,12 +1,22 @@ -import { useSyncExternalStore } from 'react' +import { useState, useSyncExternalStore } from 'react' + +import { RPC_URLS } from '@cowprotocol/common-const' +import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from '@cowprotocol/cow-sdk' import { initializeConnector, Web3ReactHooks } from '@web3-react/core' import { Web3ReactStore } from '@web3-react/types' import { default as WalletConnectV2Image } from '../../api/assets/wallet-connect-v2.png' -import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' + +import { ASYNC_CUSTOM_PROVIDER_EVENT, AsyncConnector } from './asyncConnector' + +import { ConnectionOptionProps, Web3ReactConnection } from '../types' + +import { onError } from './onError' import { ConnectionType } from '../../api/types' +import { useWalletMetaData } from '../hooks/useWalletMetadata' +import { useIsActiveConnection } from '../hooks/useIsActiveConnection' import { getConnectionName, getIsAlphaWallet, @@ -15,13 +25,7 @@ import { getIsZengoWallet, } from '../../api/utils/connection' import { WC_DISABLED_TEXT } from '../../constants' -import { WalletConnectV2Connector } from '../connectors/WalletConnectV2Connector' -import { useWalletMetaData } from '../hooks/useWalletMetadata' -import { ConnectionOptionProps, Web3ReactConnection } from '../types' - -import { useIsActiveConnection } from '../hooks/useIsActiveConnection' -import { RPC_URLS } from '@cowprotocol/common-const' -import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' +import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' const TOOLTIP_TEXT = 'Currently in development and not widely adopted yet. If you are experiencing issues, contact your wallet provider.' @@ -35,24 +39,30 @@ export const walletConnectV2Option = { const WC_PROJECT_ID = process.env.REACT_APP_WC_PROJECT_ID const WC_DEFAULT_PROJECT_ID = 'a6cc11517a10f6f12953fd67b1eb67e7' -function createWalletConnectV2Connector( - chainId: SupportedChainId -): [WalletConnectV2Connector, Web3ReactHooks, Web3ReactStore] { - return initializeConnector( +function createWalletConnectV2Connector(chainId: SupportedChainId): [AsyncConnector, Web3ReactHooks, Web3ReactStore] { + return initializeConnector( (actions) => - new WalletConnectV2Connector({ + new AsyncConnector( + () => + import('../connectors/WalletConnectV2Connector').then( + (m) => + new m.WalletConnectV2Connector({ + actions, + onError(error) { + console.error('WalletConnect2 ERROR:', error) + }, + options: { + projectId: WC_PROJECT_ID || WC_DEFAULT_PROJECT_ID, + chains: [chainId], + optionalChains: ALL_SUPPORTED_CHAIN_IDS, + showQrModal: true, + rpcMap: RPC_URLS, + }, + }) + ), actions, - onError(error) { - console.error('WalletConnect2 ERROR:', error) - }, - options: { - projectId: WC_PROJECT_ID || WC_DEFAULT_PROJECT_ID, - chains: [chainId], - optionalChains: ALL_SUPPORTED_CHAIN_IDS, - showQrModal: true, - rpcMap: RPC_URLS, - }, - }) + onError + ) ) } @@ -74,6 +84,14 @@ function createWalletConnectV2Connector( function createWc2Connection(chainId = getCurrentChainIdFromUrl()): Web3ReactConnection { let [web3WalletConnectV2, web3WalletConnectV2Hooks] = createWalletConnectV2Connector(chainId) + web3WalletConnectV2Hooks.useProvider = function useProvider() { + const [customProvider, setCustomProvider] = useState(undefined) + + web3WalletConnectV2.events.on(ASYNC_CUSTOM_PROVIDER_EVENT, setCustomProvider) + + return customProvider + } + let onActivate: (() => void) | undefined const proxyConnector = new Proxy( @@ -81,7 +99,7 @@ function createWc2Connection(chainId = getCurrentChainIdFromUrl()): Web3ReactCon { get: (target, p, receiver) => Reflect.get(web3WalletConnectV2, p, receiver), getOwnPropertyDescriptor: (target, p) => Reflect.getOwnPropertyDescriptor(web3WalletConnectV2, p), - getPrototypeOf: () => WalletConnectV2Connector.prototype, + getPrototypeOf: () => AsyncConnector.prototype, set: (target, p, receiver) => Reflect.set(web3WalletConnectV2, p, receiver), } ) as typeof web3WalletConnectV2 From c09745ef335bbddbedb2bea183a2fa975f173f30 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Thu, 21 Sep 2023 18:27:29 +0300 Subject: [PATCH 10/36] refactor: remove amplitude analytics (#3137) * refactor: remove amplitude analytics * chore: remove unused code * chore: fix build * chore: fix lint --- .../components/AmplitudeAnalytics/Trace.tsx | 64 -------------- .../AmplitudeAnalytics/TraceEvent.tsx | 71 --------------- .../AmplitudeAnalytics/constants.ts | 79 ----------------- .../components/AmplitudeAnalytics/index.ts | 88 ------------------- .../src/legacy/components/Markdown/index.tsx | 6 +- .../CommonBases/CommonBasesMod.tsx | 40 ++------- .../CurrencyList/CurrencyListMod.tsx | 41 +-------- .../CurrencySearch/CurrencySearchMod.tsx | 6 +- .../ImportToken/ImportTokenMod.tsx | 17 +--- .../application/containers/App/index.tsx | 2 - .../src/pages/About/index.tsx | 7 +- .../pages/Account/Tokens/TokensOverview.tsx | 6 +- .../src/pages/Account/index.tsx | 6 +- .../src/pages/Faq/AffiliateFaq.tsx | 8 +- .../src/pages/Faq/EthFlowFaq.tsx | 9 +- .../src/pages/Faq/LimitOrdersFaq.tsx | 7 +- .../src/pages/Faq/ProtocolFaq.tsx | 8 +- .../src/pages/Faq/TokenFaq.tsx | 7 +- .../src/pages/Faq/TradingFaq.tsx | 8 +- apps/cowswap-frontend/src/pages/Faq/index.tsx | 6 +- apps/cowswap-frontend/vite.config.ts | 3 +- 21 files changed, 38 insertions(+), 451 deletions(-) delete mode 100644 apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/Trace.tsx delete mode 100644 apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/TraceEvent.tsx delete mode 100644 apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/constants.ts delete mode 100644 apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/index.ts diff --git a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/Trace.tsx b/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/Trace.tsx deleted file mode 100644 index 52fe79b8a1..0000000000 --- a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/Trace.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { createContext, memo, PropsWithChildren, useContext, useEffect, useMemo } from 'react' - -import { - ElementName, - EventName, - ModalName, - PageName, - SectionName, -} from 'legacy/components/AmplitudeAnalytics/constants' // Mod - -import { sendAnalyticsEvent } from '.' - -export interface ITraceContext { - // Highest order context: eg Swap or Explore. - page?: PageName - - // Enclosed section name. For contexts with modals, refers to the - // section of the page from which the user triggered the modal. - section?: SectionName - - modal?: ModalName - - // Element name mostly used to identify events sources - // Does not need to be unique given the higher order page and section. - element?: ElementName -} - -export const TraceContext = createContext({}) - -type TraceProps = { - shouldLogImpression?: boolean // whether to log impression on mount - name?: EventName - properties?: Record -} & ITraceContext - -/** - * Sends an analytics event on mount (if shouldLogImpression is set), - * and propagates the context to child traces. - */ -export const Trace = memo( - ({ shouldLogImpression, name, children, page, section, element, properties }: PropsWithChildren) => { - const parentTrace = useContext(TraceContext) - - const combinedProps = useMemo( - () => ({ - ...parentTrace, - ...Object.fromEntries(Object.entries({ page, section, element }).filter(([_, v]) => v !== undefined)), - }), - [element, parentTrace, page, section] - ) - - useEffect(() => { - if (shouldLogImpression) { - sendAnalyticsEvent(name ?? EventName.PAGE_VIEWED, { ...combinedProps, ...properties }) - } - // Impressions should only be logged on mount. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) - - return {children} - } -) - -Trace.displayName = 'Trace' diff --git a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/TraceEvent.tsx b/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/TraceEvent.tsx deleted file mode 100644 index 08480d63f5..0000000000 --- a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/TraceEvent.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { Children, cloneElement, isValidElement, memo, PropsWithChildren, SyntheticEvent } from 'react' - -import { Event, EventName } from './constants' -import { ITraceContext, Trace, TraceContext } from './Trace' - -import { sendAnalyticsEvent } from '.' - -type TraceEventProps = { - events: Event[] - name: EventName - properties?: Record -} & ITraceContext - -/** - * Analytics instrumentation component that wraps event callbacks with logging logic. - * - * @example - * - * - * - */ -export const TraceEvent = memo((props: PropsWithChildren) => { - const { name, properties, events, children, ...traceProps } = props - - return ( - - - {(traceContext) => - Children.map(children, (child) => { - if (!isValidElement(child)) { - return child - } - - // For each child, augment event handlers defined in `events` with event tracing. - return cloneElement(child, getEventHandlers(child, traceContext, events, name, properties)) - }) - } - - - ) -}) - -TraceEvent.displayName = 'TraceEvent' - -/** - * Given a set of child element and event props, returns a spreadable - * object of the event handlers augmented with analytics logging. - */ -function getEventHandlers( - child: React.ReactElement, - traceContext: ITraceContext, - events: Event[], - name: EventName, - properties?: Record -) { - const eventHandlers: Partial) => void>> = {} - - for (const event of events) { - eventHandlers[event] = (eventHandlerArgs: unknown) => { - // call child event handler with original arguments, must be in array - const args = Array.isArray(eventHandlerArgs) ? eventHandlerArgs : [eventHandlerArgs] - child.props[event]?.apply(child, args) - - // augment handler with analytics logging - sendAnalyticsEvent(name, { ...traceContext, ...properties, action: event }) - } - } - - // return a spreadable event handler object - return eventHandlers -} diff --git a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/constants.ts b/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/constants.ts deleted file mode 100644 index e73d0f2ab5..0000000000 --- a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/constants.ts +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Event names that can occur in this application. - * - * Subject to change as new features are added and new events are defined - * and logged. - */ -export enum EventName { - PAGE_VIEWED = 'Page Viewed', - SWAP_SUBMITTED = 'Swap Submitted', - TOKEN_IMPORTED = 'Token Imported', - TOKEN_SELECTED = 'Token Selected', - TOKEN_SELECTOR_OPENED = 'Token Selector Opened', - // alphabetize additional event names. -} - -/** - * Known pages in the app. Highest order context. - */ -export const enum PageName { - EXPLORE_PAGE = 'explore-page', - POOL_PAGE = 'pool-page', - SWAP_PAGE = 'swap-page', - VOTE_PAGE = 'vote-page', - // alphabetize additional page names. - ACCOUNT_OVERVIEW_PAGE = 'account-overview-page', - ACCOUNT_TOKENS_PAGE = 'account-tokens-page', - ABOUT_PAGE = 'about-page', - FAQ_OVERVIEW_PAGE = 'faq-overview-page', - FAQ_PROTOCOL_PAGE = 'faq-protocol-page', - FAQ_TOKEN_PAGE = 'faq-token-page', - FAQ_TRADING_PAGE = 'faq-trading-page', - FAQ_AFFILIATE_PAGE = 'faq-affiliate-page', - FAQ_LIMIT_ORDERS_PAGE = 'faq-limit-orders-page', - FAQ_ETH_FLOW = 'faq-eth-flow', - TOC_PAGE = 'toc-page', -} - -/** - * Sections. Disambiguates low-level elements that may share a name. - * eg a `back` button in a modal will have the same `element`, - * but a different `section`. - */ -export const enum SectionName { - CURRENCY_INPUT_PANEL = 'swap-currency-input', - CURRENCY_OUTPUT_PANEL = 'swap-currency-output', - // alphabetize additional section names. -} - -/** Known modals for analytics purposes. */ -export const enum ModalName { - SWAP = 'swap-modal', - TOKEN_SELECTOR = 'token-selector-modal', - // alphabetize additional modal names. -} - -/** - * Known element names for analytics purposes. - * Use to identify low-level components given a TraceContext - */ -export const enum ElementName { - COMMON_BASES_CURRENCY_BUTTON = 'common-bases-currency-button', - CONFIRM_SWAP_BUTTON = 'confirm-swap-or-send', - IMPORT_TOKEN_BUTTON = 'import-token-button', - SWAP_BUTTON = 'swap-button', - TOKEN_SELECTOR_ROW = 'token-selector-row', - // alphabetize additional element names. -} - -/** - * Known events that trigger callbacks. - * @example - * - */ -export enum Event { - onClick = 'onClick', - onKeyPress = 'onKeyPress', - onSelect = 'onSelect', - // alphabetize additional events. -} diff --git a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/index.ts b/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/index.ts deleted file mode 100644 index d6533cc94d..0000000000 --- a/apps/cowswap-frontend/src/legacy/components/AmplitudeAnalytics/index.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Identify, identify, init, track } from '@amplitude/analytics-browser' - -/** - * Initializes Amplitude with API key for project. - * - * Uniswap has two Amplitude projects: test and production. You must be a - * member of the organization on Amplitude to view details. - */ -export function initializeAnalytics(isDevEnvironment = process.env.NODE_ENV === 'development') { - if (isDevEnvironment) return - - const API_KEY = process.env.REACT_APP_AMPLITUDE_KEY - if (typeof API_KEY === 'undefined') { - throw new Error(`REACT_APP_AMPLITUDE_KEY must be a defined environment variable`) - } - - init( - API_KEY, - /* userId= */ undefined, // User ID should be undefined to let Amplitude default to Device ID - /* options= */ { - // Disable tracking of private user information by Amplitude - trackingOptions: { - ipAddress: false, - carrier: false, - city: false, - region: false, - country: false, - dma: false, // designated market area - }, - } - ) -} - -/** Sends an event to Amplitude. */ -export function sendAnalyticsEvent(eventName: string, eventProperties?: Record) { - if (process.env.NODE_ENV === 'development') { - console.log(`[amplitude(${eventName})]: ${JSON.stringify(eventProperties)}`) - return - } - - track(eventName, eventProperties) -} - -/** - * Class that exposes methods to mutate the User Model's properties in - * Amplitude that represents the current session's user. - * - * See https://help.amplitude.com/hc/en-us/articles/115002380567-User-properties-and-event-properties - * for details. - */ -class UserModel { - constructor(private isDevEnvironment = process.env.NODE_ENV === 'development') {} - - private log(method: string, ...parameters: unknown[]) { - console.debug(`[amplitude(Identify)]: ${method}(${parameters})`) - } - - private call(mutate: (event: Identify) => Identify) { - if (this.isDevEnvironment) { - const log = (_: Identify, method: string) => this.log.bind(this, method) - mutate(new Proxy(new Identify(), { get: log })) - return - } - identify(mutate(new Identify())) - } - - set(key: string, value: string | number) { - this.call((event) => event.set(key, value)) - } - - setOnce(key: string, value: string | number) { - this.call((event) => event.setOnce(key, value)) - } - - add(key: string, value: string | number) { - this.call((event) => event.add(key, typeof value === 'number' ? value : 0)) - } - - postInsert(key: string, value: string | number) { - this.call((event) => event.postInsert(key, value)) - } - - remove(key: string, value: string | number) { - this.call((event) => event.remove(key, value)) - } -} - -export const user = new UserModel() diff --git a/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx b/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx index 0c60c40a12..5b7bc15e28 100644 --- a/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Markdown/index.tsx @@ -7,8 +7,6 @@ import ReactMarkdownHtml from 'react-markdown/with-html' import styled from 'styled-components/macro' import { WithClassName } from 'types' -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { LinkScrollable, Link } from 'legacy/components/Link' import { Page, Title, Content } from 'modules/application/pure/Page' @@ -34,7 +32,7 @@ const MarkdownContent = (props: ReactMarkdownPropsBase & { children: string }) = export function MarkdownPage({ contentFile, title, className }: MarkdownParams) { const { error, file } = useFetchFile(contentFile) return ( - + <> {title && {title}} @@ -42,6 +40,6 @@ export function MarkdownPage({ contentFile, title, className }: MarkdownParams) {error && {error}} - + ) } diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx index 5cebfc1340..5843ee98a6 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CommonBases/CommonBasesMod.tsx @@ -1,19 +1,17 @@ import { currencyId } from '@cowprotocol/common-utils' import { TokenSymbol, AutoRow } from '@cowprotocol/ui' -import { Currency, Token } from '@uniswap/sdk-core' +import { Currency } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { Text } from 'rebass' import styled from 'styled-components/macro' -import { ElementName, Event, EventName } from 'legacy/components/AmplitudeAnalytics/constants' -import { TraceEvent } from 'legacy/components/AmplitudeAnalytics/TraceEvent' import QuestionHelper from 'legacy/components/QuestionHelper' import { useFavouriteOrCommonTokens } from 'legacy/hooks/useFavouriteOrCommonTokens' import { CurrencyLogo } from 'common/pure/CurrencyLogo' -import { BaseWrapper, CommonBasesRow, MobileWrapper } from './index' // mod +import { BaseWrapper, CommonBasesRow, MobileWrapper } from './index' export const StyledScrollarea = styled.div` overflow-y: auto; // fallback for 'overlay' @@ -27,35 +25,16 @@ export const StyledScrollarea = styled.div` `} ` -const formatAnalyticsEventProperties = ( - currency: Currency, - tokenAddress: string | undefined, - searchQuery: string, - isAddressSearch: string | false -) => ({ - token_symbol: currency?.symbol, - token_chain_id: currency?.chainId, - ...(tokenAddress ? { token_address: tokenAddress } : {}), - is_suggested_token: true, - is_selected_from_list: false, - is_imported_by_user: false, - ...(isAddressSearch === false - ? { search_token_symbol_input: searchQuery } - : { search_token_address_input: isAddressSearch }), -}) - const MAX_LENGTH_OVERFLOW = 12 export default function CommonBases({ onSelect, selectedCurrency, - searchQuery, - isAddressSearch, }: { chainId?: number selectedCurrency?: Currency | null onSelect: (currency: Currency) => void - searchQuery: string - isAddressSearch: string | false + searchQuery?: string + isAddressSearch?: string | false }) { const tokens = useFavouriteOrCommonTokens() @@ -71,16 +50,9 @@ export default function CommonBases({ {tokens.map((currency: Currency) => { const isSelected = selectedCurrency?.equals(currency) - const tokenAddress = currency instanceof Token ? currency?.address : undefined return ( - + <> !isSelected && e.key === 'Enter' && onSelect(currency)} @@ -93,7 +65,7 @@ export default function CommonBases({ - + ) })} diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx index a190f4ab4d..354a7510c1 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencyList/CurrencyListMod.tsx @@ -12,8 +12,6 @@ import { FixedSizeList } from 'react-window' import { Text } from 'rebass' import styled from 'styled-components/macro' -import { ElementName, Event, EventName } from 'legacy/components/AmplitudeAnalytics/constants' -import { TraceEvent } from 'legacy/components/AmplitudeAnalytics/TraceEvent' import { LightGreyCard } from 'legacy/components/Card' import Column from 'legacy/components/Column' import QuestionHelper from 'legacy/components/QuestionHelper' @@ -118,7 +116,6 @@ function CurrencyRow({ otherSelected, style, showCurrencyAmount, - eventProperties, isUnsupported, // gp-swap added isPermitCompatible, // gp-swap added allTokens, @@ -131,7 +128,6 @@ function CurrencyRow({ otherSelected: boolean style: CSSProperties showCurrencyAmount?: boolean - eventProperties: Record isUnsupported: boolean // gp-added isPermitCompatible: boolean // gp-added allTokens: { [address: string]: Token } // gp-added @@ -150,12 +146,7 @@ function CurrencyRow({ // only show add or remove buttons if not on selected list return ( - + <> )} - + ) } @@ -240,25 +231,6 @@ interface TokenRowProps { style: CSSProperties } -const formatAnalyticsEventProperties = ( - token: Token, - index: number, - data: any[], - searchQuery: string, - isAddressSearch: string | false -) => ({ - token_symbol: token?.symbol, - token_address: token?.address, - is_suggested_token: false, - is_selected_from_list: true, - scroll_position: '', - token_list_index: index, - token_list_length: data.length, - ...(isAddressSearch === false - ? { search_token_symbol_input: searchQuery } - : { search_token_address_input: isAddressSearch }), -}) - // TODO: refactor the component export default function CurrencyList({ height, @@ -272,8 +244,6 @@ export default function CurrencyList({ setImportToken, showCurrencyAmount, isLoading, - searchQuery, - isAddressSearch, additionalTokens, BalanceComponent = Balance, // gp-swap added TokenTagsComponent = TokenTags, // gp-swap added @@ -289,8 +259,8 @@ export default function CurrencyList({ setImportToken: (token: Token) => void showCurrencyAmount?: boolean isLoading: boolean - searchQuery: string - isAddressSearch: string | false + searchQuery?: string + isAddressSearch?: string | false additionalTokens?: Currency[] BalanceComponent?: (params: { balance: CurrencyAmount }) => JSX.Element // gp-swap added TokenTagsComponent?: (params: { currency: Currency; isUnsupported: boolean }) => JSX.Element // gp-swap added @@ -373,7 +343,6 @@ export default function CurrencyList({ isUnsupported={isUnsupported} isPermitCompatible={isPermitCompatible} // gp-swap added showCurrencyAmount={showCurrencyAmount} - eventProperties={formatAnalyticsEventProperties(token, index, data, searchQuery, isAddressSearch)} /> ) } else { @@ -389,8 +358,6 @@ export default function CurrencyList({ showImportView, showCurrencyAmount, isLoading, - isAddressSearch, - searchQuery, isUnsupportedToken, BalanceComponent, TokenTagsComponent, diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx index f4d26e2e04..693e2efdfa 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/CurrencySearch/CurrencySearchMod.tsx @@ -13,8 +13,6 @@ import { FixedSizeList } from 'react-window' import { Text } from 'rebass' import styled, { DefaultTheme } from 'styled-components/macro' -import { EventName, ModalName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import Column from 'legacy/components/Column' import CommonBases from 'legacy/components/SearchModal/CommonBases' import CurrencyList from 'legacy/components/SearchModal/CurrencyList' @@ -208,7 +206,7 @@ export function CurrencySearch({ }, []) return ( - + <> @@ -288,6 +286,6 @@ export function CurrencySearch({ - + ) } diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx index 73fc7cca95..f752e237ea 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ImportToken/ImportTokenMod.tsx @@ -9,8 +9,6 @@ import { transparentize } from 'polished' import { AlertCircle, ArrowLeft } from 'react-feather' import styled from 'styled-components/macro' -import { ElementName, Event, EventName } from 'legacy/components/AmplitudeAnalytics/constants' -import { TraceEvent } from 'legacy/components/AmplitudeAnalytics/TraceEvent' import Card from 'legacy/components/Card' import { AutoColumn } from 'legacy/components/Column' import { PaddedColumn } from 'legacy/components/SearchModal/styleds' @@ -50,12 +48,6 @@ export interface ImportProps { CardComponent: (props: CardComponentProps) => JSX.Element // mod } -const formatAnalyticsEventProperties = (tokens: Token[]) => ({ - token_symbols: tokens.map((token) => token?.symbol), - token_addresses: tokens.map((token) => token?.address), - token_chain_ids: tokens.map((token) => token?.chainId), -}) - export function ImportToken(props: ImportProps) { const { tokens, list, onBack, onDismiss, handleCurrencySelect } = props const theme = useTheme() @@ -87,12 +79,7 @@ export function ImportToken(props: ImportProps) { {tokens.map((token) => ( ))} - + <> Import - +
) diff --git a/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx b/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx index 757a14fce6..9af824dfc5 100644 --- a/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx +++ b/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx @@ -1,6 +1,5 @@ import { isInjectedWidget } from '@cowprotocol/common-utils' -import { initializeAnalytics } from 'legacy/components/AmplitudeAnalytics' import ErrorBoundary from 'legacy/components/ErrorBoundary' import Footer from 'legacy/components/Footer' import Header from 'legacy/components/Header' @@ -18,7 +17,6 @@ import * as styledEl from './styled' import { useAnalyticsReporter } from '../../../../common/hooks/useAnalyticsReporter' export function App() { - initializeAnalytics() useAnalyticsReporter() useInitializeUtm() diff --git a/apps/cowswap-frontend/src/pages/About/index.tsx b/apps/cowswap-frontend/src/pages/About/index.tsx index 1e92bc226e..91712a3f34 100644 --- a/apps/cowswap-frontend/src/pages/About/index.tsx +++ b/apps/cowswap-frontend/src/pages/About/index.tsx @@ -7,9 +7,6 @@ import { ExternalLink as ExternalLinkTheme } from '@cowprotocol/ui' import { Link } from 'react-router-dom' import styled from 'styled-components/macro' -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' - import { PageTitle } from 'modules/application/containers/PageTitle' import { Page, Title, Content, GdocsListStyle } from 'modules/application/pure/Page' @@ -32,7 +29,7 @@ const Wrapper = styled(Page)` export default function About() { return ( - + <> About @@ -115,6 +112,6 @@ export default function About() {

-
+ ) } diff --git a/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx b/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx index 5df883e2b6..cdcfa8efb1 100644 --- a/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx +++ b/apps/cowswap-frontend/src/pages/Account/Tokens/TokensOverview.tsx @@ -9,8 +9,6 @@ import { useWeb3React } from '@web3-react/core' import { Trans, t } from '@lingui/macro' import { Check } from 'react-feather' -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { ContentWrapper as SearchInputFormatter } from 'legacy/components/SearchModal/CurrencySearch' import { TokenSearchInput } from 'legacy/components/Tokens/styled' import TokensTable from 'legacy/components/Tokens/TokensTable' @@ -151,7 +149,7 @@ export default function TokensOverview() { }, [account, chainId, prevAccount, prevChainId, prevSelectedView, selectedView]) return ( - + <> {!isProviderNetworkUnsupported && ( @@ -209,6 +207,6 @@ export default function TokensOverview() { {isProviderNetworkUnsupported ? 'Unsupported network' : renderTableContent()} - + ) } diff --git a/apps/cowswap-frontend/src/pages/Account/index.tsx b/apps/cowswap-frontend/src/pages/Account/index.tsx index 645d6d2c90..9a80bfb7f1 100644 --- a/apps/cowswap-frontend/src/pages/Account/index.tsx +++ b/apps/cowswap-frontend/src/pages/Account/index.tsx @@ -2,8 +2,6 @@ import { lazy, Suspense } from 'react' import { useLocation, Outlet } from 'react-router-dom' -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { Loading } from 'legacy/components/FlashingLoading' import { PageTitle } from 'modules/application/containers/PageTitle' @@ -35,7 +33,7 @@ function _getPropsFromRoute(route: string) { // Note: As we build these single pages, we will remove this component in the future export const AccountOverview = () => { return ( - + <> @@ -43,7 +41,7 @@ export const AccountOverview = () => { - + ) } diff --git a/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx index a2c55ddcb0..50e68d9a92 100644 --- a/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/AffiliateFaq.tsx @@ -2,8 +2,6 @@ import { BARN_URL, PRODUCTION_URL } from '@cowprotocol/common-const' import { Link } from 'react-router-dom' -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { LinkScrollable } from 'legacy/components/Link' import { PageTitle } from 'modules/application/containers/PageTitle' @@ -18,8 +16,6 @@ import ToC from './ToC' import { Footer } from '.' -// AmplitudeAnalytics - const PROD = `https://${PRODUCTION_URL}` const BARN = `https://${BARN_URL}` @@ -27,7 +23,7 @@ export default function AffiliateFaq() { const { toc, faqRef } = useToC() return ( - + <> @@ -204,6 +200,6 @@ export default function AffiliateFaq() { - + ) } diff --git a/apps/cowswap-frontend/src/pages/Faq/EthFlowFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/EthFlowFaq.tsx index 8def34fb02..b839996389 100644 --- a/apps/cowswap-frontend/src/pages/Faq/EthFlowFaq.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/EthFlowFaq.tsx @@ -1,6 +1,3 @@ -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' - import { PageTitle } from 'modules/application/containers/PageTitle' import { Page, Content } from 'modules/application/pure/Page' @@ -11,13 +8,11 @@ import ToC from './ToC' import { Footer } from '.' -// AmplitudeAnalytics - export default function EthFlowFAQ() { const { toc, faqRef } = useToC() return ( - + <> @@ -347,6 +342,6 @@ export default function EthFlowFAQ() { - + ) } diff --git a/apps/cowswap-frontend/src/pages/Faq/LimitOrdersFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/LimitOrdersFaq.tsx index e1295bec70..6a76ce33c0 100644 --- a/apps/cowswap-frontend/src/pages/Faq/LimitOrdersFaq.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/LimitOrdersFaq.tsx @@ -1,6 +1,3 @@ -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' - import { PageTitle } from 'modules/application/containers/PageTitle' import { Content, Page } from 'modules/application/pure/Page' @@ -15,7 +12,7 @@ export default function LimitOrderFAQ() { const { toc, faqRef } = useToC() return ( - + <> @@ -228,6 +225,6 @@ export default function LimitOrderFAQ() { - + ) } diff --git a/apps/cowswap-frontend/src/pages/Faq/ProtocolFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/ProtocolFaq.tsx index cf17adf769..182a9731e3 100644 --- a/apps/cowswap-frontend/src/pages/Faq/ProtocolFaq.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/ProtocolFaq.tsx @@ -1,5 +1,3 @@ -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { LinkScrollable } from 'legacy/components/Link' import { PageTitle } from 'modules/application/containers/PageTitle' @@ -12,13 +10,11 @@ import ToC from './ToC' import { Footer } from '.' -// AmplitudeAnalytics - export default function ProtocolFaq() { const { toc, faqRef } = useToC() return ( - + <> @@ -271,6 +267,6 @@ export default function ProtocolFaq() { - + ) } diff --git a/apps/cowswap-frontend/src/pages/Faq/TokenFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/TokenFaq.tsx index 37158f0814..9119e8a239 100644 --- a/apps/cowswap-frontend/src/pages/Faq/TokenFaq.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/TokenFaq.tsx @@ -1,8 +1,5 @@ import { Link } from 'react-router-dom' -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' - import { PageTitle } from 'modules/application/containers/PageTitle' import { Page, Content } from 'modules/application/pure/Page' @@ -19,7 +16,7 @@ export default function TokenFaq() { const { toc, faqRef } = useToC() return ( - + <> @@ -134,6 +131,6 @@ export default function TokenFaq() { - + ) } diff --git a/apps/cowswap-frontend/src/pages/Faq/TradingFaq.tsx b/apps/cowswap-frontend/src/pages/Faq/TradingFaq.tsx index f99625aa34..1a5b9c0ffa 100644 --- a/apps/cowswap-frontend/src/pages/Faq/TradingFaq.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/TradingFaq.tsx @@ -1,5 +1,3 @@ -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { LinkScrollable } from 'legacy/components/Link' import { PageTitle } from 'modules/application/containers/PageTitle' @@ -12,13 +10,11 @@ import ToC from './ToC' import { Footer } from '.' -// AmplitudeAnalytics - export default function TokenFaq() { const { toc, faqRef } = useToC() return ( - + <> @@ -238,6 +234,6 @@ export default function TokenFaq() { - + ) } diff --git a/apps/cowswap-frontend/src/pages/Faq/index.tsx b/apps/cowswap-frontend/src/pages/Faq/index.tsx index cb1f9dbfba..378ba11468 100644 --- a/apps/cowswap-frontend/src/pages/Faq/index.tsx +++ b/apps/cowswap-frontend/src/pages/Faq/index.tsx @@ -10,8 +10,6 @@ import { import { Link } from 'react-router-dom' -import { PageName } from 'legacy/components/AmplitudeAnalytics/constants' -import { Trace } from 'legacy/components/AmplitudeAnalytics/Trace' import { StyledInternalLink } from 'legacy/theme' import { PageTitle } from 'modules/application/containers/PageTitle' @@ -59,7 +57,7 @@ export function Footer() { export default function Faq() { const { toc, faqRef } = useToC() return ( - + <> @@ -202,6 +200,6 @@ export default function Faq() { - + ) } diff --git a/apps/cowswap-frontend/vite.config.ts b/apps/cowswap-frontend/vite.config.ts index 8544e0343b..2e0ad34ee2 100644 --- a/apps/cowswap-frontend/vite.config.ts +++ b/apps/cowswap-frontend/vite.config.ts @@ -123,7 +123,8 @@ export default defineConfig(({ mode }) => { output: { manualChunks(id) { if (id.includes('@1inch')) return '@1inch' - if (id.includes('@amplitude')) return '@amplitude' + if (id.includes('@cowprotocol')) return '@cowprotocol' + if (id.includes('@metamask') || id.includes('elliptic')) return '@metamask' if (id.includes('@safe-global') || id.includes('viem')) return '@safe-global' if (id.includes('@sentry')) return '@sentry' if (id.includes('@uniswap')) return '@uniswap' From 9807d1f18330394ac62bfc7784c6240628ab629f Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Thu, 21 Sep 2023 18:32:25 +0300 Subject: [PATCH 11/36] chore: add node memory limit --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 89d86aa006..87f4ad382b 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,13 @@ }, "scripts": { "start": "nx run cowswap-frontend:serve", - "preview": "nx run cowswap-frontend:preview", - "cosmos:export": "nx run cowswap-frontend:cosmos:export", + "preview": "cross-env NODE_OPTIONS=--max-old-space-size=32768 nx run cowswap-frontend:preview", + "cosmos:export": "cross-env NODE_OPTIONS=--max-old-space-size=32768 nx run cowswap-frontend:cosmos:export", "test": "nx run-many -t test --output-style=stream", "e2e": "nx run-many -t e2e", "lint": "nx run-many -t lint", "prebuild": "nx run cowswap-frontend:i18n", - "build": "nx build cowswap-frontend", + "build": "cross-env NODE_OPTIONS=--max-old-space-size=32768 nx build cowswap-frontend", "prepare": "husky install", "postinstall": "yarn run patch-package", "analyze-build": "cross-env ANALYZE_BUNDLE=true ANALYZE_BUNDLE_TEMPLATE=sunburst yarn build" From 48671b27f29b0f2826d22af9f1b463d067b5c819 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Thu, 21 Sep 2023 19:02:13 +0300 Subject: [PATCH 12/36] chore: fix build --- apps/cowswap-frontend/vite.config.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/cowswap-frontend/vite.config.ts b/apps/cowswap-frontend/vite.config.ts index 2e0ad34ee2..0a183f0aaa 100644 --- a/apps/cowswap-frontend/vite.config.ts +++ b/apps/cowswap-frontend/vite.config.ts @@ -123,8 +123,6 @@ export default defineConfig(({ mode }) => { output: { manualChunks(id) { if (id.includes('@1inch')) return '@1inch' - if (id.includes('@cowprotocol')) return '@cowprotocol' - if (id.includes('@metamask') || id.includes('elliptic')) return '@metamask' if (id.includes('@safe-global') || id.includes('viem')) return '@safe-global' if (id.includes('@sentry')) return '@sentry' if (id.includes('@uniswap')) return '@uniswap' From 2738d2631104f364d13194dc66125d7a14b25a2c Mon Sep 17 00:00:00 2001 From: fairlight <31534717+fairlighteth@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:51:27 +0100 Subject: [PATCH 13/36] feat: custom recipient warning banner (#3130) * feat: add 3rd party banner * feat: icon component * feat: banner component * feat: banner component * feat: fix cosmos fixture * feat: fix cosmos fixture * feat: add checks * feat: add checks * feat: fix type * chore(recipient-warning): 3rd party recipient banner wire up (#3131) * fix: inline banner types * chore: add owner to ParsedOrder * chore: add receiverWalletBannerVisibility state * chore: use new state on activity details and receipt modal * chore: update previous hook from CustomRecipientWarningBanner * chore: simplify and export isPending util fn * chore: only show recipient warning banner when pending * chore: simplify message and do not mention the Safe * refactor: remove SwapModalHeaderMod * chore: only display on dismiss button when there's a dismiss fn * chore: show recipient warning on swap confirm modal * chore: show recipient warning on limit and twap confirm modals * fix: error handling for emulated twap orders * chore: remove unused hook useBannerVisibility * chore: refactor getColorEnums * chore: fix import * chore: remove redundant try/catch * chore: fix imports * chore: fix imports --------- Co-authored-by: Leandro Co-authored-by: Alexandr Kazachenko --- .../hooks/useCategorizeRecentActivity.ts | 6 +- .../src/common/pure/ButtonSecondary/index.tsx | 6 +- .../src/common/pure/Icon/index.cosmos.tsx | 26 ++ .../src/common/pure/Icon/index.tsx | 80 ++++++ .../src/common/pure/InlineBanner/banners.tsx | 48 +++- .../common/pure/InlineBanner/index.cosmos.tsx | 10 +- .../src/common/pure/InlineBanner/index.tsx | 146 ++++++---- .../receiverWalletBannerVisibility/atom.ts | 21 ++ .../receiverWalletBannerVisibility/hooks.ts | 14 + .../receiverWalletBannerVisibility/index.ts | 1 + .../swap/ConfirmSwapModal/index.tsx | 6 +- .../components/swap/FeeInformationTooltip.tsx | 2 +- .../SwapModalHeader/SwapModalHeaderMod.tsx | 253 ----------------- .../components/swap/SwapModalHeader/index.tsx | 266 +++++++++++++++--- .../components/swap/SwapModalHeader/styled.ts | 73 +++++ .../Transaction/ActivityDetails.tsx | 57 +++- .../account/containers/Transaction/styled.ts | 25 +- .../containers/LimitOrdersWarnings/index.tsx | 13 +- .../ordersTable/pure/ReceiptModal/index.tsx | 32 ++- .../ordersTable/pure/ReceiptModal/styled.ts | 4 + .../pure/banners/TwapSuggestionBanner.tsx | 2 +- .../containers/TwapFormWarnings/index.tsx | 15 +- .../warnings/FallbackHandlerWarning.tsx | 4 +- .../warnings/SwapPriceDifferenceWarning.tsx | 2 +- .../warnings/UnsupportedWalletWarning.tsx | 4 +- .../twap/hooks/useEmulatedTwapOrders.ts | 13 +- .../modules/twap/utils/emulateTwapAsOrder.ts | 2 +- .../src/utils/orderUtils/parseOrder.ts | 2 + 28 files changed, 722 insertions(+), 411 deletions(-) create mode 100644 apps/cowswap-frontend/src/common/pure/Icon/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/common/pure/Icon/index.tsx create mode 100644 apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/atom.ts create mode 100644 apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/hooks.ts create mode 100644 apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/index.ts delete mode 100644 apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx create mode 100644 apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/styled.ts diff --git a/apps/cowswap-frontend/src/common/hooks/useCategorizeRecentActivity.ts b/apps/cowswap-frontend/src/common/hooks/useCategorizeRecentActivity.ts index a19dd1a91d..14a67c4b22 100644 --- a/apps/cowswap-frontend/src/common/hooks/useCategorizeRecentActivity.ts +++ b/apps/cowswap-frontend/src/common/hooks/useCategorizeRecentActivity.ts @@ -2,12 +2,12 @@ import { useMemo } from 'react' import { OrderClass } from '@cowprotocol/cow-sdk' -import { useRecentActivity, TransactionAndOrder } from 'legacy/hooks/useRecentActivity' -import { PENDING_STATES } from 'legacy/state/orders/actions' +import { useRecentActivity } from 'legacy/hooks/useRecentActivity' +import { OrderStatus, PENDING_STATES } from 'legacy/state/orders/actions' import { getIsFinalizedOrder } from 'utils/orderUtils/getIsFinalizedOrder' -const isPending = (data: TransactionAndOrder) => PENDING_STATES.includes(data.status) +export const isPending = ({ status }: { status: OrderStatus }) => PENDING_STATES.includes(status) export function useCategorizeRecentActivity() { // Returns all RECENT (last day) transaction and orders in 2 arrays: pending and confirmed diff --git a/apps/cowswap-frontend/src/common/pure/ButtonSecondary/index.tsx b/apps/cowswap-frontend/src/common/pure/ButtonSecondary/index.tsx index b376304a41..24d7de6f44 100644 --- a/apps/cowswap-frontend/src/common/pure/ButtonSecondary/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/ButtonSecondary/index.tsx @@ -2,7 +2,7 @@ import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' -export const ButtonSecondary = styled.button` +export const ButtonSecondary = styled.button<{ padding?: string; minHeight?: string }>` background: var(${UI.COLOR_LIGHT_BLUE_OPACITY_90}); color: var(${UI.COLOR_LIGHT_BLUE}); font-size: 12px; @@ -12,8 +12,8 @@ export const ButtonSecondary = styled.button` border-radius: 12px; position: relative; transition: background 0.2s ease-in-out; - min-height: 35px; - padding: 0 12px; + min-height: ${({ minHeight = '35px' }) => minHeight}; + padding: ${({ padding = '0 12px' }) => padding}; cursor: pointer; white-space: nowrap; diff --git a/apps/cowswap-frontend/src/common/pure/Icon/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/Icon/index.cosmos.tsx new file mode 100644 index 0000000000..85c6f61220 --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/Icon/index.cosmos.tsx @@ -0,0 +1,26 @@ +import styled from 'styled-components/macro'; + +import { UI } from 'common/constants/theme' + +import { Icon, IconType } from './index'; + +const Wrapper = styled.div` + width: 400px; + height: 400px; + background: var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: var(${UI.BORDER_RADIUS_NORMAL}); + display: flex; + align-items: center; + justify-content: center; + margin: 100px; +`; + +const IconFixtures = { + 'icon ALERT / default size': ( + + + + ), +}; + +export default IconFixtures; diff --git a/apps/cowswap-frontend/src/common/pure/Icon/index.tsx b/apps/cowswap-frontend/src/common/pure/Icon/index.tsx new file mode 100644 index 0000000000..88a1c94d73 --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/Icon/index.tsx @@ -0,0 +1,80 @@ +import iconInformation from '@cowprotocol/assets/cow-swap/alert-circle.svg' +import iconAlert from '@cowprotocol/assets/cow-swap/alert.svg' +import iconDanger from '@cowprotocol/assets/cow-swap/alert.svg' +import iconSuccess from '@cowprotocol/assets/cow-swap/check.svg' + +import SVG from 'react-inlinesvg' +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +export enum IconType { + ALERT = 'ALERT', + INFORMATION = 'INFORMATION', + DANGER = 'DANGER', + SUCCESS = 'SUCCESS', +} + +const IconTypeMap: Record = { + [IconType.ALERT]: iconAlert, + [IconType.INFORMATION]: iconInformation, + [IconType.DANGER]: iconDanger, + [IconType.SUCCESS]: iconSuccess, +} + +interface IconProps { + image: keyof typeof IconType + size?: number + bgColor?: UI | string + color?: UI + description?: string + padding?: string + borderRadius?: string +} + +const Wrapper = styled.div>` + display: flex; + position: relative; + align-items: center; + justify-content: center; + width: ${({ size }) => size}px; + height: ${({ size }) => size}px; + min-width: ${({ size }) => size}px; + min-height: ${({ size }) => size}px; + border-radius: ${({ borderRadius }) => borderRadius}; + background-color: ${({ bgColor }) => (bgColor ? `var(${bgColor})` : 'transparent')}; + padding: ${({ padding }) => padding}; + + > svg { + object-fit: contain; + z-index: 2; + position: relative; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + } + + > svg > path { + fill: ${({ color = UI.COLOR_TEXT1 }) => `var(${color})`}; + } +` + +export function Icon({ + image, + size = 16, + bgColor, + color, + description, + borderRadius = '0', + padding = '0 3px 0 0', +}: IconProps) { + const svgPath = IconTypeMap[image] + + return ( + + + + ) +} diff --git a/apps/cowswap-frontend/src/common/pure/InlineBanner/banners.tsx b/apps/cowswap-frontend/src/common/pure/InlineBanner/banners.tsx index 84281bb088..0cf8c5c066 100644 --- a/apps/cowswap-frontend/src/common/pure/InlineBanner/banners.tsx +++ b/apps/cowswap-frontend/src/common/pure/InlineBanner/banners.tsx @@ -3,13 +3,19 @@ import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core' import { Nullish } from 'types' +import { ButtonSecondary } from '../ButtonSecondary' import { CowSwapSafeAppLink } from '../CowSwapSafeAppLink' -import { InlineBanner } from './index' +import { InlineBanner, InlineBannerProps } from './index' + +export enum BannerOrientation { + Horizontal = 'horizontal', + Vertical = 'vertical', +} export function BundleTxApprovalBanner() { return ( - + Token approval bundling

For your convenience, token approval and order placement will be bundled into a single transaction, streamlining @@ -26,7 +32,7 @@ export type BundleTxWrapBannerProps = { export function BundleTxWrapBanner({ nativeCurrencySymbol, wrappedCurrencySymbol }: BundleTxWrapBannerProps) { return ( - + Token wrapping bundling

For your convenience, CoW Swap will bundle all the necessary actions for this trade into a single transaction. @@ -48,7 +54,7 @@ export function BundleTxSafeWcBanner({ nativeCurrencySymbol, supportsWrapping }: const supportsWrappingText = supportsWrapping ? `${nativeCurrencySymbol} wrapping, ` : '' return ( - + Use Safe web app

Use the Safe web app for streamlined trading: {supportsWrappingText}token approval and orders bundled in one go! @@ -81,3 +87,37 @@ export function SmallVolumeWarningBanner({ feePercentage, feeAmount }: SmallVolu ) } + +type CustomRecipientBannerProps = InlineBannerProps & { onDismiss?: () => void } + +export function CustomRecipientWarningBanner({ + bannerType, + borderRadius, + orientation, + iconSize = 21, + iconPadding = '0', + padding = '10px 16px', + onDismiss, +}: CustomRecipientBannerProps) { + const handleDismiss = () => onDismiss?.() + + return ( + +

+ Caution: Order recipient address differs from order owner! +

+ {onDismiss && ( + + Dismiss + + )} +
+ ) +} diff --git a/apps/cowswap-frontend/src/common/pure/InlineBanner/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/InlineBanner/index.cosmos.tsx index f1ea3565a3..76693c91e5 100644 --- a/apps/cowswap-frontend/src/common/pure/InlineBanner/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/common/pure/InlineBanner/index.cosmos.tsx @@ -12,14 +12,14 @@ const Fixtures = { ), alert: ( - - This is an alert banner (explicitly passed type). + + This is an alert banner (explicitly passed bannerType). ), information: ( - + Token approval bundling

For your convenience, token approval and order placement will be bundled into a single transaction, @@ -30,14 +30,14 @@ const Fixtures = { ), success: ( - + Operation completed successfully! ), danger: ( - + Something went wrong! Please try again. diff --git a/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx b/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx index a2dcffa2e7..816b5e2f4d 100644 --- a/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/InlineBanner/index.tsx @@ -1,55 +1,74 @@ import { ReactNode } from 'react' -import iconInformation from '@cowprotocol/assets/cow-swap/alert-circle.svg' -import iconAlert from '@cowprotocol/assets/cow-swap/alert.svg' -import iconDanger from '@cowprotocol/assets/cow-swap/alert.svg' -import iconSuccess from '@cowprotocol/assets/cow-swap/check.svg' +import styled from 'styled-components/macro' -import { lighten, darken, transparentize } from 'polished' -import SVG from 'react-inlinesvg' -import styled, { useTheme } from 'styled-components/macro' // import useTheme +import { UI } from 'common/constants/theme' +import { Icon, IconType } from 'common/pure/Icon' +import { BannerOrientation } from 'common/pure/InlineBanner/banners' -type BannerType = 'alert' | 'information' | 'success' | 'danger' | 'savings' +export type BannerType = 'alert' | 'information' | 'success' | 'danger' | 'savings' -interface BannerConfig { - colorKey: Exclude - icon?: string +interface ColorEnums { + icon?: IconType iconText?: string + color: UI + bg: string + text: string } -const BANNER_CONFIG: Record = { +const colorEnumsMap: Record = { alert: { - icon: iconAlert, - colorKey: 'alert', + icon: IconType.ALERT, + color: UI.COLOR_ALERT, + bg: UI.COLOR_ALERT_BG, + text: UI.COLOR_ALERT_TEXT, }, information: { - icon: iconInformation, - colorKey: 'information', + icon: IconType.INFORMATION, + color: UI.COLOR_INFORMATION, + bg: UI.COLOR_INFORMATION_BG, + text: UI.COLOR_INFORMATION_TEXT, }, success: { - icon: iconSuccess, - colorKey: 'success', + icon: IconType.SUCCESS, + color: UI.COLOR_SUCCESS, + bg: UI.COLOR_SUCCESS_BG, + text: UI.COLOR_SUCCESS_TEXT, + }, + danger: { + icon: IconType.DANGER, + color: UI.COLOR_DANGER, + bg: UI.COLOR_DANGER_BG, + text: UI.COLOR_DANGER_TEXT, }, savings: { iconText: '💸', - colorKey: 'success', - }, - danger: { - icon: iconDanger, - colorKey: 'danger', + color: UI.COLOR_SUCCESS, + bg: UI.COLOR_SUCCESS_BG, + text: UI.COLOR_SUCCESS_TEXT, }, } -const Wrapper = styled.span<{ color: string }>` +function getColorEnums(bannerType: BannerType): ColorEnums { + return colorEnumsMap[bannerType] || colorEnumsMap.alert +} + +const Wrapper = styled.span<{ + colorEnums: ColorEnums + borderRadius?: string + orientation?: BannerOrientation + iconSize?: number + padding?: string +}>` display: flex; align-items: center; justify-content: center; - background: ${({ theme, color }) => (theme.darkMode ? transparentize(0.9, color) : transparentize(0.85, color))}; - color: ${({ theme, color }) => (theme.darkMode ? lighten(0.1, color) : darken(0.2, color))}; + background: ${({ colorEnums }) => `var(${colorEnums.bg})`}; + color: ${({ colorEnums }) => `var(${colorEnums.text})`}; gap: 24px 10px; - border-radius: 16px; + border-radius: ${({ borderRadius = '16px' }) => borderRadius}; margin: auto; - padding: 16px; + padding: ${({ padding = '16px' }) => padding}; font-size: 14px; font-weight: 400; line-height: 1.2; @@ -59,29 +78,10 @@ const Wrapper = styled.span<{ color: string }>` display: flex; justify-content: center; align-items: center; - flex-flow: column wrap; + flex-flow: ${({ orientation = BannerOrientation.Vertical }) => + orientation === BannerOrientation.Horizontal ? 'row' : 'column wrap'}; gap: 10px; width: 100%; - } - - > span > svg { - --size: 32px; - display: block; - min-width: var(--size); - min-height: var(--size); - width: var(--size); - height: var(--size); - object-fit: contain; - stroke: none !important; - } - - > span > svg > path { - fill: ${({ color }) => color}; - } - - > span { - display: flex; - flex-flow: row wrap; ${({ theme }) => theme.mediaWidth.upToSmall` flex-flow: column wrap; @@ -93,7 +93,7 @@ const Wrapper = styled.span<{ color: string }>` display: flex; align-items: center; gap: 6px; - color: ${({ theme, color }) => (theme.darkMode ? lighten(0.2, color) : darken(0.2, color))}; + color: ${({ colorEnums }) => `var(${colorEnums.text})`}; } > span > p { @@ -101,7 +101,8 @@ const Wrapper = styled.span<{ color: string }>` margin: auto; padding: 0; width: 100%; - text-align: center; + text-align: ${({ orientation = BannerOrientation.Vertical }) => + orientation === BannerOrientation.Horizontal ? 'left' : 'center'}; } > span > i { @@ -115,19 +116,46 @@ export type InlineBannerProps = { children?: ReactNode className?: string hideIcon?: boolean - type?: BannerType + bannerType?: BannerType + borderRadius?: string + orientation?: BannerOrientation + iconSize?: number + iconPadding?: string + padding?: string } -export function InlineBanner({ children, className, hideIcon, type = 'alert' }: InlineBannerProps) { - const theme = useTheme() - const config = BANNER_CONFIG[type] - const color = theme[config.colorKey] +export function InlineBanner({ + children, + className, + hideIcon, + bannerType = 'alert', + borderRadius, + orientation, + iconSize, + iconPadding, + padding, +}: InlineBannerProps) { + const colorEnums = getColorEnums(bannerType) return ( - + - {!hideIcon && config.icon && } - {!hideIcon && config.iconText && {config.iconText}} + {!hideIcon && colorEnums.icon && ( + + )} + {!hideIcon && colorEnums.iconText && {colorEnums.iconText}} {children} diff --git a/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/atom.ts b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/atom.ts new file mode 100644 index 0000000000..d6288955d7 --- /dev/null +++ b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/atom.ts @@ -0,0 +1,21 @@ +import { atom } from 'jotai' +import { atomWithStorage } from 'jotai/utils' + +export type WarningBannerVisibility = string[] + +const WARNING_BANNER_VISIBILITY_KEY = 'warningBannerVisibility:v0' + +export const hiddenReceiverWalletBannersAtom = atomWithStorage( + WARNING_BANNER_VISIBILITY_KEY, + [] +) + +export const hideReceiverWalletBannerAtom = atom(null, (get, set, orderId: string) => { + const hiddenBanners = get(hiddenReceiverWalletBannersAtom) + + if (hiddenBanners.includes(orderId)) { + return + } + + set(hiddenReceiverWalletBannersAtom, [...hiddenBanners, orderId]) +}) diff --git a/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/hooks.ts b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/hooks.ts new file mode 100644 index 0000000000..369e794ac8 --- /dev/null +++ b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/hooks.ts @@ -0,0 +1,14 @@ +import { useAtomValue, useSetAtom } from 'jotai' +import { useMemo } from 'react' + +import { hiddenReceiverWalletBannersAtom, hideReceiverWalletBannerAtom } from './atom' + +export function useIsReceiverWalletBannerHidden(orderId?: string): boolean { + const hiddenBanners = useAtomValue(hiddenReceiverWalletBannersAtom) + + return useMemo(() => !!orderId && hiddenBanners.includes(orderId), [hiddenBanners, orderId]) +} + +export function useHideReceiverWalletBanner() { + return useSetAtom(hideReceiverWalletBannerAtom) +} diff --git a/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/index.ts b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/index.ts new file mode 100644 index 0000000000..64c191af4c --- /dev/null +++ b/apps/cowswap-frontend/src/common/state/receiverWalletBannerVisibility/index.ts @@ -0,0 +1 @@ +export { useHideReceiverWalletBanner, useIsReceiverWalletBannerHidden } from './hooks' diff --git a/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx index fcc5b5cb53..a83820adc9 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/ConfirmSwapModal/index.tsx @@ -7,10 +7,7 @@ import { Percent } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' import { SwapModalFooter } from 'legacy/components/swap/SwapModalFooter' -import SwapModalHeader from 'legacy/components/swap/SwapModalHeader' -import { TransactionConfirmationModal } from 'legacy/components/TransactionConfirmationModal' import TradeGp from 'legacy/state/swap/TradeGp' -import { ConfirmOperationType } from 'legacy/state/types' import { SwapConfirmState } from 'modules/swap/state/swapConfirmAtom' @@ -19,7 +16,10 @@ import { TransactionErrorContent } from 'common/pure/TransactionErrorContent' import { useButtonText } from './hooks' +import { ConfirmOperationType } from '../../../state/types' +import { TransactionConfirmationModal } from '../../TransactionConfirmationModal' import { LegacyConfirmationModalContent } from '../../TransactionConfirmationModal/LegacyConfirmationModalContent' +import { SwapModalHeader } from '../SwapModalHeader' type ConfirmSwapModalProps = { swapConfirmState: SwapConfirmState diff --git a/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx b/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx index 6f67733acb..74d25969f2 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/FeeInformationTooltip.tsx @@ -51,7 +51,7 @@ const FeeAmountAndFiat = styled.span` } ` -export default function FeeInformationTooltip(props: FeeInformationTooltipProps) { +export function FeeInformationTooltip(props: FeeInformationTooltipProps) { const { trade, label, amountAfterFees, type, showHelper, fiatValue, showFiat = false, allowsOffchainSigning } = props const theme = useTheme() diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx deleted file mode 100644 index 5636f6f072..0000000000 --- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/SwapModalHeaderMod.tsx +++ /dev/null @@ -1,253 +0,0 @@ -import React, { useContext, useMemo } from 'react' - -import { INPUT_OUTPUT_EXPLANATION } from '@cowprotocol/common-const' -import { isAddress, shortenAddress } from '@cowprotocol/common-utils' -import { TokenAmount, TokenSymbol, RowBetween, RowFixed } from '@cowprotocol/ui' -import { Percent, TradeType } from '@uniswap/sdk-core' - -import { Trans } from '@lingui/macro' -import { transparentize } from 'polished' -import { ArrowDown } from 'react-feather' -import { Text } from 'rebass' -import styled, { ThemeContext } from 'styled-components/macro' - -import { AutoColumn } from 'legacy/components/Column' -import { AdvancedSwapDetails } from 'legacy/components/swap/AdvancedSwapDetails' -import { AuxInformationContainer, TruncatedText } from 'legacy/components/swap/styleds' -import { WarningProps } from 'legacy/components/SwapWarnings' -import TradeGp from 'legacy/state/swap/TradeGp' -import { Field } from 'legacy/state/types' -import { ThemedText } from 'legacy/theme' -import { computeSlippageAdjustedAmounts } from 'legacy/utils/prices' - -import { PriceUpdatedBanner } from 'modules/trade/pure/PriceUpdatedBanner' -import { useTradeUsdAmounts } from 'modules/usdAmount' - -import { CurrencyLogo } from 'common/pure/CurrencyLogo' -import { FiatValue } from 'common/pure/FiatValue' -import { RateInfo, RateInfoParams } from 'common/pure/RateInfo' - -import FeeInformationTooltip from '../FeeInformationTooltip' - -import { LightCardType } from './index' - -export const ArrowWrapper = styled.div` - --size: 26px; - padding: 0; - height: var(--size); - width: var(--size); - position: relative; - margin: -13px 0; - left: calc(50% - var(--size) / 2); - display: flex; - justify-content: center; - align-items: center; - z-index: 2; - border-radius: 8px; - border: ${({ theme }) => `2px solid ${theme.grey1}`}; - box-shadow: 0px 0px 0px 3px ${({ theme }) => theme.bg1}; - background: ${({ theme }) => (theme.darkMode ? theme.grey1 : theme.white)}; - - > svg { - stroke-width: 2px; - padding: 1px; - height: 100%; - width: 100%; - cursor: pointer; - } -` - -const StyledRateInfo = styled(RateInfo)` - font-size: 13px; - font-weight: 500; - margin: 0 auto; -` - -export interface SwapModalHeaderProps { - trade: TradeGp - allowedSlippage: Percent - recipient: string | null - showAcceptChanges: boolean - priceImpactWithoutFee?: Percent - priceImpact?: Percent - onAcceptChanges: () => void - LightCard: LightCardType - HighFeeWarning: React.FC - NoImpactWarning: React.ReactNode - allowsOffchainSigning: boolean - rateInfoParams: RateInfoParams -} - -export default function SwapModalHeader({ - trade, - allowedSlippage, - recipient, - showAcceptChanges, - onAcceptChanges, - priceImpact, - LightCard, - HighFeeWarning, - NoImpactWarning, - allowsOffchainSigning, - rateInfoParams, -}: SwapModalHeaderProps) { - const slippageAdjustedAmounts = useMemo( - () => computeSlippageAdjustedAmounts(trade, allowedSlippage), - [trade, allowedSlippage] - ) - - const theme = useContext(ThemeContext) - - const { - inputAmount: { value: fiatValueInput }, - outputAmount: { value: fiatValueOutput }, - } = useTradeUsdAmounts(trade.inputAmountWithoutFee, trade.outputAmountWithoutFee) - - const [slippageIn, slippageOut] = useMemo( - () => [slippageAdjustedAmounts[Field.INPUT], slippageAdjustedAmounts[Field.OUTPUT]], - [slippageAdjustedAmounts] - ) - - const [exactInLabel, exactOutLabel] = useMemo(() => { - return [ - trade?.tradeType === TradeType.EXACT_OUTPUT ? From (incl. fee) : null, - trade?.tradeType === TradeType.EXACT_INPUT ? Receive (incl. fee) : null, - ] - }, [trade]) - - return ( - - - - - - From - - - - - - - - - - - - - - - - - - - {!!exactInLabel && ( - - } - amountBeforeFees={} - feeAmount={trade.fee.feeAsCurrency} - allowsOffchainSigning={allowsOffchainSigning} - label={exactInLabel} - showHelper - trade={trade} - type="From" - fiatValue={fiatValueInput} - /> - - )} - - - - - - - - To - - - - - - - - - - - - - - - {} - - - - - - {!!exactOutLabel && ( - - } - amountBeforeFees={} - feeAmount={trade.outputAmountWithoutFee?.subtract(trade.outputAmount)} - label={exactOutLabel} - allowsOffchainSigning={allowsOffchainSigning} - showHelper - trade={trade} - type="To" - fiatValue={fiatValueOutput} - /> - - )} - - - {showAcceptChanges && } - - {trade.tradeType === TradeType.EXACT_INPUT ? ( - - - Output is estimated. You will receive at least{' '} - - {' '} - {' '} - or the swap will not execute. {INPUT_OUTPUT_EXPLANATION} - - - ) : ( - - - Input is estimated. You will sell at most{' '} - - {' '} - {' '} - or the swap will not execute. {INPUT_OUTPUT_EXPLANATION} - - - )} - - {recipient !== null ? ( - - - - Output will be sent to{' '} - {isAddress(recipient) ? shortenAddress(recipient) : recipient} - - - - ) : null} - {/* High Fee Warning */} - - {/* No Impact Warning */} - {!priceImpact && NoImpactWarning} - - ) -} diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx index 6aa4151c0e..23524ae1f5 100644 --- a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/index.tsx @@ -1,61 +1,46 @@ -import React from 'react' +import React, { useContext, useMemo } from 'react' +import { INPUT_OUTPUT_EXPLANATION } from '@cowprotocol/common-const' +import { isAddress, shortenAddress } from '@cowprotocol/common-utils' +import { RowBetween, RowFixed, TokenAmount, TokenSymbol } from '@cowprotocol/ui' import { useWalletDetails } from '@cowprotocol/wallet' +import { Percent, TradeType } from '@uniswap/sdk-core' +import { Trans } from '@lingui/macro' import { transparentize } from 'polished' -import styled from 'styled-components/macro' +import { ArrowDown } from 'react-feather' +import { Text } from 'rebass' +import { ThemeContext } from 'styled-components/macro' -import { LightCard as LightCardUni } from 'legacy/components/Card' -import { SwapShowAcceptChanges } from 'legacy/components/swap/styleds' -import { HighFeeWarning as HighFeeWarningBase } from 'legacy/components/SwapWarnings' +import { AutoColumn } from 'legacy/components/Column' +import { AdvancedSwapDetails } from 'legacy/components/swap/AdvancedSwapDetails' +import { AuxInformationContainer, TruncatedText } from 'legacy/components/swap/styleds' +import { WarningProps } from 'legacy/components/SwapWarnings' +import TradeGp from 'legacy/state/swap/TradeGp' +import { ThemedText } from 'legacy/theme' +import { computeSlippageAdjustedAmounts } from 'legacy/utils/prices' import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning' +import { PriceUpdatedBanner } from 'modules/trade/pure/PriceUpdatedBanner' +import { useTradeUsdAmounts } from 'modules/usdAmount' -import { UI } from 'common/constants/theme' +import { CurrencyLogo } from 'common/pure/CurrencyLogo' +import { FiatValue } from 'common/pure/FiatValue' +import { BannerOrientation, CustomRecipientWarningBanner } from 'common/pure/InlineBanner/banners' +import { RateInfoParams } from 'common/pure/RateInfo' -import SwapModalHeaderMod, { SwapModalHeaderProps } from './SwapModalHeaderMod' +import { ArrowWrapper, HighFeeWarning, LightCard, LightCardType, StyledRateInfo, Wrapper } from './styled' -const LightCard = styled(LightCardUni)<{ flatBorder?: boolean }>` - background-color: var(${UI.COLOR_GREY}); - border: none; - ${({ flatBorder = false }) => flatBorder && `border-radius: 20px 20px 0 0;`}; -` +import { Field } from '../../../state/types' +import { FeeInformationTooltip } from '../FeeInformationTooltip' -export type LightCardType = typeof LightCard - -// targettable by styled injection -const HighFeeWarning = styled(HighFeeWarningBase)`` - -const Wrapper = styled.div` - ${({ theme }) => theme.mediaWidth.upToSmall` - margin: 0 auto; - `}; - - ${SwapShowAcceptChanges} { - background: ${({ theme }) => transparentize(0.85, theme.alert)}; - border: 1px solid ${({ theme }) => transparentize(0.75, theme.alert)}; - padding: 8px 8px 8px 16px; - margin: 8px 0 0; - - svg { - stroke: ${({ theme }) => theme.alert}; - } - } - - svg { - stroke: var(${UI.COLOR_TEXT1}); - } -` - -export default function SwapModalHeader( - props: Omit -) { +export function SwapModalHeader(props: Omit) { const { allowsOffchainSigning } = useWalletDetails() const NoImpactWarningComponent = return ( - ) } + +interface SwapModalHeaderProps { + trade: TradeGp + allowedSlippage: Percent + recipient: string | null + showAcceptChanges: boolean + priceImpactWithoutFee?: Percent + priceImpact?: Percent + onAcceptChanges: () => void + LightCard: LightCardType + HighFeeWarning: React.FC + NoImpactWarning: React.ReactNode + allowsOffchainSigning: boolean + rateInfoParams: RateInfoParams +} + +function SwapModalHeaderComponent({ + trade, + allowedSlippage, + recipient, + showAcceptChanges, + onAcceptChanges, + priceImpact, + LightCard, + HighFeeWarning, + NoImpactWarning, + allowsOffchainSigning, + rateInfoParams, +}: SwapModalHeaderProps) { + const slippageAdjustedAmounts = useMemo( + () => computeSlippageAdjustedAmounts(trade, allowedSlippage), + [trade, allowedSlippage] + ) + + const theme = useContext(ThemeContext) + + const { + inputAmount: { value: fiatValueInput }, + outputAmount: { value: fiatValueOutput }, + } = useTradeUsdAmounts(trade.inputAmountWithoutFee, trade.outputAmountWithoutFee) + + const [slippageIn, slippageOut] = useMemo( + () => [slippageAdjustedAmounts[Field.INPUT], slippageAdjustedAmounts[Field.OUTPUT]], + [slippageAdjustedAmounts] + ) + + const [exactInLabel, exactOutLabel] = useMemo(() => { + return [ + trade?.tradeType === TradeType.EXACT_OUTPUT ? From (incl. fee) : null, + trade?.tradeType === TradeType.EXACT_INPUT ? Receive (incl. fee) : null, + ] + }, [trade]) + + const isCustomRecipient = recipient !== null + + return ( + + + + + + From + + + + + + + + + + + + + + + + + + + {!!exactInLabel && ( + + } + amountBeforeFees={} + feeAmount={trade.fee.feeAsCurrency} + allowsOffchainSigning={allowsOffchainSigning} + label={exactInLabel} + showHelper + trade={trade} + type="From" + fiatValue={fiatValueInput} + /> + + )} + + + + + + + + To + + + + + + + + + + + + + + + {} + + + + + + {!!exactOutLabel && ( + + } + amountBeforeFees={} + feeAmount={trade.outputAmountWithoutFee?.subtract(trade.outputAmount)} + label={exactOutLabel} + allowsOffchainSigning={allowsOffchainSigning} + showHelper + trade={trade} + type="To" + fiatValue={fiatValueOutput} + /> + + )} + + + {showAcceptChanges && } + + {trade.tradeType === TradeType.EXACT_INPUT ? ( + + + Output is estimated. You will receive at least{' '} + + {' '} + {' '} + or the swap will not execute. {INPUT_OUTPUT_EXPLANATION} + + + ) : ( + + + Input is estimated. You will sell at most{' '} + + {' '} + {' '} + or the swap will not execute. {INPUT_OUTPUT_EXPLANATION} + + + )} + + {/*TODO: adjust styles and maybe merge with the indication below? */} + {isCustomRecipient && ( + + + + )} + {isCustomRecipient ? ( + + + + Output will be sent to{' '} + {isAddress(recipient) ? shortenAddress(recipient) : recipient} + + + + ) : null} + {/* High Fee Warning */} + + {/* No Impact Warning */} + {!priceImpact && NoImpactWarning} + + ) +} diff --git a/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/styled.ts b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/styled.ts new file mode 100644 index 0000000000..a75c03e991 --- /dev/null +++ b/apps/cowswap-frontend/src/legacy/components/swap/SwapModalHeader/styled.ts @@ -0,0 +1,73 @@ +import { transparentize } from 'polished' +import styled from 'styled-components/macro' + +import { LightCard as LightCardUni } from 'legacy/components/Card' +import { SwapShowAcceptChanges } from 'legacy/components/swap/styleds' +import { HighFeeWarning as HighFeeWarningBase } from 'legacy/components/SwapWarnings' + +import { UI } from 'common/constants/theme' +import { RateInfo } from 'common/pure/RateInfo' + +export const LightCard = styled(LightCardUni)<{ flatBorder?: boolean }>` + background-color: var(${UI.COLOR_GREY}); + border: none; + ${({ flatBorder = false }) => flatBorder && `border-radius: 20px 20px 0 0;`}; +` + +export type LightCardType = typeof LightCard + +// targettable by styled injection +export const HighFeeWarning = styled(HighFeeWarningBase)`` + +export const Wrapper = styled.div` + ${({ theme }) => theme.mediaWidth.upToSmall` + margin: 0 auto; + `}; + + ${SwapShowAcceptChanges} { + background: ${({ theme }) => transparentize(0.85, theme.alert)}; + border: 1px solid ${({ theme }) => transparentize(0.75, theme.alert)}; + padding: 8px 8px 8px 16px; + margin: 8px 0 0; + + svg { + stroke: ${({ theme }) => theme.alert}; + } + } + + svg { + stroke: var(${UI.COLOR_TEXT1}); + } +` + +export const ArrowWrapper = styled.div` + --size: 26px; + padding: 0; + height: var(--size); + width: var(--size); + position: relative; + margin: -13px 0; + left: calc(50% - var(--size) / 2); + display: flex; + justify-content: center; + align-items: center; + z-index: 2; + border-radius: 8px; + border: ${({ theme }) => `2px solid ${theme.grey1}`}; + box-shadow: 0px 0px 0px 3px ${({ theme }) => theme.bg1}; + background: ${({ theme }) => (theme.darkMode ? theme.grey1 : theme.white)}; + + > svg { + stroke-width: 2px; + padding: 1px; + height: 100%; + width: 100%; + cursor: pointer; + } +` + +export const StyledRateInfo = styled(RateInfo)` + font-size: 13px; + font-weight: 500; + margin: 0 auto; +` diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx b/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx index 8bcdc9fa56..8c84e3f393 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx +++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/ActivityDetails.tsx @@ -1,7 +1,9 @@ import { ReactNode } from 'react' import { V_COW_CONTRACT_ADDRESS, V_COW, COW } from '@cowprotocol/common-const' -import { TokenAmount } from '@cowprotocol/ui' +import { ExplorerDataType, getExplorerLink, shortenAddress } from '@cowprotocol/common-utils' +import { useENS } from '@cowprotocol/ens' +import { ExternalLink, TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount } from '@uniswap/sdk-core' import { OrderProgressBar } from 'legacy/components/OrderProgressBar' @@ -12,24 +14,33 @@ import { OrderStatus } from 'legacy/state/orders/actions' import { EthFlowStepper } from 'modules/swap/containers/EthFlowStepper' +import { UI } from 'common/constants/theme' import { useCancelOrder } from 'common/hooks/useCancelOrder' +import { isPending } from 'common/hooks/useCategorizeRecentActivity' import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue' import { CurrencyLogo } from 'common/pure/CurrencyLogo' +import { Icon } from 'common/pure/Icon' +import { BannerOrientation, CustomRecipientWarningBanner } from 'common/pure/InlineBanner/banners' import { RateInfoParams, RateInfo } from 'common/pure/RateInfo' import { SafeWalletLink } from 'common/pure/SafeWalletLink' +import { + useHideReceiverWalletBanner, + useIsReceiverWalletBannerHidden, +} from 'common/state/receiverWalletBannerVisibility' import { StatusDetails } from './StatusDetails' import { + ActivityVisual, + CreationTimeText, + FiatWrapper, + IconType, + StyledFiatAmount, Summary, SummaryInner, SummaryInnerRow, - TransactionInnerDetail, TextAlert, + TransactionInnerDetail, TransactionState as ActivityLink, - CreationTimeText, - ActivityVisual, - StyledFiatAmount, - FiatWrapper, } from './styled' import { ActivityDerivedState } from './index' @@ -170,6 +181,12 @@ export function ActivityDetails(props: { const { surplusFiatValue, showFiatValue, surplusToken, surplusAmount } = useGetSurplusData(order) + const { name: receiverEnsName } = useENS(order?.receiver) + + // Check if Custom Recipient Warning Banner should be visible + const isCustomRecipientWarningBannerVisible = !useIsReceiverWalletBannerHidden(id) && order && isPending(order) + const hideCustomRecipientWarning = useHideReceiverWalletBanner() + if (!order && !enhancedTransaction) return null // Order Summary default object @@ -246,8 +263,19 @@ export function ActivityDetails(props: { outputToken = COW[chainId] } + const isCustomRecipient = Boolean(order?.receiver && order.owner !== order.receiver) + return ( <> + {/* Warning banner if custom recipient */} + {isCustomRecipient && isCustomRecipientWarningBannerVisible && ( + hideCustomRecipientWarning(id)} + /> + )} +

{creationTime && {creationTime}} @@ -299,6 +327,23 @@ export function ActivityDetails(props: { )} + + {order && isCustomRecipient && ( + + Recipient: + + {isCustomRecipientWarningBannerVisible && ( + + )} + + {receiverEnsName || shortenAddress(order.receiver || order.owner)} ↗ + + + + )} + {surplusAmount?.greaterThan(0) && ( Surplus diff --git a/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts b/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts index 631eb8876d..7a12e05aff 100644 --- a/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts +++ b/apps/cowswap-frontend/src/modules/account/containers/Transaction/styled.ts @@ -83,6 +83,7 @@ export const IconType = styled.div` ` export const Summary = styled.div` + position: relative; display: grid; flex-flow: row wrap; width: 100%; @@ -269,8 +270,8 @@ export const StatusLabel = styled.div<{ isPending || isPresignaturePending || isCreating ? theme.text1 : color === 'success' - ? theme.success - : theme.attention}; + ? theme.success + : theme.attention}; position: relative; border-radius: 4px; display: flex; @@ -290,13 +291,13 @@ export const StatusLabel = styled.div<{ &::before { content: ''; background: ${({ color, isTransaction, isPending, isPresignaturePending, isCancelling, isCreating, theme }) => - !isCancelling && (isPending || isCreating) - ? 'transparent' - : isPresignaturePending || (isPending && isTransaction) + !isCancelling && (isPending || isCreating) + ? 'transparent' + : isPresignaturePending || (isPending && isTransaction) ? theme.pending : color === 'success' - ? theme.success - : theme.attention}; + ? theme.success + : theme.attention}; position: absolute; left: 0; top: 0; @@ -330,9 +331,9 @@ export const StatusLabel = styled.div<{ > svg > path { fill: ${({ theme, color, isPending, isPresignaturePending, isCreating }) => - isPending || isPresignaturePending || isCreating - ? theme.text1 - : color === 'success' + isPending || isPresignaturePending || isCreating + ? theme.text1 + : color === 'success' ? theme.success : theme.attention}; } @@ -355,7 +356,7 @@ export const StatusLabelBelow = styled.div<{ isCancelling?: boolean }>` } ` -export const OldTransactionState = styled(ExternalLink)<{ pending: boolean; success?: boolean }>` +export const OldTransactionState = styled(ExternalLink) <{ pending: boolean; success?: boolean }>` display: flex; justify-content: space-between; align-items: center; @@ -482,7 +483,7 @@ export const ActivityVisual = styled.div` box-shadow: none; background: ${({ theme }) => theme.white}; color: ${({ theme }) => - theme.transaction.tokenColor}!important; // TODO: Fix MOD file to not require this !important property value. + theme.transaction.tokenColor}!important; // TODO: Fix MOD file to not require this !important property value. border: 2px solid ${({ theme }) => theme.bg1}; } diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx index 1b3494b41c..c82bd3c577 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWarnings/index.tsx @@ -1,5 +1,4 @@ -import { useSetAtom } from 'jotai' -import { useAtomValue } from 'jotai' +import { useAtomValue, useSetAtom } from 'jotai' import React, { useCallback, useEffect } from 'react' import { isFractionFalsy } from '@cowprotocol/common-utils' @@ -18,6 +17,7 @@ import { updateLimitOrdersWarningsAtom, } from 'modules/limitOrders/state/limitOrdersWarningsAtom' import { useTradePriceImpact } from 'modules/trade' +import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning' import { TradeFormValidation, useGetTradeFormValidation } from 'modules/tradeFormValidation' import { useTradeQuote } from 'modules/tradeQuote' @@ -25,8 +25,10 @@ import { useTradeQuote } from 'modules/tradeQuote' import { HIGH_FEE_WARNING_PERCENTAGE } from 'common/constants/common' import { useShouldZeroApprove } from 'common/hooks/useShouldZeroApprove' import { + BannerOrientation, BundleTxApprovalBanner, BundleTxSafeWcBanner, + CustomRecipientWarningBanner, SmallVolumeWarningBanner, } from 'common/pure/InlineBanner/banners' import { ZeroApprovalWarning } from 'common/pure/ZeroApprovalWarning' @@ -103,13 +105,17 @@ export function LimitOrdersWarnings(props: LimitOrdersWarningsProps) { isSafeViaWc && primaryFormValidation === TradeFormValidation.ApproveRequired + const { state } = useDerivedTradeState() + const showRecipientWarning = isConfirmScreen && state?.recipient && account !== state.recipient + const isVisible = showPriceImpactWarning || rateImpact < 0 || showHighFeeWarning || showApprovalBundlingBanner || showSafeWcBundlingBanner || - shouldZeroApprove + shouldZeroApprove || + showRecipientWarning // Reset price impact flag when there is no price impact useEffect(() => { @@ -135,6 +141,7 @@ export function LimitOrdersWarnings(props: LimitOrdersWarningsProps) { return isVisible ? ( + {showRecipientWarning && } {showZeroApprovalWarning && } {showPriceImpactWarning && ( - +

{isTwapPartOrder ? `Part of a ${twapOrder.order.n}-part TWAP order split` @@ -123,6 +139,15 @@ export function ReceiptModal({ + {/* If custom recipient show warning banner */} + {showCustomRecipientBanner && ( + hideCustomRecipientWarning(order.id)} + /> + )} + @@ -132,8 +157,11 @@ export function ReceiptModal({

+ {showCustomRecipientBanner && ( + + )} - {receiverEnsName || shortenAddress(order.receiver)} + {receiverEnsName || shortenAddress(order.receiver)} ↗
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts index 40f48d20d3..0c829b2b09 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/styled.ts @@ -82,6 +82,10 @@ export const Field = styled.div` &:last-child { border-radius: 0 0 16px 16px; } + + > div { + display: flex; + } ` export const CurrencyField = styled.div` diff --git a/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx b/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx index d8d4033eb3..76f54c9b2e 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/banners/TwapSuggestionBanner.tsx @@ -54,7 +54,7 @@ export function TwapSuggestionBanner({ parameterizeTradeRoute(tradeUrlParams, Routes.ADVANCED_ORDERS) + `?${TRADE_URL_SELL_AMOUNT_KEY}=${sellAmount}` return ( - + Minimize price impact with TWAP

The price impact is {+priceImpact.toFixed(2)}%. Consider breaking up your order using a{' '} diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx index a3cd2a9c25..a9b4df69c7 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/index.tsx @@ -1,5 +1,4 @@ -import { useAtomValue } from 'jotai' -import { useSetAtom } from 'jotai' +import { useAtomValue, useSetAtom } from 'jotai' import { useCallback } from 'react' import { modifySafeHandlerAnalytics } from '@cowprotocol/analytics' @@ -10,7 +9,11 @@ import { NoImpactWarning } from 'modules/trade/pure/NoImpactWarning' import { useTradeQuoteFeeFiatAmount } from 'modules/tradeQuote' import { useShouldZeroApprove } from 'common/hooks/useShouldZeroApprove' -import { BundleTxApprovalBanner } from 'common/pure/InlineBanner/banners' +import { + BannerOrientation, + BundleTxApprovalBanner, + CustomRecipientWarningBanner, +} from 'common/pure/InlineBanner/banners' import { ZeroApprovalWarning } from 'common/pure/ZeroApprovalWarning' import { @@ -79,6 +82,10 @@ export function TwapFormWarnings({ localFormValidation, isConfirmationModal }: T updateTwapOrdersSettings({ isPriceImpactAccepted: !isPriceImpactAccepted }) }, [updateTwapOrdersSettings, isPriceImpactAccepted]) + const { account } = useWalletInfo() + + const showRecipientWarning = isConfirmationModal && twapOrder?.receiver && twapOrder.receiver !== account + // Don't display any warnings while a wallet is not connected if (walletIsNotConnected) return null @@ -103,6 +110,8 @@ export function TwapFormWarnings({ localFormValidation, isConfirmationModal }: T /> )} + {showRecipientWarning && } + {(() => { if (localFormValidation === TwapFormState.NOT_SAFE) { return diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx index 586715bfbd..76be392d47 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/FallbackHandlerWarning.tsx @@ -74,7 +74,7 @@ export function FallbackHandlerWarning({ if (isFallbackHandlerSetupAccepted) { return ( - + {fallbackHandlerCheckbox} @@ -82,7 +82,7 @@ export function FallbackHandlerWarning({ } else { return ( - + Unsupported Safe detected

Connected Safe lacks required fallback handler. Switch to a compatible Safe or modify fallback handler for diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx index addfd9a348..5500199b33 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/SwapPriceDifferenceWarning.tsx @@ -47,7 +47,7 @@ export function SwapPriceDifferenceWarning({ const swapOrderLink = SWAP order return ( - + {isTwapBetter ? ( <> Maximizing Your Gains! {/**/} diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx index 73da882db0..8f3198794c 100644 --- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx +++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWarnings/warnings/UnsupportedWalletWarning.tsx @@ -8,7 +8,7 @@ import { InlineBanner } from 'common/pure/InlineBanner' export function UnsupportedWalletWarning({ isSafeViaWc }: { isSafeViaWc: boolean }) { if (isSafeViaWc) { return ( - + Use Safe web app

Use the Safe web app for advanced trading.
@@ -19,7 +19,7 @@ export function UnsupportedWalletWarning({ isSafeViaWc }: { isSafeViaWc: boolean } return ( - + Unsupported wallet detected

TWAP orders currently require a Safe with a special fallback handler. Have one? Switch to it! Need setup?{' '} diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts index f3f1d78bb6..17dc8e82f9 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useEmulatedTwapOrders.ts @@ -28,10 +28,13 @@ export function useEmulatedTwapOrders(tokensByAddress: TokensByAddress | undefin if (!refresher) return [] if (!tokensByAddress) return [] - return allTwapOrders - .filter((order) => order.chainId === chainId && order.safeAddress.toLowerCase() === accountLowerCase) - .map((order) => { - return mapTwapOrderToStoreOrder(order, tokensByAddress) - }) + return allTwapOrders.reduce((acc, order) => { + if (order.chainId !== chainId || order.safeAddress.toLowerCase() !== accountLowerCase) { + return acc + } + + acc.push(mapTwapOrderToStoreOrder(order, tokensByAddress)) + return acc + }, []) }, [allTwapOrders, accountLowerCase, chainId, tokensByAddress, refresher]) } diff --git a/apps/cowswap-frontend/src/modules/twap/utils/emulateTwapAsOrder.ts b/apps/cowswap-frontend/src/modules/twap/utils/emulateTwapAsOrder.ts index 73dffa195f..76a6de409d 100644 --- a/apps/cowswap-frontend/src/modules/twap/utils/emulateTwapAsOrder.ts +++ b/apps/cowswap-frontend/src/modules/twap/utils/emulateTwapAsOrder.ts @@ -22,7 +22,7 @@ export function emulateTwapAsOrder(item: TwapOrderItem): EnrichedOrder { const creationTime = new Date(item.executedDate || item.submissionDate) const expirationTime = new Date(creationTime.getTime() + t * n * 1000) - const { executedSellAmount, executedBuyAmount, executedFeeAmount } = executionInfo.info + const { executedSellAmount = '0', executedBuyAmount = '0', executedFeeAmount = '0' } = executionInfo?.info || {} return { signingScheme: SigningScheme.EIP1271, diff --git a/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts b/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts index a799edb648..fec8eae063 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts @@ -33,6 +33,7 @@ export interface ParsedOrderExecutionData { export interface ParsedOrder { id: string + owner: string isCancelling: boolean | undefined receiver: string | undefined inputToken: Token @@ -94,6 +95,7 @@ export const parseOrder = (order: Order): ParsedOrder => { return { id: order.id, + owner: order.owner, isCancelling: order.isCancelling, inputToken: order.inputToken, outputToken: order.outputToken, From becfc3c147bbbe307650b8c563d9befbea84c2c0 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Mon, 25 Sep 2023 20:35:17 +0600 Subject: [PATCH 14/36] fix(twap): approve infinite amount (#3141) * fix(twap): approve infinite amount * chore: fix test * chore: fix import --- .../services/__snapshots__/createTwapOrderTxs.test.ts.snap | 4 ++-- .../src/modules/twap/services/createTwapOrderTxs.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/twap/services/__snapshots__/createTwapOrderTxs.test.ts.snap b/apps/cowswap-frontend/src/modules/twap/services/__snapshots__/createTwapOrderTxs.test.ts.snap index 8736ed1f9b..9e2467e7f0 100644 --- a/apps/cowswap-frontend/src/modules/twap/services/__snapshots__/createTwapOrderTxs.test.ts.snap +++ b/apps/cowswap-frontend/src/modules/twap/services/__snapshots__/createTwapOrderTxs.test.ts.snap @@ -21,7 +21,7 @@ exports[`Create TWAP order When sell token is NOT approved AND token needs zero "approve", [ "0xB4FBF271143F4FBf7B91A5ded31805e42b222222", - "100000000000", + "115792089237316195423570985008687907853269984665640564039457584007913129639935", ], ] `; @@ -80,7 +80,7 @@ exports[`Create TWAP order When sell token is NOT approved, then should generate "approve", [ "0xB4FBF271143F4FBf7B91A5ded31805e42b222222", - "100000000000", + "115792089237316195423570985008687907853269984665640564039457584007913129639935", ], ] `; diff --git a/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.ts b/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.ts index 599b170f6f..5643d2c8c3 100644 --- a/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.ts +++ b/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.ts @@ -1,3 +1,4 @@ +import { MaxUint256 } from '@ethersproject/constants' import { MetaTransactionData } from '@safe-global/safe-core-sdk-types' import { TwapOrderCreationContext } from '../hooks/useTwapOrderCreationContext' @@ -20,7 +21,7 @@ export function createTwapOrderTxs( const { sellAmount } = order const sellTokenAddress = sellAmount.currency.address - const sellAmountAtoms = sellAmount.quotient.toString() + const sellAmountAtoms = MaxUint256.toString() const txs: MetaTransactionData[] = [] From 009a9d75635d50ac8cb610279699c4a278754dc4 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Tue, 26 Sep 2023 12:41:45 +0600 Subject: [PATCH 15/36] fix(limit-orders): fix tooltips displaying in settings (#3143) * chore: remove unused code * fix(limit-orders): fix tooltips displaying in settings --- .../QuestionHelper/QuestionHelperMod.tsx | 27 ------------ .../limitOrders/pure/Settings/styled.ts | 44 ------------------- libs/ui/src/pure/Popover/PopoverMod.tsx | 36 +++++++++++---- 3 files changed, 28 insertions(+), 79 deletions(-) delete mode 100644 apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts diff --git a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx index 6e2abdee6c..6d4e5779c1 100644 --- a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx @@ -6,32 +6,6 @@ import styled from 'styled-components/macro' import { QuestionWrapper } from './index' -/* const QuestionWrapper = styled.div` - display: flex; - align-items: center; - justify-content: center; - padding: 0px; - width: 18px; - height: 18px; - border: none; - background: none; - outline: none; - cursor: default; - border-radius: 36px; - font-size: 12px; - background-color: ${({ theme }) => theme.bg2}; - color: var(${UI.COLOR_TEXT2}); - - :hover, - :focus { - opacity: 0.7; - } -` */ - -/* const QuestionMark = styled.span` - font-size: 14px; -` */ - const QuestionHelperContainer = styled.span` margin-left: 4px; display: flex; @@ -73,7 +47,6 @@ export default function QuestionHelper({ text, className, QuestionMark, ...toolt - {/* ? */} diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts b/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts deleted file mode 100644 index 96535ebbba..0000000000 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/Settings/styled.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { transparentize } from 'polished' -import styled from 'styled-components/macro' - -import { UI } from 'common/constants/theme' - -export const SettingsTitle = styled.h3` - font-weight: 600; - font-size: 14px; - color: var(${UI.COLOR_TEXT1}); - margin: 0 0 12px 0; -` - -export const SettingsContainer = styled.div` - margin: 12px 0 0; - padding: 16px; - border-radius: 12px; - box-shadow: ${({ theme }) => theme.boxShadow2}; - border: 1px solid ${({ theme }) => transparentize(0.95, theme.white)}; - background: var(${UI.COLOR_CONTAINER_BG_01}); - color: var(${UI.COLOR_TEXT1}); -` - -export const SettingsBox = styled.div<{ disabled: boolean }>` - display: flex; - justify-content: space-between; - margin-bottom: 10px; - - :last-child { - margin-bottom: 0; - } - - opacity: ${({ disabled }) => (disabled ? '0.7' : '1')}; - pointer-events: ${({ disabled }) => (disabled ? 'none' : '')}; -` - -export const SettingsBoxTitle = styled.div` - display: flex; - align-items: center; - font-weight: 400; - color: var(${UI.COLOR_TEXT1}); - font-size: 14px; - opacity: 0.85; - margin-right: 2rem; -` diff --git a/libs/ui/src/pure/Popover/PopoverMod.tsx b/libs/ui/src/pure/Popover/PopoverMod.tsx index 66daa017ad..86ae703012 100644 --- a/libs/ui/src/pure/Popover/PopoverMod.tsx +++ b/libs/ui/src/pure/Popover/PopoverMod.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useState } from 'react' +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { Options, Placement } from '@popperjs/core' import { Portal } from '@reach/portal' @@ -85,6 +85,32 @@ export interface PopoverProps extends PopoverContainerProps, Omit, never> // gp mod } +// TODO: reuse hook from @cowprotocol/common-hooks +// Currently it's not possible because of dependency inversion +function useInterval(callback: () => void, delay: null | number, leading = true) { + const savedCallback = useRef<() => void>() + + // Remember the latest callback. + useEffect(() => { + savedCallback.current = callback + }, [callback]) + + // Set up the interval. + useEffect(() => { + function tick() { + const { current } = savedCallback + current && current() + } + + if (delay !== null) { + if (leading) tick() + const id = setInterval(tick, delay) + return () => clearInterval(id) + } + return + }, [delay, leading]) +} + export default function Popover({ content, show, @@ -119,13 +145,7 @@ export default function Popover({ update && update() }, [update]) - useEffect(() => { - if (!show) return - - const interval = setInterval(updateCallback, 100) - - return () => clearInterval(interval) - }, []) + useInterval(updateCallback, show ? 100 : null) return ( <> From 572d87e06e74ccef742d1468d7a96cb9bd86e0e3 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Tue, 26 Sep 2023 13:14:48 +0600 Subject: [PATCH 16/36] feat(orders-table): approve order token from allowance warn tooltip (#3144) * chore: remove unused code * fix(limit-orders): fix tooltips displaying in settings * refactor(limit-orders): replace allowance warn tooltip by a new one * feat(orders-table): approve order token from allowance warn tooltip * chore: test commit --- .../QuestionHelper/QuestionHelperMod.tsx | 3 +- .../components/QuestionHelper/index.tsx | 7 ++-- .../hooks/useOrdersTableTokenApprove.test.ts | 36 +++++++++++++++++++ .../hooks/useOrdersTableTokenApprove.ts | 29 +++++++++++++++ .../containers/OrdersTableWidget/index.tsx | 4 +++ .../OrdersTableContainer/OrderRow/index.tsx | 27 ++++++++------ .../OrdersTableContainer/OrderRow/styled.tsx | 12 +++++++ .../OrdersTableContainer/index.cosmos.tsx | 3 ++ .../pure/OrdersTableContainer/types.ts | 3 ++ 9 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.test.ts create mode 100644 apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.ts diff --git a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx index 6d4e5779c1..9fb689e300 100644 --- a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/QuestionHelperMod.tsx @@ -14,10 +14,9 @@ const QuestionHelperContainer = styled.span` export interface QuestionHelperProps extends Omit { className?: string - QuestionMark: () => JSX.Element // mod + QuestionMark: () => JSX.Element } -// export default function QuestionHelper({ text }: { text: ReactNode; size?: number }) { export default function QuestionHelper({ text, className, QuestionMark, ...tooltipProps }: QuestionHelperProps) { const [show, setShow] = useState(false) const [mouseLeaveTimeout, setMouseLeaveTimeout] = useState(null) diff --git a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx index 907a17ddd6..9597b3f168 100644 --- a/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/QuestionHelper/index.tsx @@ -10,7 +10,7 @@ import { UI } from 'common/constants/theme' import QuestionHelperMod, { QuestionHelperProps } from './QuestionHelperMod' -const QuestionMark = () => +const DefaultQuestionMark = export const QuestionWrapper = styled.div` display: flex; @@ -32,10 +32,11 @@ export const QuestionWrapper = styled.div` interface EnhancedQuestionHelperProps extends Omit { text: ReactNode + Icon?: JSX.Element } -export default function QuestionHelper({ text, ...props }: EnhancedQuestionHelperProps) { +export default function QuestionHelper({ text, Icon, ...props }: EnhancedQuestionHelperProps) { const tooltip = renderTooltip(text, props) - return + return Icon || DefaultQuestionMark} /> } diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.test.ts b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.test.ts new file mode 100644 index 0000000000..c93d059593 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.test.ts @@ -0,0 +1,36 @@ +import { useEffect } from 'react' + +import { WETH_GOERLI } from '@cowprotocol/common-const' + +import { renderHook } from '@testing-library/react-hooks' + +import { useTradeApproveCallback } from 'common/containers/TradeApprove' + +import { useOrdersTableTokenApprove } from './useOrdersTableTokenApprove' + +jest.mock('common/containers/TradeApprove') + +const mockUseTradeApproveCallback = useTradeApproveCallback as jest.MockedFunction +const tradeApproveCallbackMock = jest.fn().mockImplementation(() => Promise.resolve(undefined)) + +describe('useOrdersTableTokenApprove()', () => { + beforeEach(() => { + // GIVEN + mockUseTradeApproveCallback.mockReturnValue(tradeApproveCallbackMock as any) + }) + + it('When a token is set, then should trigger trade approve flow', () => { + // WHEN + renderHook(() => { + const callback = useOrdersTableTokenApprove() + + useEffect(() => { + callback(WETH_GOERLI) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + }) + + // THEN + expect(tradeApproveCallbackMock).toBeCalledTimes(1) + }) +}) diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.ts b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.ts new file mode 100644 index 0000000000..f7f1f3d909 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableTokenApprove.ts @@ -0,0 +1,29 @@ +import { Dispatch, SetStateAction, useMemo, useState } from 'react' + +import { MaxUint256 } from '@ethersproject/constants' +import { CurrencyAmount, Token } from '@uniswap/sdk-core' + +import { useTradeApproveCallback } from 'common/containers/TradeApprove' +import { useSafeEffect } from 'common/hooks/useSafeMemo' + +export function useOrdersTableTokenApprove(): Dispatch> { + const [tokenToApprove, setTokenToApprove] = useState(undefined) + + // Infinite amount + const amountToApprove = useMemo(() => { + return tokenToApprove ? CurrencyAmount.fromRawAmount(tokenToApprove, MaxUint256.toString()) : undefined + }, [tokenToApprove]) + + const tradeApproveCallback = useTradeApproveCallback(amountToApprove) + + // Trigger approve flow once amountToApprove is set + useSafeEffect(() => { + if (amountToApprove) { + tradeApproveCallback().finally(() => { + setTokenToApprove(undefined) + }) + } + }, [amountToApprove, tradeApproveCallback]) + + return setTokenToApprove +} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx index d614a6f8a6..19e4afc5c7 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx @@ -25,6 +25,7 @@ import { CancellableOrder } from 'common/utils/isOrderCancellable' import { ParsedOrder } from 'utils/orderUtils/parseOrder' import { OrdersTableList, useOrdersTableList } from './hooks/useOrdersTableList' +import { useOrdersTableTokenApprove } from './hooks/useOrdersTableTokenApprove' import { useValidatePageUrlParams } from './hooks/useValidatePageUrlParams' import { useCategorizeRecentActivity } from '../../../../common/hooks/useCategorizeRecentActivity' @@ -130,11 +131,14 @@ export function OrdersTableWidget({ [allOrders, cancelOrder] ) + const approveOrderToken = useOrdersTableTokenApprove() + const orderActions: OrderActions = { getShowCancellationModal, selectReceiptOrder, toggleOrderForCancellation, toggleOrdersForCancellation, + approveOrderToken, } // Set page params initially once diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx index 975b764807..21f8a63541 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx @@ -5,8 +5,7 @@ import { ZERO_FRACTION } from '@cowprotocol/common-const' import { useTimeAgo } from '@cowprotocol/common-hooks' import { getAddress, getEtherscanLink } from '@cowprotocol/common-utils' import { OrderClass, SupportedChainId } from '@cowprotocol/cow-sdk' -import { TokenAmount, TokenSymbol, Loader } from '@cowprotocol/ui' -import { MouseoverTooltipContent } from '@cowprotocol/ui' +import { Loader, TokenAmount, TokenSymbol } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Percent, Price } from '@uniswap/sdk-core' import SVG from 'react-inlinesvg' @@ -28,6 +27,7 @@ import { OrderStatusBox } from 'modules/ordersTable/pure/OrderStatusBox' import { getIsEthFlowOrder } from 'modules/swap/containers/EthFlowStepper' import { useSafeMemo } from 'common/hooks/useSafeMemo' +import { ButtonSecondary } from 'common/pure/ButtonSecondary' import { CurrencyLogo } from 'common/pure/CurrencyLogo' import { RateInfo } from 'common/pure/RateInfo' import { getQuoteCurrency } from 'common/services/getQuoteCurrency' @@ -92,7 +92,7 @@ function BalanceWarning(params: { symbol: string; isScheduled: boolean }) { ) } -function AllowanceWarning(params: { symbol: string; isScheduled: boolean }) { +function AllowanceWarning(params: { symbol: string; isScheduled: boolean; approve: () => void }) { const { symbol, isScheduled } = params return ( @@ -129,6 +129,9 @@ function AllowanceWarning(params: { symbol: string; isScheduled: boolean }) { )}

+ + Approve + ) } @@ -345,23 +348,25 @@ export function OrderRow({ {withWarning && ( - } + text={ {hasEnoughBalance === false && ( )} {hasEnoughAllowance === false && ( - + orderActions.approveOrderToken(order.inputToken)} + symbol={inputTokenSymbol} + isScheduled={isOrderScheduled} + /> )} } - placement="bottom" - > - - + /> )} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx index ec9f87962c..a335e391df 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/styled.tsx @@ -1,6 +1,8 @@ import { transparentize } from 'polished' import styled from 'styled-components/macro' +import QuestionHelper from 'legacy/components/QuestionHelper' + import { UI } from 'common/constants/theme' import { RateWrapper } from 'common/pure/RateInfo' @@ -23,6 +25,7 @@ export const WarningIndicator = styled.button<{ hasBackground?: boolean }>` svg > path { fill: ${({ theme }) => theme.alert}; + stroke: none; } ` @@ -30,6 +33,7 @@ export const WarningContent = styled.div` max-width: 270px; padding: 10px; color: ${({ theme }) => theme.black}; + background: ${({ theme }) => theme.alert}; h3, p { @@ -42,6 +46,10 @@ export const WarningContent = styled.div` } ` +export const StyledQuestionHelper = styled(QuestionHelper)` + margin: 0; +` + export const WarningParagraph = styled.div` margin-bottom: 20px; @@ -50,6 +58,10 @@ export const WarningParagraph = styled.div` } ` +export const WarningActionBox = styled.div` + margin-top: 15px; +` + export const RateValue = styled.span`` export const StatusBox = styled.div` diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx index 9b96ba327d..106ec79be7 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx @@ -46,6 +46,9 @@ const orderActions: OrderActions = { toggleOrdersForCancellation() { console.log('toggleAllOrdersForCancellation') }, + approveOrderToken() { + console.log('approveOrderToken ') + }, } export default ( diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/types.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/types.ts index e23b339ce2..6353201fac 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/types.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/types.ts @@ -1,3 +1,5 @@ +import { Token } from '@uniswap/sdk-core' + import { UseCancelOrderReturn } from 'common/hooks/useCancelOrder' import { ParsedOrder } from 'utils/orderUtils/parseOrder' @@ -6,4 +8,5 @@ export interface OrderActions { selectReceiptOrder(order: ParsedOrder): void toggleOrderForCancellation(order: ParsedOrder): void toggleOrdersForCancellation(orders: ParsedOrder[]): void + approveOrderToken(token: Token): void } From e4164ed382a14cc52a44133808d997aaf757ceb6 Mon Sep 17 00:00:00 2001 From: Leandro Date: Tue, 26 Sep 2023 01:18:29 -0700 Subject: [PATCH 17/36] feat(permit): update outdated permits (#3140) * chore: move getPermitUtilsInstance to its own file * fix: add default permit duration to Date.now() before transforming from ms to s * feat: check whether permit is still valid based on nonce * refactor: await the fn right where its declared * chore: remove debug statements * chore: lowercase account address in the cache key * chore: do one permit utils instance cache per type --- .../permit/utils/checkIsTokenPermittable.ts | 20 +-- .../permit/utils/generatePermitHook.ts | 116 +++++++++++++----- .../modules/permit/utils/getPermitDeadline.ts | 2 +- .../permit/utils/getPermitUtilsInstance.ts | 45 +++++++ 4 files changed, 133 insertions(+), 50 deletions(-) create mode 100644 apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts diff --git a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts index a55a0fb9a0..8eab04b4fc 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts @@ -4,10 +4,9 @@ import type { Web3Provider } from '@ethersproject/providers' import { DAI_LIKE_PERMIT_TYPEHASH, Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' -import { PermitProviderConnector } from 'modules/wallet/utils/PermitProviderConnector' - import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData' import { getPermitDeadline } from './getPermitDeadline' +import { getPermitUtilsInstance } from './getPermitUtilsInstance' import { DEFAULT_PERMIT_VALUE, PERMIT_GAS_LIMIT_MIN, PERMIT_SIGNER } from '../const' import { CheckIsTokenPermittableParams, EstimatePermitResult } from '../types' @@ -101,23 +100,6 @@ async function actuallyCheckTokenIsPermittable(params: CheckIsTokenPermittablePa } } -const PERMIT_UTILS_CACHE: Record = {} - -function getPermitUtilsInstance(chainId: SupportedChainId, provider: Web3Provider): Eip2612PermitUtils { - const cached = PERMIT_UTILS_CACHE[chainId] - - if (cached) { - return cached - } - - const web3ProviderConnector = new PermitProviderConnector(provider, PERMIT_SIGNER) - const eip2612PermitUtils = new Eip2612PermitUtils(web3ProviderConnector) - - PERMIT_UTILS_CACHE[chainId] = eip2612PermitUtils - - return eip2612PermitUtils -} - // TODO: refactor and make DAI like tokens work function estimateDaiLikeToken( tokenAddress: string, diff --git a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts index 207abece48..1f2e295bab 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts @@ -3,10 +3,9 @@ import { Web3Provider } from '@ethersproject/providers' import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' -import { PermitProviderConnector } from 'modules/wallet/utils/PermitProviderConnector' - import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData' import { getPermitDeadline } from './getPermitDeadline' +import { getPermitUtilsInstance } from './getPermitUtilsInstance' import { DEFAULT_PERMIT_GAS_LIMIT, DEFAULT_PERMIT_VALUE, PERMIT_SIGNER } from '../const' import { PermitHookData, PermitHookParams } from '../types' @@ -14,17 +13,21 @@ import { PermitHookData, PermitHookParams } from '../types' const CACHE_PREFIX = 'permitCache:v0-' const REQUESTS_CACHE: { [permitKey: string]: Promise } = {} -function getCacheKey(params: PermitHookParams): string { - const { inputToken, chainId, account } = params - - return `${CACHE_PREFIX}${inputToken.address.toLowerCase()}-${chainId}${account ? `-${account}` : ''}` -} - export async function generatePermitHook(params: PermitHookParams): Promise { const permitKey = getCacheKey(params) - const cachedResult = localStorage.getItem(permitKey) - if (cachedResult) return JSON.parse(cachedResult) + const { chainId, provider, account, inputToken } = params + + const eip2162Utils = getPermitUtilsInstance(chainId, provider, account) + + // Always get the nonce for the real account, to know whether the cache should be invalidated + // Static account should never need to pre-check the nonce as it'll never change once cached + const nonce = account ? await eip2162Utils.getTokenNonce(inputToken.address, account) : undefined + + const cachedResult = load(permitKey, nonce) + if (cachedResult) { + return cachedResult + } const cachedRequest = REQUESTS_CACHE[permitKey] @@ -37,10 +40,12 @@ export async function generatePermitHook(params: PermitHookParams): Promise { - const permitHook = JSON.stringify(permitHookData) + const request = generatePermitHookRaw({ ...params, eip2162Utils, preFetchedNonce: nonce }).then((permitHookData) => { + // Store permit in the cache + save(permitKey, nonce, permitHookData) - localStorage.setItem(permitKey, permitHook) + // Remove consumed request to avoid stale data + delete REQUESTS_CACHE[permitKey] return permitHookData }) @@ -50,30 +55,27 @@ export async function generatePermitHook(params: PermitHookParams): Promise { - const { inputToken, chainId, permitInfo, provider, account } = params +async function generatePermitHookRaw( + params: PermitHookParams & { eip2162Utils: Eip2612PermitUtils; preFetchedNonce: number | undefined } +): Promise { + const { inputToken, chainId, permitInfo, provider, account, eip2162Utils, preFetchedNonce } = params const tokenAddress = inputToken.address const tokenName = inputToken.name || tokenAddress - // TODO: verify whether cached result is still valid and renew it if needed - - const web3ProviderConnector = new PermitProviderConnector(provider, account ? undefined : PERMIT_SIGNER) - const eip2612PermitUtils = new Eip2612PermitUtils(web3ProviderConnector) - const owner = account || PERMIT_SIGNER.address - // TODO: check whether cached permit nonce matches current nonce and update it in case it doesnt - - const nonce = await eip2612PermitUtils.getTokenNonce(tokenAddress, owner) + // Only fetch the nonce in case it wasn't pre-fetched before + // That's the case for static account + const nonce = preFetchedNonce === undefined ? await eip2162Utils.getTokenNonce(tokenAddress, owner) : preFetchedNonce const spender = GP_VAULT_RELAYER[chainId] const deadline = getPermitDeadline() const value = DEFAULT_PERMIT_VALUE - const callDataPromise = + const callData = permitInfo.type === 'eip-2612' - ? buildEip2162PermitCallData({ - eip2162Utils: eip2612PermitUtils, + ? await buildEip2162PermitCallData({ + eip2162Utils, callDataParams: [ { owner, @@ -87,8 +89,8 @@ async function generatePermitHookRaw(params: PermitHookParams): Promise() +/** + * Cache by provider. Here we cache per provider as each account should have its own instance + */ +const PROVIDER_UTILS_CACHE = new Map() + +export function getPermitUtilsInstance( + chainId: SupportedChainId, + provider: Web3Provider, + account?: string | undefined +): Eip2612PermitUtils { + const chainCache = CHAIN_UTILS_CACHE.get(chainId) + + if (!account && chainCache) { + return chainCache + } + const providerCache = PROVIDER_UTILS_CACHE.get(provider) + + if (providerCache) { + return providerCache + } + + const web3ProviderConnector = new PermitProviderConnector(provider, account ? undefined : PERMIT_SIGNER) + const eip2612PermitUtils = new Eip2612PermitUtils(web3ProviderConnector) + + if (!account) { + CHAIN_UTILS_CACHE.set(chainId, eip2612PermitUtils) + } else { + PROVIDER_UTILS_CACHE.set(provider, eip2612PermitUtils) + } + + return eip2612PermitUtils +} From 3370b4266674f978c4a9c6ae375cf0f75d56a353 Mon Sep 17 00:00:00 2001 From: Leandro Date: Tue, 26 Sep 2023 01:34:08 -0700 Subject: [PATCH 18/36] feat(permit): limit orders (fill or kill only) (#3142) * chore: remove redundant appData. It's already inside postOrderParams * feat: do not show approval button when token is permittable * chore: pass permit related params to limit orders' tradeFlowContext * feat: use permit hook when placing limit order * feat: add handlePermit util fn * refactor: use handlePermit on swapFlow and tradeFlow * fix: update TradeFlowContext instances * chore: move analytics after permit --- .../src/mocks/tradeStateMock.ts | 3 +- .../limitOrders/hooks/useTradeFlowContext.ts | 14 +++- .../pure/LimitOrdersDetails/index.cosmos.tsx | 7 +- .../limitOrders/services/tradeFlow/index.ts | 71 ++++++++++++------- .../src/modules/limitOrders/services/types.ts | 5 +- .../src/modules/permit/index.ts | 1 + .../src/modules/permit/types.ts | 8 +++ .../src/modules/permit/utils/handlePermit.ts | 36 ++++++++++ .../modules/swap/services/swapFlow/index.ts | 37 ++++------ .../hooks/useTradeFormValidationContext.ts | 4 ++ .../services/validateTradeForm.ts | 7 +- .../src/modules/tradeFormValidation/types.ts | 1 + 12 files changed, 136 insertions(+), 58 deletions(-) create mode 100644 apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts diff --git a/apps/cowswap-frontend/src/mocks/tradeStateMock.ts b/apps/cowswap-frontend/src/mocks/tradeStateMock.ts index 55d6737961..84523caefd 100644 --- a/apps/cowswap-frontend/src/mocks/tradeStateMock.ts +++ b/apps/cowswap-frontend/src/mocks/tradeStateMock.ts @@ -50,6 +50,8 @@ export const outputCurrencyInfoMock: CurrencyInfo = { } export const tradeContextMock: TradeFlowContext = { + hasEnoughAllowance: undefined, + permitInfo: undefined, postOrderParams: { class: OrderClass.LIMIT, account: '0x000', @@ -68,7 +70,6 @@ export const tradeContextMock: TradeFlowContext = { appData: getAppData(), }, rateImpact: 0, - appData: {} as any, provider: {} as any, settlementContract: {} as any, chainId: 1, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts index b993a8130d..ef2822b58f 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts @@ -1,5 +1,6 @@ import { useAtomValue } from 'jotai' +import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' import { useGP2SettlementContract } from '@cowprotocol/common-hooks' import { OrderClass } from '@cowprotocol/cow-sdk' import { useGnosisSafeInfo, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' @@ -14,6 +15,8 @@ import { useAppData } from 'modules/appData' import { useRateImpact } from 'modules/limitOrders/hooks/useRateImpact' import { TradeFlowContext } from 'modules/limitOrders/services/types' import { limitOrdersSettingsAtom } from 'modules/limitOrders/state/limitOrdersSettingsAtom' +import { useIsTokenPermittable } from 'modules/permit' +import { useEnoughBalanceAndAllowance } from 'modules/tokens' import { useTradeQuote } from 'modules/tradeQuote' import { useLimitOrdersDerivedState } from './useLimitOrdersDerivedState' @@ -30,6 +33,14 @@ export function useTradeFlowContext(): TradeFlowContext | null { const quoteState = useTradeQuote() const rateImpact = useRateImpact() const settingsState = useAtomValue(limitOrdersSettingsAtom) + const permitInfo = useIsTokenPermittable(state.inputCurrency) + + const checkAllowanceAddress = GP_VAULT_RELAYER[chainId] + const { enoughAllowance: hasEnoughAllowance } = useEnoughBalanceAndAllowance({ + account, + amount: state.slippageAdjustedSellAmount || undefined, + checkAllowanceAddress, + }) if ( !chainId || @@ -62,8 +73,9 @@ export function useTradeFlowContext(): TradeFlowContext | null { isGnosisSafeWallet, dispatch, provider, - appData, rateImpact, + permitInfo, + hasEnoughAllowance, postOrderParams: { class: OrderClass.LIMIT, kind: state.orderKind, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx index 8e246a0168..2a71f011a8 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx @@ -1,9 +1,7 @@ import { SetStateAction } from 'jotai' import { COW, GNO } from '@cowprotocol/common-const' -import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { OrderKind } from '@cowprotocol/cow-sdk' -import { OrderClass } from '@cowprotocol/cow-sdk' +import { OrderClass, OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount } from '@uniswap/sdk-core' import { getAppData } from 'modules/appData' @@ -18,6 +16,8 @@ const inputCurrency = COW[SupportedChainId.MAINNET] const outputCurrency = GNO[SupportedChainId.MAINNET] const tradeContext: TradeFlowContext = { + hasEnoughAllowance: undefined, + permitInfo: undefined, postOrderParams: { class: OrderClass.LIMIT, account: '0x000', @@ -36,7 +36,6 @@ const tradeContext: TradeFlowContext = { appData: getAppData(), }, rateImpact: 0, - appData: {} as any, provider: {} as any, settlementContract: {} as any, chainId: 1, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts index fcd22122d1..b61ef7ffc8 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts @@ -9,10 +9,10 @@ import { LOW_RATE_THRESHOLD_PERCENT } from 'modules/limitOrders/const/trade' import { PriceImpactDeclineError, TradeFlowContext } from 'modules/limitOrders/services/types' import { LimitOrdersSettingsState } from 'modules/limitOrders/state/limitOrdersSettingsAtom' import { calculateLimitOrdersDeadline } from 'modules/limitOrders/utils/calculateLimitOrdersDeadline' +import { handlePermit } from 'modules/permit' import { presignOrderStep } from 'modules/swap/services/swapFlow/steps/presignOrderStep' import { addPendingOrderStep } from 'modules/trade/utils/addPendingOrderStep' -import { tradeFlowAnalytics } from 'modules/trade/utils/analytics' -import { SwapFlowAnalyticsContext } from 'modules/trade/utils/analytics' +import { SwapFlowAnalyticsContext, tradeFlowAnalytics } from 'modules/trade/utils/analytics' import { logTradeFlow } from 'modules/trade/utils/logger' import { getSwapErrorMessage } from 'modules/trade/utils/swapErrorHelper' @@ -23,7 +23,19 @@ export async function tradeFlow( confirmPriceImpactWithoutFee: (priceImpact: Percent) => Promise, beforeTrade?: () => void ): Promise { - const { account, recipientAddressOrName, sellToken, buyToken } = params.postOrderParams + const { + postOrderParams, + rateImpact, + permitInfo, + provider, + chainId, + hasEnoughAllowance, + allowsOffchainSigning, + settlementContract, + dispatch, + isGnosisSafeWallet, + } = params + const { account, recipientAddressOrName, sellToken, buyToken, appData } = postOrderParams const marketLabel = [sellToken.symbol, buyToken.symbol].join(',') const swapFlowAnalyticsContext: SwapFlowAnalyticsContext = { account, @@ -34,64 +46,75 @@ export async function tradeFlow( } logTradeFlow('LIMIT ORDER FLOW', 'STEP 1: confirm price impact') - const isTooLowRate = params.rateImpact < LOW_RATE_THRESHOLD_PERCENT + const isTooLowRate = rateImpact < LOW_RATE_THRESHOLD_PERCENT if (!isTooLowRate && priceImpact.priceImpact && !(await confirmPriceImpactWithoutFee(priceImpact.priceImpact))) { throw new PriceImpactDeclineError() } - logTradeFlow('LIMIT ORDER FLOW', 'STEP 2: send transaction') - tradeFlowAnalytics.trade(swapFlowAnalyticsContext) - beforeTrade?.() - const validTo = calculateLimitOrdersDeadline(settingsState) try { - logTradeFlow('LIMIT ORDER FLOW', 'STEP 3: sign and post order') + logTradeFlow('LIMIT ORDER FLOW', 'STEP 2: handle permit') + postOrderParams.appData = await handlePermit({ + permitInfo, + hasEnoughAllowance, + inputToken: sellToken, + provider, + account, + chainId, + appData, + }) + + logTradeFlow('LIMIT ORDER FLOW', 'STEP 3: send transaction') + tradeFlowAnalytics.trade(swapFlowAnalyticsContext) + beforeTrade?.() + + logTradeFlow('LIMIT ORDER FLOW', 'STEP 4: sign and post order') const { id: orderId, order } = await signAndPostOrder({ - ...params.postOrderParams, - signer: params.provider.getSigner(), + ...postOrderParams, + signer: provider.getSigner(), validTo, }) - logTradeFlow('LIMIT ORDER FLOW', 'STEP 4: add pending order step') + logTradeFlow('LIMIT ORDER FLOW', 'STEP 5: add pending order step') addPendingOrderStep( { id: orderId, - chainId: params.chainId, + chainId: chainId, order: { ...order, - isHidden: !params.allowsOffchainSigning, + isHidden: !allowsOffchainSigning, }, }, - params.dispatch + dispatch ) - logTradeFlow('LIMIT ORDER FLOW', 'STEP 5: presign order (optional)') - const presignTx = await (params.allowsOffchainSigning + logTradeFlow('LIMIT ORDER FLOW', 'STEP 6: presign order (optional)') + const presignTx = await (allowsOffchainSigning ? Promise.resolve(null) - : presignOrderStep(orderId, params.settlementContract)) + : presignOrderStep(orderId, settlementContract)) - logTradeFlow('LIMIT ORDER FLOW', 'STEP 6: unhide SC order (optional)') + logTradeFlow('LIMIT ORDER FLOW', 'STEP 7: unhide SC order (optional)') if (presignTx) { partialOrderUpdate( { - chainId: params.chainId, + chainId, order: { id: order.id, - presignGnosisSafeTxHash: params.isGnosisSafeWallet ? presignTx.hash : undefined, + presignGnosisSafeTxHash: isGnosisSafeWallet ? presignTx.hash : undefined, isHidden: false, }, }, - params.dispatch + dispatch ) } - logTradeFlow('LIMIT ORDER FLOW', 'STEP 7: Sign order') + logTradeFlow('LIMIT ORDER FLOW', 'STEP 8: Sign order') tradeFlowAnalytics.sign(swapFlowAnalyticsContext) return orderId } catch (error: any) { - logTradeFlow('LIMIT ORDER FLOW', 'STEP 8: ERROR: ', error) + logTradeFlow('LIMIT ORDER FLOW', 'STEP 9: ERROR: ', error) const swapErrorMessage = getSwapErrorMessage(error) tradeFlowAnalytics.error(error, swapErrorMessage, swapFlowAnalyticsContext) diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts index 54e51d1798..2c88ed15d9 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts @@ -6,7 +6,7 @@ import SafeAppsSDK from '@safe-global/safe-apps-sdk' import { AppDispatch } from 'legacy/state' import { PostOrderParams } from 'legacy/utils/trade' -import { AppDataInfo } from 'modules/appData' +import { PermitInfo } from 'modules/permit' export interface TradeFlowContext { // signer changes creates redundant re-renders @@ -16,10 +16,11 @@ export interface TradeFlowContext { chainId: SupportedChainId dispatch: AppDispatch rateImpact: number - appData: AppDataInfo provider: Web3Provider allowsOffchainSigning: boolean isGnosisSafeWallet: boolean + permitInfo: PermitInfo | undefined + hasEnoughAllowance: boolean | undefined } export interface SafeBundleFlowContext extends TradeFlowContext { diff --git a/apps/cowswap-frontend/src/modules/permit/index.ts b/apps/cowswap-frontend/src/modules/permit/index.ts index f060dce5cd..ef487d8884 100644 --- a/apps/cowswap-frontend/src/modules/permit/index.ts +++ b/apps/cowswap-frontend/src/modules/permit/index.ts @@ -1,4 +1,5 @@ export { useAccountAgnosticPermitHookData } from './hooks/useAccountAgnosticPermitHookData' export { generatePermitHook } from './utils/generatePermitHook' export { useIsTokenPermittable } from './hooks/useIsTokenPermittable' +export { handlePermit } from './utils/handlePermit' export * from './types' diff --git a/apps/cowswap-frontend/src/modules/permit/types.ts b/apps/cowswap-frontend/src/modules/permit/types.ts index baa427015f..f0eaa79a7f 100644 --- a/apps/cowswap-frontend/src/modules/permit/types.ts +++ b/apps/cowswap-frontend/src/modules/permit/types.ts @@ -5,6 +5,8 @@ import { Token } from '@uniswap/sdk-core' import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' +import { AppDataInfo } from 'modules/appData' + export type PermitType = 'dai-like' | 'eip-2612' export type SupportedPermitInfo = { @@ -32,6 +34,12 @@ export type PermitHookParams = { account?: string } +export type HandlePermitParams = Omit & { + permitInfo: IsTokenPermittableResult + hasEnoughAllowance: undefined | boolean + appData: AppDataInfo +} + export type PermitHookData = latest.CoWHook type FailedToIdentify = { error: string } diff --git a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts new file mode 100644 index 0000000000..5f2d37ba91 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts @@ -0,0 +1,36 @@ +import { AppDataInfo, buildAppDataHooks, updateHooksOnAppData } from 'modules/appData' +import { generatePermitHook, HandlePermitParams } from 'modules/permit' + +/** + * Handle token permit + * + * Will request user signature if needed + * Can use cached permit if available + * + * If not needed, will remove any permit info from appData + * + * Returns the updated appData + */ +export async function handlePermit(params: HandlePermitParams): Promise { + const { permitInfo, hasEnoughAllowance, inputToken, provider, account, chainId, appData } = params + + if (permitInfo && !hasEnoughAllowance) { + // If token is permittable and there's not enough allowance, get the permit hook + + // TODO: maybe we need a modal to inform the user what they need to sign? + const permitData = await generatePermitHook({ + inputToken, + provider, + account, + chainId, + permitInfo, + }) + + const hooks = buildAppDataHooks([permitData]) + + return updateHooksOnAppData(appData, hooks) + } else { + // Otherwise, remove hooks (if any) from appData to avoid stale data + return updateHooksOnAppData(appData, undefined) + } +} diff --git a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts index 67ba87bba4..98de4a2c54 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts @@ -5,8 +5,7 @@ import { PriceImpact } from 'legacy/hooks/usePriceImpact' import { partialOrderUpdate } from 'legacy/state/orders/utils' import { signAndPostOrder } from 'legacy/utils/trade' -import { buildAppDataHooks, updateHooksOnAppData } from 'modules/appData' -import { generatePermitHook } from 'modules/permit' +import { handlePermit } from 'modules/permit' import { addPendingOrderStep } from 'modules/trade/utils/addPendingOrderStep' import { tradeFlowAnalytics } from 'modules/trade/utils/analytics' import { logTradeFlow } from 'modules/trade/utils/logger' @@ -26,11 +25,12 @@ export async function swapFlow( return } - if (input.permitInfo && !input.hasEnoughAllowance) { - // If token is permittable and there's not enough allowance, get th permit hook + try { + logTradeFlow('SWAP FLOW', 'STEP 2: handle permit') + input.orderParams.appData = await handlePermit({ + appData: input.orderParams.appData, + hasEnoughAllowance: input.hasEnoughAllowance, - // TODO: maybe we need a modal to inform the user what they need to sign? - const permitData = await generatePermitHook({ inputToken: input.context.trade.inputAmount.currency as Token, provider: input.orderParams.signer.provider as Web3Provider, account: input.orderParams.account, @@ -38,20 +38,11 @@ export async function swapFlow( permitInfo: input.permitInfo, }) - const hooks = buildAppDataHooks([permitData]) - - input.orderParams.appData = await updateHooksOnAppData(input.orderParams.appData, hooks) - } else { - // Otherwise, remove hooks (if any) from appData to avoid stale data - input.orderParams.appData = await updateHooksOnAppData(input.orderParams.appData, undefined) - } + logTradeFlow('SWAP FLOW', 'STEP 3: send transaction') + tradeFlowAnalytics.trade(input.swapFlowAnalyticsContext) + input.swapConfirmManager.sendTransaction(input.context.trade) - logTradeFlow('SWAP FLOW', 'STEP 2: send transaction') - tradeFlowAnalytics.trade(input.swapFlowAnalyticsContext) - input.swapConfirmManager.sendTransaction(input.context.trade) - - try { - logTradeFlow('SWAP FLOW', 'STEP 3: sign and post order') + logTradeFlow('SWAP FLOW', 'STEP 4: sign and post order') const { id: orderId, order } = await signAndPostOrder(input.orderParams).finally(() => { input.callbacks.closeModals() }) @@ -68,12 +59,12 @@ export async function swapFlow( input.dispatch ) - logTradeFlow('SWAP FLOW', 'STEP 4: presign order (optional)') + logTradeFlow('SWAP FLOW', 'STEP 5: presign order (optional)') const presignTx = await (input.flags.allowsOffchainSigning ? Promise.resolve(null) : presignOrderStep(orderId, input.contract)) - logTradeFlow('SWAP FLOW', 'STEP 5: unhide SC order (optional)') + logTradeFlow('SWAP FLOW', 'STEP 6: unhide SC order (optional)') if (presignTx) { partialOrderUpdate( { @@ -88,11 +79,11 @@ export async function swapFlow( ) } - logTradeFlow('SWAP FLOW', 'STEP 6: show UI of the successfully sent transaction', orderId) + logTradeFlow('SWAP FLOW', 'STEP 7: show UI of the successfully sent transaction', orderId) input.swapConfirmManager.transactionSent(orderId) tradeFlowAnalytics.sign(input.swapFlowAnalyticsContext) } catch (error: any) { - logTradeFlow('SWAP FLOW', 'STEP 7: ERROR: ', error) + logTradeFlow('SWAP FLOW', 'STEP 8: ERROR: ', error) const swapErrorMessage = getSwapErrorMessage(error) tradeFlowAnalytics.error(error, swapErrorMessage, input.swapFlowAnalyticsContext) diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts index a558e0c4b2..f60e9adb3b 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts @@ -6,6 +6,7 @@ import { useGnosisSafeInfo, useIsBundlingSupported, useWalletDetails, useWalletI import { useIsTradeUnsupported } from 'legacy/state/lists/hooks' import { isUnsupportedTokenInQuote } from 'modules/limitOrders/utils/isUnsupportedTokenInQuote' +import { useIsTokenPermittable } from 'modules/permit' import { useDerivedTradeState } from 'modules/trade/hooks/useDerivedTradeState' import { useIsWrapOrUnwrap } from 'modules/trade/hooks/useIsWrapOrUnwrap' import { useTradeQuote } from 'modules/tradeQuote' @@ -32,6 +33,8 @@ export function useTradeFormValidationContext(): TradeFormValidationCommonContex const isSafeReadonlyUser = gnosisSafeInfo?.isReadOnly || false + const isPermitSupported = !!useIsTokenPermittable(inputCurrency) + const commonContext = { account, isWrapUnwrap, @@ -42,6 +45,7 @@ export function useTradeFormValidationContext(): TradeFormValidationCommonContex recipientEnsAddress, approvalState, tradeQuote, + isPermitSupported, } return useMemo(() => { diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts index c47501c73c..c128750939 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/services/validateTradeForm.ts @@ -1,5 +1,4 @@ -import { isFractionFalsy } from '@cowprotocol/common-utils' -import { isAddress } from '@cowprotocol/common-utils' +import { isAddress, isFractionFalsy } from '@cowprotocol/common-utils' import { ApprovalState } from 'legacy/hooks/useApproveCallback/useApproveCallbackMod' @@ -18,11 +17,13 @@ export function validateTradeForm(context: TradeFormValidationContext): TradeFor recipientEnsAddress, tradeQuote, account, + isPermitSupported, } = context const { inputCurrency, outputCurrency, inputCurrencyAmount, inputCurrencyBalance, recipient } = derivedTradeState - const approvalRequired = approvalState === ApprovalState.NOT_APPROVED || approvalState === ApprovalState.PENDING + const approvalRequired = + !isPermitSupported && (approvalState === ApprovalState.NOT_APPROVED || approvalState === ApprovalState.PENDING) const inputAmountIsNotSet = !inputCurrencyAmount || isFractionFalsy(inputCurrencyAmount) diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts index a889122039..5f14fa9cb9 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/types.ts @@ -49,6 +49,7 @@ export interface TradeFormValidationCommonContext { isSupportedWallet: boolean isSwapUnsupported: boolean isSafeReadonlyUser: boolean + isPermitSupported: boolean } export interface TradeFormValidationContext extends TradeFormValidationLocalContext, TradeFormValidationCommonContext {} From 05843dbef864eb2054b7ea8ad7e8898e8eb948cc Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Wed, 27 Sep 2023 16:13:07 +0600 Subject: [PATCH 19/36] fix: don't fetch tokens list ens hashes (#3152) * fix: don't fetch tokens list ens hashes * fix: cache token list ens hash for 6 hours * chore: refactor --- .../src/legacy/hooks/useFetchListCallback.ts | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts b/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts index dfc39abab8..4246458c47 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/useFetchListCallback.ts @@ -1,27 +1,60 @@ +import { useAtomValue, useSetAtom } from 'jotai' +import { atomWithStorage } from 'jotai/utils' import { useCallback } from 'react' import { MAINNET_PROVIDER } from '@cowprotocol/common-const' -import { resolveENSContentHash } from '@cowprotocol/common-utils' +import { atomWithPartialUpdate, resolveENSContentHash } from '@cowprotocol/common-utils' import { useWalletInfo } from '@cowprotocol/wallet' import { TokenList } from '@uniswap/token-lists' import { nanoid } from '@reduxjs/toolkit' +import ms from 'ms.macro' import { useAppDispatch } from 'legacy/state/hooks' import { fetchTokenList } from 'legacy/state/lists/actions' import getTokenList from 'lib/hooks/useTokenList/fetchTokenList' +const TOKENS_LIST_ENS_CACHE_TIMEOUT = ms`6h` + +interface TokensListEnsCache { + timestamp: number + value: string +} + +const { atom: tokensListEnsCachesAtom, updateAtom: updateTokensListEnsCachesAtom } = atomWithPartialUpdate( + atomWithStorage<{ [ensName: string]: TokensListEnsCache }>('tokensListEnsCaches:v1', {}) +) + +const isCacheValid = ({ timestamp }: TokensListEnsCache) => Date.now() - timestamp < TOKENS_LIST_ENS_CACHE_TIMEOUT + export function useFetchListCallback(): (listUrl: string, sendDispatch?: boolean) => Promise { const dispatch = useAppDispatch() const { chainId } = useWalletInfo() + const tokensListEnsCaches = useAtomValue(tokensListEnsCachesAtom) + const setTokensListEnsCaches = useSetAtom(updateTokensListEnsCachesAtom) + // note: prevent dispatch if using for list search or unsupported list return useCallback( async (listUrl: string, sendDispatch = true) => { const requestId = nanoid() sendDispatch && dispatch(fetchTokenList.pending({ requestId, url: listUrl, chainId })) - return getTokenList(listUrl, (ensName: string) => resolveENSContentHash(ensName, MAINNET_PROVIDER)) + return getTokenList(listUrl, (ensName: string) => { + const cached = tokensListEnsCaches[ensName] + + // Return cached value if it's not stale + if (cached && isCacheValid(cached)) { + return Promise.resolve(cached.value) + } + + return resolveENSContentHash(ensName, MAINNET_PROVIDER).then((value) => { + // Cache the fetched value + setTokensListEnsCaches({ [ensName]: { timestamp: Date.now(), value } }) + + return value + }) + }) .then((tokenList) => { // Mod: add chainId sendDispatch && dispatch(fetchTokenList.fulfilled({ url: listUrl, tokenList, requestId, chainId })) @@ -34,6 +67,6 @@ export function useFetchListCallback(): (listUrl: string, sendDispatch?: boolean throw error }) }, - [chainId, dispatch] + [chainId, dispatch, setTokensListEnsCaches, tokensListEnsCaches] ) } From 48af81017d796b4e5c39a06e6a1cf6f2aa943578 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Thu, 28 Sep 2023 19:09:08 +0600 Subject: [PATCH 20/36] chore: fix cosmos CI (#3163) * chore: fix cosmos CI * chore: fix cosmos CI --- apps/cowswap-frontend/cosmos.config.json | 2 +- apps/cowswap-frontend/package.json | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/apps/cowswap-frontend/cosmos.config.json b/apps/cowswap-frontend/cosmos.config.json index e6367b2b64..70dc78a271 100644 --- a/apps/cowswap-frontend/cosmos.config.json +++ b/apps/cowswap-frontend/cosmos.config.json @@ -3,7 +3,7 @@ "fixtureFileSuffix": "cosmos", "watchDirs": ["src"], "port": 5001, - "exportPath": "./public/cosmos", + "exportPath": "../../build/cosmos", "publicUrl": "./", "plugins": ["react-cosmos-plugin-vite"], "vite": { diff --git a/apps/cowswap-frontend/package.json b/apps/cowswap-frontend/package.json index 9b31c7b72c..0b3b20ea50 100644 --- a/apps/cowswap-frontend/package.json +++ b/apps/cowswap-frontend/package.json @@ -5,18 +5,18 @@ "author": "", "license": "ISC", "scripts": { - "ipfs:build": "nx exec -- cross-env PUBLIC_URL=\".\" yarn build", - "ipfs:publish": "nx exec -- ipfs-deploy build -p pinata -O", - "patch-package": "nx exec -- patch-package", - "i18n": "nx exec -- yarn i18n:compile", - "i18n:compile": "yarn i18n:extract && lingui compile", - "i18n:extract": "cross-env NODE_ENV=development lingui extract --locale en-US", - "i18n:pseudo": "lingui extract --locale pseudo && lingui compile", - "postinstall": "yarn i18n", - "cosmos:clear": "nx exec -- rm -rf ./public/cosmos", - "cosmos:run": "nx exec -- yarn _cosmos:run ", - "cosmos:export": "nx exec -- cross-env NODE_ENV=development cosmos-export", - "_cosmos:run": "yarn cosmos:clear && cosmos" + "ipfs:build": "cross-env PUBLIC_URL=\".\" yarn build", + "ipfs:publish": "npx ipfs-deploy build -p pinata -O", + "patch-package": "npx patch-package", + "i18n": "yarn run i18n:compile", + "i18n:compile": "yarn run i18n:extract && npx lingui compile", + "i18n:extract": "cross-env NODE_ENV=development npx lingui extract --locale en-US", + "i18n:pseudo": "npx lingui extract --locale pseudo && lingui compile", + "postinstall": "yarn run i18n", + "cosmos:clear": "rm -rf ./public/cosmos", + "cosmos:run": "yarn run _cosmos:run", + "cosmos:export": "cross-env NODE_ENV=development npx cosmos-export", + "_cosmos:run": "yarn cosmos:clear && npx cosmos" }, "browser": { "crypto": false From 93674f5c2ff0929d6085c2e363fa9fd9e467d188 Mon Sep 17 00:00:00 2001 From: Leandro Date: Thu, 28 Sep 2023 06:32:39 -0700 Subject: [PATCH 21/36] feat(permit): quote by order type (#3155) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: change TradeType enum from number to string * refactor: minor linting * fix: do not pass a obj key with undefined * chore: add TradeType to TradeDerivedState * feat: add const with mapping of order types and whether it supports permit ⚠️ limit permit support is disabled * feat: require TradeType to indentify whether token is permittable * chore: reset permit hook data when there are no pemrit params * fix: unit tests --- .../hooks/useAdvancedOrdersDerivedState.ts | 5 +++-- .../src/modules/appData/utils/buildAppDataHooks.ts | 4 ++-- .../hooks/useLimitOrdersDerivedState.ts | 5 +++-- .../limitOrders/hooks/useTradeFlowContext.ts | 3 ++- apps/cowswap-frontend/src/modules/permit/const.ts | 8 ++++++++ .../hooks/useAccountAgnosticPermitHookData.ts | 10 +++++++--- .../modules/permit/hooks/useIsTokenPermittable.ts | 14 +++++++++++--- .../src/modules/swap/hooks/useSwapButtonContext.ts | 8 ++++---- .../src/modules/swap/hooks/useSwapFlowContext.ts | 7 ++++--- .../src/modules/swap/state/useSwapDerivedState.ts | 2 ++ .../modules/trade/hooks/useDerivedTradeState.ts | 12 +++--------- .../src/modules/trade/hooks/useTradeTypeInfo.ts | 6 +++--- .../src/modules/trade/types/TradeDerivedState.ts | 4 ++++ .../hooks/useTradeFormValidationContext.ts | 4 ++-- .../twap/services/createTwapOrderTxs.test.ts | 5 +++-- 15 files changed, 61 insertions(+), 36 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersDerivedState.ts b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersDerivedState.ts index b58e60be28..01bf0817c3 100644 --- a/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersDerivedState.ts +++ b/apps/cowswap-frontend/src/modules/advancedOrders/hooks/useAdvancedOrdersDerivedState.ts @@ -1,11 +1,12 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useEffect } from 'react' +import { TradeType } from 'modules/trade' import { useBuildTradeDerivedState } from 'modules/trade/hooks/useBuildTradeDerivedState' import { - AdvancedOrdersDerivedState, advancedOrdersAtom, + AdvancedOrdersDerivedState, advancedOrdersDerivedStateAtom, } from '../state/advancedOrdersAtom' @@ -21,6 +22,6 @@ export function useFillAdvancedOrdersDerivedState() { const isUnlocked = rawState.isUnlocked useEffect(() => { - updateDerivedState({ ...derivedState, isUnlocked }) + updateDerivedState({ ...derivedState, isUnlocked, tradeType: TradeType.ADVANCED_ORDERS }) }, [derivedState, isUnlocked, updateDerivedState]) } diff --git a/apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts b/apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts index cc671136b8..a03512a3ae 100644 --- a/apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts +++ b/apps/cowswap-frontend/src/modules/appData/utils/buildAppDataHooks.ts @@ -9,7 +9,7 @@ export function buildAppDataHooks( } return { - ...{ pre: preInteractionHooks || undefined }, - ...{ post: postInteractionHooks || undefined }, + ...(preInteractionHooks ? { pre: preInteractionHooks } : undefined), + ...(postInteractionHooks ? { post: postInteractionHooks } : undefined), } } diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersDerivedState.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersDerivedState.ts index 3d9b624b36..061a285f8e 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersDerivedState.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useLimitOrdersDerivedState.ts @@ -2,10 +2,11 @@ import { useAtomValue, useSetAtom } from 'jotai' import { useEffect } from 'react' import { - limitOrdersRawStateAtom, LimitOrdersDerivedState, limitOrdersDerivedStateAtom, + limitOrdersRawStateAtom, } from 'modules/limitOrders/state/limitOrdersRawStateAtom' +import { TradeType } from 'modules/trade' import { useBuildTradeDerivedState } from 'modules/trade/hooks/useBuildTradeDerivedState' export function useLimitOrdersDerivedState(): LimitOrdersDerivedState { @@ -20,6 +21,6 @@ export function useFillLimitOrdersDerivedState() { const derivedState = useBuildTradeDerivedState(limitOrdersRawStateAtom) useEffect(() => { - updateDerivedState({ ...derivedState, isUnlocked }) + updateDerivedState({ ...derivedState, isUnlocked, tradeType: TradeType.LIMIT_ORDER }) }, [derivedState, updateDerivedState, isUnlocked]) } diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts index ef2822b58f..7d0f090eb3 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts @@ -17,6 +17,7 @@ import { TradeFlowContext } from 'modules/limitOrders/services/types' import { limitOrdersSettingsAtom } from 'modules/limitOrders/state/limitOrdersSettingsAtom' import { useIsTokenPermittable } from 'modules/permit' import { useEnoughBalanceAndAllowance } from 'modules/tokens' +import { TradeType } from 'modules/trade' import { useTradeQuote } from 'modules/tradeQuote' import { useLimitOrdersDerivedState } from './useLimitOrdersDerivedState' @@ -33,7 +34,7 @@ export function useTradeFlowContext(): TradeFlowContext | null { const quoteState = useTradeQuote() const rateImpact = useRateImpact() const settingsState = useAtomValue(limitOrdersSettingsAtom) - const permitInfo = useIsTokenPermittable(state.inputCurrency) + const permitInfo = useIsTokenPermittable(state.inputCurrency, TradeType.LIMIT_ORDER) const checkAllowanceAddress = GP_VAULT_RELAYER[chainId] const { enoughAllowance: hasEnoughAllowance } = useEnoughBalanceAndAllowance({ diff --git a/apps/cowswap-frontend/src/modules/permit/const.ts b/apps/cowswap-frontend/src/modules/permit/const.ts index 9f534b3bc4..81f276485a 100644 --- a/apps/cowswap-frontend/src/modules/permit/const.ts +++ b/apps/cowswap-frontend/src/modules/permit/const.ts @@ -4,6 +4,8 @@ import { Wallet } from '@ethersproject/wallet' import ms from 'ms.macro' +import { TradeType } from '../trade' + // PK used only for signing permit requests for quoting and identifying token 'permittability' // Do not use or try to send funds to it. Or do. It'll be your funds 🤷 const PERMIT_PK = '0xc58a2a421ca71ca57ae698f1c32feeb0b0ccb434da0b8089d88d80fb918f3f9d' // address: 0xFf65D1DfCF256cf4A8D5F2fb8e70F936606B7474 @@ -21,3 +23,9 @@ export const DEFAULT_PERMIT_GAS_LIMIT = '80000' export const DEFAULT_PERMIT_VALUE = MaxUint256.toString() export const DEFAULT_PERMIT_DURATION = ms`5 years` + +export const ORDER_TYPE_SUPPORTS_PERMIT: Record = { + [TradeType.SWAP]: true, + [TradeType.LIMIT_ORDER]: false, + [TradeType.ADVANCED_ORDERS]: false, +} diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts index d778e690b3..b4d95a2d79 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts @@ -26,7 +26,11 @@ export function useAccountAgnosticPermitHookData(): PermitHookData | undefined { const [data, setData] = useState(undefined) useEffect(() => { - if (!params) return + if (!params) { + setData(undefined) + + return + } generatePermitHook(params).then(setData) }, [params]) @@ -39,9 +43,9 @@ function usePermitHookParams(): PermitHookParams | undefined { const { provider } = useWeb3React() const { state } = useDerivedTradeState() - const { inputCurrency } = state || {} + const { inputCurrency, tradeType } = state || {} - const permitInfo = useIsTokenPermittable(inputCurrency) + const permitInfo = useIsTokenPermittable(inputCurrency, tradeType) return useSafeMemo(() => { if (!inputCurrency || !provider || !permitInfo) return undefined diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts index fb53e69be3..147db0402d 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts @@ -8,8 +8,11 @@ import { useWeb3React } from '@web3-react/core' import { Nullish } from 'types' +import { TradeType } from 'modules/trade' + import { useIsPermitEnabled } from 'common/hooks/featureFlags/useIsPermitEnabled' +import { ORDER_TYPE_SUPPORTS_PERMIT } from '../const' import { addPermitInfoForTokenAtom, permittableTokensAtom } from '../state/atoms' import { IsTokenPermittableResult } from '../types' import { checkIsTokenPermittable } from '../utils/checkIsTokenPermittable' @@ -21,9 +24,11 @@ import { checkIsTokenPermittable } from '../utils/checkIsTokenPermittable' * When it is not, returned type is `false` * When it is unknown, returned type is `undefined` * - * @param token */ -export function useIsTokenPermittable(token: Nullish): IsTokenPermittableResult { +export function useIsTokenPermittable( + token: Nullish, + tradeType: Nullish +): IsTokenPermittableResult { const { chainId } = useWalletInfo() const { provider } = useWeb3React() @@ -31,7 +36,10 @@ export function useIsTokenPermittable(token: Nullish): IsTokenPermitta const isNative = token?.isNative const tokenName = token?.name || lowerCaseAddress || '' - const isPermitEnabled = useIsPermitEnabled(chainId) + // Avoid building permit info in the first place if order type is not supported + const isPermitSupported = !!tradeType && ORDER_TYPE_SUPPORTS_PERMIT[tradeType] + + const isPermitEnabled = useIsPermitEnabled(chainId) && isPermitSupported const addPermitInfo = useAddPermitInfo() const permitInfo = usePermitInfo(chainId, isPermitEnabled ? lowerCaseAddress : undefined) diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts index 0b4939f98b..e76de08d48 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapButtonContext.ts @@ -1,9 +1,9 @@ import { - useIsSmartContractWallet, useGnosisSafeInfo, + useIsBundlingSupported, + useIsSmartContractWallet, useWalletDetails, useWalletInfo, - useIsBundlingSupported, } from '@cowprotocol/wallet' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' @@ -23,7 +23,7 @@ import { useSwapConfirmManager } from 'modules/swap/hooks/useSwapConfirmManager' import { useSwapFlowContext } from 'modules/swap/hooks/useSwapFlowContext' import { SwapButtonsContext } from 'modules/swap/pure/SwapButtons' import useCurrencyBalance from 'modules/tokens/hooks/useCurrencyBalance' -import { useWrapNativeFlow } from 'modules/trade' +import { TradeType, useWrapNativeFlow } from 'modules/trade' import { useIsNativeIn } from 'modules/trade/hooks/useIsNativeInOrOut' import { useIsWrappedOut } from 'modules/trade/hooks/useIsWrappedInOrOut' import { useWrappedToken } from 'modules/trade/hooks/useWrappedToken' @@ -92,7 +92,7 @@ export function useSwapButtonContext(input: SwapButtonInput): SwapButtonsContext const isSwapUnsupported = useIsTradeUnsupported(currencyIn, currencyOut) const isSmartContractWallet = useIsSmartContractWallet() const isBundlingSupported = useIsBundlingSupported() - const isPermitSupported = !!useIsTokenPermittable(currencyIn) + const isPermitSupported = !!useIsTokenPermittable(currencyIn, TradeType.SWAP) const swapButtonState = getSwapButtonState({ account, diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts index 7c88f9d00b..85003357ad 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts @@ -1,18 +1,19 @@ import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' import { useGP2SettlementContract } from '@cowprotocol/common-hooks' import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' -import { TradeType } from '@uniswap/sdk-core' +import { TradeType as UniTradeType } from '@uniswap/sdk-core' import { useIsTokenPermittable } from 'modules/permit' import { FlowType, getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext' import { SwapFlowContext } from 'modules/swap/services/types' import { useEnoughBalanceAndAllowance } from 'modules/tokens' +import { TradeType } from 'modules/trade' export function useSwapFlowContext(): SwapFlowContext | null { const contract = useGP2SettlementContract() const baseProps = useBaseFlowContextSetup() const sellCurrency = baseProps.trade?.inputAmount?.currency - const permitInfo = useIsTokenPermittable(sellCurrency) + const permitInfo = useIsTokenPermittable(sellCurrency, TradeType.SWAP) const checkAllowanceAddress = GP_VAULT_RELAYER[baseProps.chainId || SupportedChainId.MAINNET] const { enoughAllowance: hasEnoughAllowance } = useEnoughBalanceAndAllowance({ @@ -26,7 +27,7 @@ export function useSwapFlowContext(): SwapFlowContext | null { const baseContext = getFlowContext({ baseProps, sellToken: baseProps.trade.inputAmount.currency.wrapped, - kind: baseProps.trade.tradeType === TradeType.EXACT_INPUT ? OrderKind.SELL : OrderKind.BUY, + kind: baseProps.trade.tradeType === UniTradeType.EXACT_INPUT ? OrderKind.SELL : OrderKind.BUY, }) if (!contract || !baseContext || baseProps.flowType !== FlowType.REGULAR) return null diff --git a/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts b/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts index d8adf46643..51e0f63f12 100644 --- a/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts +++ b/apps/cowswap-frontend/src/modules/swap/state/useSwapDerivedState.ts @@ -5,6 +5,7 @@ import { OrderKind } from '@cowprotocol/cow-sdk' import { Field } from 'legacy/state/types' +import { TradeType } from 'modules/trade' import { useTradeUsdAmounts } from 'modules/usdAmount' import { useSafeMemoObject } from 'common/hooks/useSafeMemo' @@ -49,6 +50,7 @@ export function useFillSwapDerivedState() { recipient, recipientAddress, orderKind: isSellTrade ? OrderKind.SELL : OrderKind.BUY, + tradeType: TradeType.SWAP, }) useEffect(() => { diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useDerivedTradeState.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useDerivedTradeState.ts index 22e48f7710..5781562082 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useDerivedTradeState.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useDerivedTradeState.ts @@ -18,19 +18,13 @@ export function useDerivedTradeState(): { state?: TradeDerivedState } { if (!tradeTypeInfo) return {} if (tradeTypeInfo.tradeType === TradeType.SWAP) { - return { - state: swapDerivedState, - } + return { state: swapDerivedState } } if (tradeTypeInfo.tradeType === TradeType.ADVANCED_ORDERS) { - return { - state: advancedOrdersDerivedState, - } + return { state: advancedOrdersDerivedState } } - return { - state: limitOrdersDerivedState, - } + return { state: limitOrdersDerivedState } }, [tradeTypeInfo, swapDerivedState, limitOrdersDerivedState, advancedOrdersDerivedState]) } diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useTradeTypeInfo.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useTradeTypeInfo.ts index 57a971ba4d..46de0eac16 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useTradeTypeInfo.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useTradeTypeInfo.ts @@ -6,9 +6,9 @@ import { useMatch } from 'react-router-dom' import { Routes, RoutesValues, TRADE_WIDGET_PREFIX } from 'common/constants/routes' export enum TradeType { - SWAP, - LIMIT_ORDER, - ADVANCED_ORDERS, + SWAP = 'SWAP', + LIMIT_ORDER = 'LIMIT_ORDER', + ADVANCED_ORDERS = 'ADVANCED_ORDERS', } export interface TradeTypeInfo { diff --git a/apps/cowswap-frontend/src/modules/trade/types/TradeDerivedState.ts b/apps/cowswap-frontend/src/modules/trade/types/TradeDerivedState.ts index abf2be3627..aa80b975e7 100644 --- a/apps/cowswap-frontend/src/modules/trade/types/TradeDerivedState.ts +++ b/apps/cowswap-frontend/src/modules/trade/types/TradeDerivedState.ts @@ -1,6 +1,8 @@ import { OrderKind } from '@cowprotocol/cow-sdk' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' +import { TradeType } from '../hooks/useTradeTypeInfo' + export interface TradeDerivedState { readonly inputCurrency: Currency | null readonly outputCurrency: Currency | null @@ -25,6 +27,7 @@ export interface TradeDerivedState { readonly recipient: string | null readonly recipientAddress: string | null readonly orderKind: OrderKind + readonly tradeType: TradeType | null } export const DEFAULT_TRADE_DERIVED_STATE: TradeDerivedState = { @@ -40,4 +43,5 @@ export const DEFAULT_TRADE_DERIVED_STATE: TradeDerivedState = { recipient: null, recipientAddress: null, orderKind: OrderKind.SELL, + tradeType: null, } diff --git a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts index f60e9adb3b..1c1d9ce845 100644 --- a/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts +++ b/apps/cowswap-frontend/src/modules/tradeFormValidation/hooks/useTradeFormValidationContext.ts @@ -20,7 +20,7 @@ export function useTradeFormValidationContext(): TradeFormValidationCommonContex const { state: derivedTradeState } = useDerivedTradeState() const tradeQuote = useTradeQuote() - const { inputCurrency, outputCurrency, slippageAdjustedSellAmount, recipient } = derivedTradeState || {} + const { inputCurrency, outputCurrency, slippageAdjustedSellAmount, recipient, tradeType } = derivedTradeState || {} const approvalState = useTradeApproveState(slippageAdjustedSellAmount) const { address: recipientEnsAddress } = useENSAddress(recipient) const isSwapUnsupported = @@ -33,7 +33,7 @@ export function useTradeFormValidationContext(): TradeFormValidationCommonContex const isSafeReadonlyUser = gnosisSafeInfo?.isReadOnly || false - const isPermitSupported = !!useIsTokenPermittable(inputCurrency) + const isPermitSupported = !!useIsTokenPermittable(inputCurrency, tradeType) const commonContext = { account, diff --git a/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts b/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts index 7ee4b6c52f..950ee1da98 100644 --- a/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts +++ b/apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.test.ts @@ -1,5 +1,4 @@ -import { COW } from '@cowprotocol/common-const' -import { WETH_GOERLI } from '@cowprotocol/common-const' +import { COW, WETH_GOERLI } from '@cowprotocol/common-const' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { CurrencyAmount } from '@uniswap/sdk-core' @@ -12,6 +11,8 @@ import { TwapOrderCreationContext } from '../hooks/useTwapOrderCreationContext' import { TWAPOrder } from '../types' import { buildTwapOrderParamsStruct } from '../utils/buildTwapOrderParamsStruct' +jest.mock('modules/permit') + const APP_DATA_HASH = getAppData().appDataKeccak256 const chainId = SupportedChainId.GOERLI From 0b66ae710adee574e0f80bb542c99ee08ec6098c Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Thu, 28 Sep 2023 21:13:30 +0600 Subject: [PATCH 22/36] refactor: removed unused code (#3157) --- .../src/legacy/state/lists/hooks.ts | 50 ++++++------------- libs/common-const/src/lists.ts | 2 - libs/common-utils/src/index.ts | 1 - libs/common-utils/src/listSort.ts | 14 ------ 4 files changed, 16 insertions(+), 51 deletions(-) delete mode 100644 libs/common-utils/src/listSort.ts diff --git a/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts b/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts index 6a5a1d0565..c9f96e4f02 100644 --- a/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts +++ b/apps/cowswap-frontend/src/legacy/state/lists/hooks.ts @@ -1,7 +1,6 @@ import { useCallback, useMemo } from 'react' import { UNSUPPORTED_LIST_URLS } from '@cowprotocol/common-const' -import { sortByListPriority } from '@cowprotocol/common-utils' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { useWalletInfo } from '@cowprotocol/wallet' import DEFAULT_TOKEN_LIST from '@uniswap/default-token-list' @@ -72,32 +71,19 @@ export function useCombinedTokenMapFromUrls(urls: string[] | undefined): TokenAd const lists = useAllLists() return useMemo(() => { if (!urls) return {} - return ( - urls - .slice() - // sort by priority so top priority goes last - .sort(sortByListPriority) - .reduce((allTokens, currentUrl) => { - const current = lists[currentUrl]?.current - if (!current) return allTokens - try { - return combineMaps(allTokens, tokensToChainTokenMap(current)) - } catch (error: any) { - console.error('Could not show token list due to error', error) - return allTokens - } - }, {}) - ) + return urls.slice().reduce((allTokens, currentUrl) => { + const current = lists[currentUrl]?.current + if (!current) return allTokens + try { + return combineMaps(allTokens, tokensToChainTokenMap(current)) + } catch (error: any) { + console.error('Could not show token list due to error', error) + return allTokens + } + }, {}) }, [lists, urls]) } -// get all the tokens from active lists, combine with local default tokens -export function useCombinedActiveList(): TokenAddressMap { - const activeListUrls = useActiveListUrls() - const activeTokens = useCombinedTokenMapFromUrls(activeListUrls) - return activeTokens -} - // list of tokens not supported on interface for various reasons, used to show warnings and prevent swaps and adds export function useUnsupportedTokenList(): TokenAddressMap { return useCombinedTokenMapFromUrls(UNSUPPORTED_LIST_URLS[1]) @@ -109,16 +95,12 @@ export function useTokensListFromUrls(urls: string[] | undefined): TokenInfo[] { return useMemo(() => { if (!urls) return [] - return ( - urls - .slice() - // sort by priority so top priority goes last - .sort(sortByListPriority) - .map((url) => { - return lists?.[url]?.current?.tokens || [] - }) - .flat() - ) + return urls + .slice() + .map((url) => { + return lists?.[url]?.current?.tokens || [] + }) + .flat() }, [lists, urls]) } diff --git a/libs/common-const/src/lists.ts b/libs/common-const/src/lists.ts index 9d26dc1b78..7c57d026eb 100644 --- a/libs/common-const/src/lists.ts +++ b/libs/common-const/src/lists.ts @@ -78,5 +78,3 @@ export const DEFAULT_ACTIVE_LIST_URLS_BY_NETWORK: NetworkLists = { // Set what we want as the default list when no chain id available: default = MAINNET export const DEFAULT_NETWORK_FOR_LISTS = ChainId.MAINNET - -export const DEFAULT_LIST_OF_LISTS: string[] = [] diff --git a/libs/common-utils/src/index.ts b/libs/common-utils/src/index.ts index 70de2e928a..411a4ccc8b 100644 --- a/libs/common-utils/src/index.ts +++ b/libs/common-utils/src/index.ts @@ -32,7 +32,6 @@ export * from './isFractionFalsy' export * from './getAddress' export * from './tooltips' export * from './genericPropsChecker' -export * from './listSort' export * from './sound' export * from './userAgent' export * from './getExplorerLink' diff --git a/libs/common-utils/src/listSort.ts b/libs/common-utils/src/listSort.ts deleted file mode 100644 index 1c97484f5c..0000000000 --- a/libs/common-utils/src/listSort.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DEFAULT_LIST_OF_LISTS } from '@cowprotocol/common-const' - -const DEFAULT_LIST_PRIORITIES = DEFAULT_LIST_OF_LISTS.reduce<{ [listUrl: string]: number }>((memo, listUrl, index) => { - memo[listUrl] = index + 1 - return memo -}, {}) - -// use ordering of default list of lists to assign priority -export function sortByListPriority(urlA: string, urlB: string) { - if (DEFAULT_LIST_PRIORITIES[urlA] && DEFAULT_LIST_PRIORITIES[urlB]) { - return DEFAULT_LIST_PRIORITIES[urlA] - DEFAULT_LIST_PRIORITIES[urlB] - } - return 0 -} From d5b69cd4716d1a77e94a4ecba808186e96ef4794 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Sat, 30 Sep 2023 19:56:47 +0600 Subject: [PATCH 23/36] feat(tokens): new UI component for token select modal (#3166) * feat: skeleton for SelectTokenModal * chore: setup SelectTokenModal cosmos * chore: styles SelectTokenModal * chore: select token modal styles --- .../src/legacy/components/InfoIcon/index.tsx | 37 +++++--- .../orders/hooks/useTokensForOrdersList.ts | 3 +- .../SelectTokenModal/index.cosmos.tsx | 39 ++++++++ .../containers/SelectTokenModal/index.tsx | 45 +++++++++ .../containers/SelectTokenModal/mocks.ts | 77 ++++++++++++++++ .../containers/SelectTokenModal/styled.ts | 92 +++++++++++++++++++ .../tokensList/pure/AllTokensList/index.tsx | 39 ++++++++ .../tokensList/pure/AllTokensList/styled.ts | 55 +++++++++++ .../pure/FavouriteTokensList/index.tsx | 37 ++++++++ .../pure/FavouriteTokensList/styled.ts | 53 +++++++++++ .../tokensList/state/tokensListAtom.ts | 17 +--- .../src/modules/tokensList/types.ts | 15 +++ .../tokensList/updaters/TokensListUpdater.ts | 4 +- 13 files changed, 482 insertions(+), 31 deletions(-) create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/mocks.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/types.ts diff --git a/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx b/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx index eaae70599b..39a7acc21e 100644 --- a/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/InfoIcon/index.tsx @@ -2,20 +2,24 @@ import { ReactNode } from 'react' import { MouseoverTooltipContent, TooltipContainer } from '@cowprotocol/ui' -import { Info } from 'react-feather' +import { Info, HelpCircle } from 'react-feather' import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' -const StyledInfoIcon = styled(Info)` - opacity: 0.5; - stroke: var(${UI.COLOR_TEXT1}); - line-height: 0; - vertical-align: middle; - transition: opacity 0.2s ease-in-out; +const StyledIcon = styled.div` + display: inline-block; - :hover { - opacity: 1; + > svg { + opacity: 0.5; + stroke: var(${UI.COLOR_TEXT1}); + line-height: 0; + vertical-align: middle; + transition: opacity 0.2s ease-in-out; + + :hover { + opacity: 1; + } } ` @@ -28,15 +32,22 @@ const StyledTooltipContainer = styled(TooltipContainer)` export interface InfoIconProps { content: ReactNode + iconType?: 'info' | 'help' className?: string } -export function InfoIcon(props: InfoIconProps) { - const content = {props.content} +export function InfoIcon({ content, iconType = 'info', className }: InfoIconProps) { + const tooltipContent = {content} return ( - - + + + {iconType === 'info' ? ( + + ) : ( + + )} + ) } diff --git a/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts b/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts index 0d04ef6ea3..5d1174e575 100644 --- a/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts +++ b/apps/cowswap-frontend/src/modules/orders/hooks/useTokensForOrdersList.ts @@ -6,7 +6,8 @@ import { Token } from '@uniswap/sdk-core' import { useAllTokens } from 'legacy/hooks/Tokens' import { useTokenLazy } from 'legacy/hooks/useTokenLazy' -import { TokensByAddress, TokenWithLogo } from 'modules/tokensList/state/tokensListAtom' +import { TokensByAddress } from 'modules/tokensList/state/tokensListAtom' +import { TokenWithLogo } from 'modules/tokensList/types' import { getTokenFromMapping } from 'utils/orderUtils/getTokenFromMapping' diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx new file mode 100644 index 0000000000..51e25e3a7a --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx @@ -0,0 +1,39 @@ +import { getRandomInt } from '@cowprotocol/common-utils' +import { CurrencyAmount } from '@uniswap/sdk-core' +import { Currency } from '@uniswap/sdk-core' + +import styled from 'styled-components/macro' + +import { allTokensMock, favouriteTokensMock } from './mocks' + +import { SelectTokenModal } from './index' + +const Wrapper = styled.div` + width: 450px; +` + +const selectedToken = favouriteTokensMock[0] + +const balances = allTokensMock.reduce<{ [key: string]: CurrencyAmount }>((acc, token) => { + acc[token.address.toLowerCase()] = CurrencyAmount.fromRawAmount( + token, + getRandomInt(20_000, 120_000_000) * 10 ** token.decimals + ) + + return acc +}, {}) + +const Fixtures = { + default: ( + + + + ), +} + +export default Fixtures diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx new file mode 100644 index 0000000000..275adbbeba --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx @@ -0,0 +1,45 @@ +import { Currency, CurrencyAmount } from '@uniswap/sdk-core' + +import { Edit, X } from 'react-feather' + +import * as styledEl from './styled' + +import { AllTokensList } from '../../pure/AllTokensList' +import { FavouriteTokensList } from '../../pure/FavouriteTokensList' +import { TokenWithLogo } from '../../types' + +export interface SelectTokenModalProps { + allTokens: TokenWithLogo[] + favouriteTokens: TokenWithLogo[] + balances: { [key: string]: CurrencyAmount } + selectedToken?: TokenWithLogo +} + +export function SelectTokenModal(props: SelectTokenModalProps) { + const { favouriteTokens, allTokens, selectedToken, balances } = props + + return ( + + +

Select a token

+ +
+ + + + + + +
+ +
+
+ + Manage Token Lists + +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/mocks.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/mocks.ts new file mode 100644 index 0000000000..77ed5e8e8e --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/mocks.ts @@ -0,0 +1,77 @@ +import { TokenWithLogo } from '../../types' + +export const allTokensMock: TokenWithLogo[] = [ + { + name: 'Gnosis', + chainId: 5, + symbol: 'GNO', + decimals: 18, + address: '0x02abbdbaaa7b1bb64b5c878f7ac17f8dda169532', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png', + }, + { + name: 'Basic Attention Token', + chainId: 5, + symbol: 'BAT', + decimals: 18, + address: '0x70cBa46d2e933030E2f274AE58c951C800548AeF', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0D8775F648430679A709E98d2b0Cb6250d2887EF/logo.png', + }, + { + name: 'CoW Protocol Token', + chainId: 5, + symbol: 'COW', + decimals: 18, + address: '0x91056D4A53E1faa1A84306D4deAEc71085394bC8', + logoURI: 'https://gnosis.mypinata.cloud/ipfs/Qme9B6jRpGtZsRFcPjHvA5T4ugFuL4c3SzWfxyMPa59AMo', + }, + { + name: 'USD Coin', + chainId: 5, + symbol: 'USDC', + decimals: 6, + address: '0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + { + name: 'DAI', + chainId: 5, + symbol: 'DAI', + decimals: 18, + address: '0xdc31Ee1784292379Fbb2964b3B9C4124D8F89C60', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png', + }, + { + name: '0x', + chainId: 5, + symbol: 'ZRX', + decimals: 18, + address: '0xe4E81Fa6B16327D4B78CFEB83AAdE04bA7075165', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png', + }, +].map((item) => new TokenWithLogo(item.logoURI, item.chainId, item.address, item.decimals, item.symbol, item.name)) + +export const favouriteTokensMock: TokenWithLogo[] = [ + { + name: 'Basic Attention Token', + chainId: 5, + symbol: 'BAT', + decimals: 18, + address: '0x70cBa46d2e933030E2f274AE58c951C800548AeF', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0D8775F648430679A709E98d2b0Cb6250d2887EF/logo.png', + }, + { + name: 'Polymath Network', + chainId: 5, + symbol: 'POLY', + decimals: 18, + address: '0x9e32c0EfF886B6Ccae99350Fd5e7002dCED55F15', + logoURI: 'https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034', + }, +].map((item) => new TokenWithLogo(item.logoURI, item.chainId, item.address, item.decimals, item.symbol, item.name)) diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts new file mode 100644 index 0000000000..584cf6d591 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts @@ -0,0 +1,92 @@ +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +export const Wrapper = styled.div` + display: flex; + flex-direction: column; + background: var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: 20px; +` + +export const Row = styled.div` + margin: 0 20px 15px 20px; +` + +export const Header = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 20px 20px 0 20px; + margin-bottom: 15px; + + > h3 { + font-size: 16px; + font-weight: 500; + margin: 0; + } + + > button { + margin: 0; + padding: 0; + border: none; + outline: none; + background: none; + cursor: pointer; + opacity: 0.6; + transition: opacity 0.2s ease-in-out; + + > svg { + color: var(${UI.COLOR_TEXT1}); + } + + &:hover { + opacity: 1; + } + } +` + +export const SearchInput = styled.input` + width: 100%; + outline: none; + border-radius: 20px; + color: var(${UI.COLOR_TEXT1}); + padding: 16px; + border: 1px solid var(${UI.COLOR_GREY}); + -webkit-appearance: none; + transition: border 100ms; + background: transparent; + + font-size: 18px; + + ::placeholder { + color: var(${UI.COLOR_LINK}); + } + + :focus { + border: 1px solid var(${UI.COLOR_CONTAINER_BG_02}); + outline: none; + } +` + +export const ActionButton = styled.button` + display: flex; + width: 100%; + align-items: center; + flex-direction: row; + justify-content: center; + gap: 10px; + cursor: pointer; + padding: 20px 0; + margin: 0; + font-size: 16px; + font-weight: 500; + color: var(${UI.COLOR_TEXT1}); + background: none; + border: 0; + outline: none; + + &:hover { + opacity: 0.7; + } +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx new file mode 100644 index 0000000000..8e5e1ba4c3 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx @@ -0,0 +1,39 @@ +import { TokenAmount, TokenSymbol } from '@cowprotocol/ui' +import { Currency, CurrencyAmount } from '@uniswap/sdk-core' + +import * as styledEl from './styled' + +import { TokenWithLogo } from '../../types' + +export interface AllTokensListProps { + tokens: TokenWithLogo[] + selectedToken?: TokenWithLogo + balances: { [key: string]: CurrencyAmount } +} + +export function AllTokensList(props: AllTokensListProps) { + const { tokens, selectedToken, balances } = props + + return ( + + {tokens.map((token) => { + const isTokenSelected = token.address.toLowerCase() === selectedToken?.address.toLowerCase() + + return ( + + + +
+ + {token.name} +
+
+ + + +
+ ) + })} +
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts new file mode 100644 index 0000000000..bb08a9d8b2 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts @@ -0,0 +1,55 @@ +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +export const Wrapper = styled.div` + border-top: 1px solid var(${UI.COLOR_BORDER}); + border-bottom: 1px solid var(${UI.COLOR_BORDER}); +` + +export const TokenItem = styled.button` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + width: 100%; + background: none; + border: 0; + outline: none; + color: var(${UI.COLOR_TEXT1}); + cursor: pointer; + font-size: 16px; + padding: 10px 20px; + margin-bottom: 10px; + opacity: ${({ disabled }) => (disabled ? 0.5 : 1)}; + + &:last-child { + margin-bottom: 0; + } + + &:hover { + background-color: ${({ disabled }) => !disabled && `var(${UI.COLOR_GREY})`}; + } +` + +export const TokenLogo = styled.img` + --size: 36px; + width: var(--size); + height: var(--size); + border-radius: 50%; + background: var(${UI.COLOR_LIGHT_BLUE}); +` + +export const TokenInfo = styled.div` + display: flex; + flex-direction: row; + text-align: left; + gap: 16px; + font-weight: 500; +` + +export const TokenName = styled.div` + font-size: 12px; + font-weight: 400; + color: var(${UI.COLOR_TEXT2}); +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/index.tsx new file mode 100644 index 0000000000..cecb000792 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/index.tsx @@ -0,0 +1,37 @@ +import { TokenSymbol } from '@cowprotocol/ui' + +import { InfoIcon } from 'legacy/components/InfoIcon' + +import * as styledEl from './styled' + +import { TokenWithLogo } from '../../types' + +export interface FavouriteTokensListProps { + tokens: TokenWithLogo[] + selectedToken?: TokenWithLogo +} + +export function FavouriteTokensList(props: FavouriteTokensListProps) { + const { tokens, selectedToken } = props + + return ( +
+ +

Favourite tokens

+ +
+ + {tokens.map((token) => { + const isTokenSelected = token.address.toLowerCase() === selectedToken?.address.toLowerCase() + + return ( + + {token.name} + + + ) + })} + +
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/styled.ts new file mode 100644 index 0000000000..614464bcf1 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/FavouriteTokensList/styled.ts @@ -0,0 +1,53 @@ +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +export const Header = styled.div` + display: flex; + gap: 5px; + flex-direction: row; + align-items: center; + + > h4 { + font-size: 14px; + font-weight: 500; + margin: 0; + } +` + +export const TokensList = styled.div` + margin: 10px 0; +` + +export const TokensItem = styled.button` + display: inline-flex; + flex-direction: row; + align-items: center; + gap: 6px; + justify-content: center; + min-width: 140px; + margin: 5px 5px 5px 0; + background: none; + outline: none; + padding: 6px 0; + border-radius: 10px; + color: var(${UI.COLOR_TEXT1}); + border: 1px solid var(${UI.COLOR_GREY}); + font-weight: 500; + font-size: 16px; + cursor: ${({ disabled }) => (disabled ? '' : 'pointer')}; + background-color: ${({ theme, disabled }) => disabled && theme.bg3}; + opacity: ${({ disabled }) => (disabled ? 0.5 : 1)}; + + :hover { + background-color: ${({ theme, disabled }) => !disabled && theme.bg4}; + } + + > img { + --size: 24px; + width: var(--size); + height: var(--size); + border-radius: 50%; + background: var(${UI.COLOR_LIGHT_BLUE}); + } +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/state/tokensListAtom.ts b/apps/cowswap-frontend/src/modules/tokensList/state/tokensListAtom.ts index 0abca1bf79..39d2add888 100644 --- a/apps/cowswap-frontend/src/modules/tokensList/state/tokensListAtom.ts +++ b/apps/cowswap-frontend/src/modules/tokensList/state/tokensListAtom.ts @@ -1,21 +1,6 @@ import { atom } from 'jotai' -import { Token } from '@uniswap/sdk-core' - -// It's a hack for useCurrencyLogoURIs(), must be refactored -export class TokenWithLogo extends Token { - constructor( - public logoURI: string | undefined, - chainId: number, - address: string, - decimals: number, - symbol?: string, - name?: string, - bypassChecksum?: boolean - ) { - super(chainId, address, decimals, symbol, name, bypassChecksum) - } -} +import { TokenWithLogo } from '../types' export type TokensByAddress = { [address: string]: TokenWithLogo } diff --git a/apps/cowswap-frontend/src/modules/tokensList/types.ts b/apps/cowswap-frontend/src/modules/tokensList/types.ts new file mode 100644 index 0000000000..0b9cf90087 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/types.ts @@ -0,0 +1,15 @@ +import { Token } from '@uniswap/sdk-core' + +export class TokenWithLogo extends Token { + constructor( + public logoURI: string | undefined, + chainId: number, + address: string, + decimals: number, + symbol?: string, + name?: string, + bypassChecksum?: boolean + ) { + super(chainId, address, decimals, symbol, name, bypassChecksum) + } +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/updaters/TokensListUpdater.ts b/apps/cowswap-frontend/src/modules/tokensList/updaters/TokensListUpdater.ts index d9708e316e..2f6aa18f98 100644 --- a/apps/cowswap-frontend/src/modules/tokensList/updaters/TokensListUpdater.ts +++ b/apps/cowswap-frontend/src/modules/tokensList/updaters/TokensListUpdater.ts @@ -3,7 +3,9 @@ import { useEffect, useMemo } from 'react' import { useTokensListWithDefaults } from 'legacy/state/lists/hooks' -import { tokensByAddressAtom, tokensBySymbolAtom, TokenWithLogo } from 'modules/tokensList/state/tokensListAtom' +import { tokensByAddressAtom, tokensBySymbolAtom } from 'modules/tokensList/state/tokensListAtom' + +import { TokenWithLogo } from '../types' /** * This updater protects from redundant recalculations From 4b3fbc0f6de2f89235cc69fdc6e7eaefb9bd12b6 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Mon, 2 Oct 2023 11:24:12 +0600 Subject: [PATCH 24/36] feat: remove walletConnect v1 and use v2 by default (#3156) * feat: remove walletConnect v1 and use v2 by default * chore: walletconnect icon * chore: remove tooltip --- .../src/common/hooks/useZeroApprove.ts | 4 +- .../containers/ConnectWalletOptions.tsx | 6 +- .../wallet/containers/WalletModal/index.tsx | 17 +--- .../modules/wallet/pure/StatusIcon/index.tsx | 2 +- libs/wallet/src/api/types.ts | 3 +- libs/wallet/src/api/utils/connection.ts | 2 - libs/wallet/src/index.ts | 3 +- .../web3-react/connection/walletConnect.tsx | 97 ------------------- .../web3-react/connection/walletConnectV2.tsx | 5 +- .../WalletConnectLabeledOption/index.tsx | 5 +- .../web3-react/hooks/useIsWalletConnect.ts | 2 +- .../src/web3-react/hooks/useWalletMetadata.ts | 2 +- .../utils/getWeb3ReactConnection.ts | 8 +- .../src/web3-react/utils/isChainAllowed.ts | 1 - 14 files changed, 14 insertions(+), 143 deletions(-) delete mode 100644 libs/wallet/src/web3-react/connection/walletConnect.tsx diff --git a/apps/cowswap-frontend/src/common/hooks/useZeroApprove.ts b/apps/cowswap-frontend/src/common/hooks/useZeroApprove.ts index 48ccc0ece2..eb52d63f07 100644 --- a/apps/cowswap-frontend/src/common/hooks/useZeroApprove.ts +++ b/apps/cowswap-frontend/src/common/hooks/useZeroApprove.ts @@ -1,7 +1,7 @@ import { useSetAtom } from 'jotai' import { useCallback } from 'react' -import { useIsSafeWallet, walletConnectConnection } from '@cowprotocol/wallet' +import { useIsSafeWallet, walletConnectConnectionV2 } from '@cowprotocol/wallet' import SafeApiKit from '@safe-global/api-kit' import { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' @@ -44,7 +44,7 @@ export function useZeroApprove(currency: Currency) { const amountToApprove = CurrencyAmount.fromRawAmount(currency, 0) const approveCallback = useApproveCallback(amountToApprove, spender) const safeApiKit = useSafeApiKit() - const isWalletConnect = useIsActiveWallet(walletConnectConnection) + const isWalletConnect = useIsActiveWallet(walletConnectConnectionV2) const isSafeWallet = useIsSafeWallet() return useCallback(async () => { diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx index 40f225c6a5..72218b1556 100644 --- a/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsx @@ -13,7 +13,6 @@ import { LedgerOption, TrezorOption, TrustWalletOption, - WalletConnectOption, WalletConnectV2Option, getIsCoinbaseWallet, getIsInjected, @@ -62,8 +61,6 @@ export function ConnectWalletOptions({ tryActivation }: { tryActivation: TryActi const coinbaseWalletOption = - const walletConnectionOption = (!isInjectedMobileBrowser && ) ?? null - const walletConnectionV2Option = (!isInjectedMobileBrowser && ) ?? null // Wallet-connect based @@ -82,8 +79,7 @@ export function ConnectWalletOptions({ tryActivation }: { tryActivation: TryActi return ( <> {injectedOption} - {walletConnectionOption} - {walletConnectionV2Option} + {walletConnectionV2Option} {coinbaseWalletOption} {ledgerOption} {trezorOption} diff --git a/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx b/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx index 93dc61ddfe..daef27f9be 100644 --- a/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/containers/WalletModal/index.tsx @@ -4,7 +4,7 @@ import { useCallback, useEffect, useState } from 'react' import { changeWalletAnalytics } from '@cowprotocol/analytics' import { usePrevious } from '@cowprotocol/common-hooks' import { getCurrentChainIdFromUrl } from '@cowprotocol/common-utils' -import { useWalletInfo, ConnectionType, getIsHardWareWallet, getWeb3ReactConnection } from '@cowprotocol/wallet' +import { useWalletInfo, getIsHardWareWallet, getWeb3ReactConnection } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' import { Connector } from '@web3-react/types' @@ -90,21 +90,6 @@ export function WalletModal() { await connector.activate(getCurrentChainIdFromUrl()) - const connection = getWeb3ReactConnection(connector) - - // Important for balances to load when connected to Gnosis-chain via WalletConnect - if (connection.type === ConnectionType.WALLET_CONNECT) { - const provider: any = connector.provider - - if (provider && provider.isWalletConnect) { - const { http, rpc, signer } = (connector as any).provider - const chainId = signer.connection.chainId - // don't default to SupportedChainId.Mainnet - throw instead - if (!chainId) throw new Error('[WalletModal::activation error: No chainId') - http.connection.url = rpc.custom[chainId] - } - } - dispatch(updateSelectedWallet({ wallet: connectionType })) if (isHardWareWallet) { diff --git a/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx index 6b37269109..8c9a9910ae 100644 --- a/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx +++ b/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx @@ -28,7 +28,7 @@ export function StatusIcon({ connectionType }: StatusIconProps) { case ConnectionType.INJECTED: image = break - case ConnectionType.WALLET_CONNECT: + case ConnectionType.WALLET_CONNECT_V2: image = WalletConnect break case ConnectionType.COINBASE_WALLET: diff --git a/libs/wallet/src/api/types.ts b/libs/wallet/src/api/types.ts index 191afa122f..1eef0f0315 100644 --- a/libs/wallet/src/api/types.ts +++ b/libs/wallet/src/api/types.ts @@ -5,7 +5,6 @@ export enum ConnectionType { INJECTED = 'INJECTED', INJECTED_WIDGET = 'INJECTED_WIDGET', COINBASE_WALLET = 'COINBASE_WALLET', - WALLET_CONNECT = 'WALLET_CONNECT', WALLET_CONNECT_V2 = 'WALLET_CONNECT_V2', NETWORK = 'NETWORK', GNOSIS_SAFE = 'GNOSIS_SAFE', @@ -19,7 +18,7 @@ export enum ConnectionType { TREZOR = 'TREZOR', } -export const BACKFILLABLE_WALLETS = [ConnectionType.INJECTED, ConnectionType.WALLET_CONNECT] +export const BACKFILLABLE_WALLETS = [ConnectionType.INJECTED] export interface WalletInfo { chainId: SupportedChainId diff --git a/libs/wallet/src/api/utils/connection.ts b/libs/wallet/src/api/utils/connection.ts index 0c67be1adc..8d7543726f 100644 --- a/libs/wallet/src/api/utils/connection.ts +++ b/libs/wallet/src/api/utils/connection.ts @@ -11,7 +11,6 @@ const connectionTypeToName: Record = { [ConnectionType.INJECTED]: 'injected', [ConnectionType.INJECTED_WIDGET]: 'CowSwap widget', [ConnectionType.COINBASE_WALLET]: 'Coinbase Wallet', - [ConnectionType.WALLET_CONNECT]: 'WalletConnect', [ConnectionType.WALLET_CONNECT_V2]: 'WalletConnect v2', [ConnectionType.NETWORK]: 'Network', [ConnectionType.GNOSIS_SAFE]: 'Safe', @@ -41,7 +40,6 @@ const connectionTypeToIcon: Record = { [ConnectionType.LEDGER]: LedgerIcon, [ConnectionType.TREZOR]: TrezorIcon, [ConnectionType.KEYSTONE]: KeystoneImage, - [ConnectionType.WALLET_CONNECT]: WalletConnectIcon, [ConnectionType.WALLET_CONNECT_V2]: WalletConnectIcon, } diff --git a/libs/wallet/src/index.ts b/libs/wallet/src/index.ts index a7c359114e..119ff2def4 100644 --- a/libs/wallet/src/index.ts +++ b/libs/wallet/src/index.ts @@ -43,7 +43,6 @@ export { InstallKeystoneOption, KeystoneOption } from './web3-react/connection/k export { LedgerOption } from './web3-react/connection/ledger' export { TrezorOption } from './web3-react/connection/trezor' export { TrustWalletOption } from './web3-react/connection/trust' -export { WalletConnectOption } from './web3-react/connection/walletConnect' export { WalletConnectV2Option } from './web3-react/connection/walletConnectV2' export { AlphaOption } from './web3-react/connection/alpha' export { AmbireOption } from './web3-react/connection/ambire' @@ -56,4 +55,4 @@ export * from './api/state' // Connections export { injectedConnection } from './web3-react/connection/injected' -export { walletConnectConnection } from './web3-react/connection/walletConnect' +export { walletConnectConnectionV2 } from './web3-react/connection/walletConnectV2' diff --git a/libs/wallet/src/web3-react/connection/walletConnect.tsx b/libs/wallet/src/web3-react/connection/walletConnect.tsx deleted file mode 100644 index 1ae9ecc339..0000000000 --- a/libs/wallet/src/web3-react/connection/walletConnect.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { useMemo } from 'react' - -import { RPC_URLS } from '@cowprotocol/common-const' - -import { initializeConnector } from '@web3-react/core' -import { useFlags } from 'launchdarkly-react-client-sdk' - -import { default as WalletConnectImage } from '../../api/assets/walletConnectIcon.svg' - -import { AsyncConnector } from './asyncConnector' -import { ConnectionOptionProps, Web3ReactConnection } from '../types' -import { onError } from './onError' -import { ConnectionType } from '../../api/types' -import { useWalletMetaData } from '../hooks/useWalletMetadata' -import { - getConnectionName, - getIsAlphaWallet, - getIsAmbireWallet, - getIsTrustWallet, - getIsZengoWallet, -} from '../../api/utils/connection' -import { WC_DISABLED_TEXT } from '../../constants' -import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' -import { useIsActiveConnection } from '../hooks/useIsActiveConnection' - -const WC_SUNSET_LINK = - 'https://medium.com/walletconnect/weve-reset-the-clock-on-the-walletconnect-v1-0-shutdown-now-scheduled-for-june-28-2023-ead2d953b595' -const WC_SUNSET_TEXT = - 'The WalletConnect v1.0 protocol has been shut down on June 28, 2023 at 2pm (UTC). Click to read more.' - -export const walletConnectOption = { - color: '#4196FC', - icon: WalletConnectImage, - id: 'wallet-connect', -} - -const [web3WalletConnect, web3WalletConnectHooks] = initializeConnector( - (actions) => - new AsyncConnector( - () => - import('@web3-react/walletconnect').then( - (m) => - new m.WalletConnect({ - actions, - options: { - rpc: RPC_URLS, - qrcode: true, - bridge: process.env.REACT_APP_WALLET_CONNECT_V1_BRIDGE || 'https://safe-walletconnect.safe.global', - }, - onError, - }) - ), - actions, - onError - ) -) -export const walletConnectConnection: Web3ReactConnection = { - connector: web3WalletConnect, - hooks: web3WalletConnectHooks, - type: ConnectionType.WALLET_CONNECT, -} - -export function WalletConnectOption({ selectedWallet, tryActivation }: ConnectionOptionProps) { - const { walletName } = useWalletMetaData() - const { walletConnectV1Deprecated: isDeprecated } = useFlags() - - const isWalletConnect = useIsActiveConnection(selectedWallet, walletConnectConnection) - const isActive = - isWalletConnect && - !getIsZengoWallet(walletName) && - !getIsAmbireWallet(walletName) && - !getIsAlphaWallet(walletName) && - !getIsTrustWallet(walletName) - - const tooltipText = useMemo(() => { - if (isDeprecated) { - return WC_SUNSET_TEXT - } - - return !isActive && isWalletConnect ? WC_DISABLED_TEXT : null - }, [isActive, isWalletConnect, isDeprecated]) - - const link = isDeprecated ? WC_SUNSET_LINK : null - - return ( - (!isDeprecated ? tryActivation(walletConnectConnection.connector) : null)} - header={getConnectionName(ConnectionType.WALLET_CONNECT)} - /> - ) -} diff --git a/libs/wallet/src/web3-react/connection/walletConnectV2.tsx b/libs/wallet/src/web3-react/connection/walletConnectV2.tsx index 6d47b9a281..e83a3babb8 100644 --- a/libs/wallet/src/web3-react/connection/walletConnectV2.tsx +++ b/libs/wallet/src/web3-react/connection/walletConnectV2.tsx @@ -27,9 +27,6 @@ import { import { WC_DISABLED_TEXT } from '../../constants' import { ConnectWalletOption } from '../../api/pure/ConnectWalletOption' -const TOOLTIP_TEXT = - 'Currently in development and not widely adopted yet. If you are experiencing issues, contact your wallet provider.' - export const walletConnectV2Option = { color: '#4196FC', icon: WalletConnectV2Image, @@ -157,7 +154,7 @@ export function WalletConnectV2Option({ selectedWallet, tryActivation }: Connect !getIsAlphaWallet(walletName) && !getIsTrustWallet(walletName) - const tooltipText = !isActive && isWalletConnect ? WC_DISABLED_TEXT : TOOLTIP_TEXT + const tooltipText = !isActive && isWalletConnect ? WC_DISABLED_TEXT : undefined return ( = { [ConnectionType.INJECTED]: injectedConnection, [ConnectionType.COINBASE_WALLET]: coinbaseWalletConnection, - [ConnectionType.WALLET_CONNECT]: walletConnectConnection, [ConnectionType.WALLET_CONNECT_V2]: walletConnectConnectionV2, - [ConnectionType.ZENGO]: walletConnectConnection, + [ConnectionType.ZENGO]: walletConnectConnectionV2, [ConnectionType.NETWORK]: networkConnection, [ConnectionType.GNOSIS_SAFE]: gnosisSafeConnection, - [ConnectionType.AMBIRE]: walletConnectConnection, - [ConnectionType.ALPHA]: walletConnectConnection, + [ConnectionType.AMBIRE]: walletConnectConnectionV2, + [ConnectionType.ALPHA]: walletConnectConnectionV2, [ConnectionType.TALLY]: tallyWalletConnection, [ConnectionType.TRUST]: trustWalletConnection, [ConnectionType.LEDGER]: ledgerConnection, diff --git a/libs/wallet/src/web3-react/utils/isChainAllowed.ts b/libs/wallet/src/web3-react/utils/isChainAllowed.ts index 56abdae9ec..645ca8d4d3 100644 --- a/libs/wallet/src/web3-react/utils/isChainAllowed.ts +++ b/libs/wallet/src/web3-react/utils/isChainAllowed.ts @@ -9,7 +9,6 @@ const allowedChainsByWallet: Record = { [ConnectionType.INJECTED]: ALL_SUPPORTED_CHAIN_IDS, [ConnectionType.INJECTED_WIDGET]: ALL_SUPPORTED_CHAIN_IDS, [ConnectionType.COINBASE_WALLET]: ALL_SUPPORTED_CHAIN_IDS, - [ConnectionType.WALLET_CONNECT]: ALL_SUPPORTED_CHAIN_IDS, [ConnectionType.WALLET_CONNECT_V2]: ALL_SUPPORTED_CHAIN_IDS, [ConnectionType.NETWORK]: ALL_SUPPORTED_CHAIN_IDS, [ConnectionType.GNOSIS_SAFE]: ALL_SUPPORTED_CHAIN_IDS, From 6c2c2535a11707ad1cc30aa17bd003863d832faa Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Mon, 2 Oct 2023 11:42:09 +0600 Subject: [PATCH 25/36] feat(tokens): new UI for tokens management (#3174) * feat: skeleton for SelectTokenModal * chore: setup SelectTokenModal cosmos * chore: styles SelectTokenModal * chore: select token modal styles * feat: html of ManageListsAndTokens * chore: manage lists styles * chore: manage tokens styles * chore: import token from blockchain UI * chore: search tokens sources * chore: extract ModalHeader component * chore: component ImportTokenModal * chore: manage lists states * chore: component ImportListModal * chore: fix build --- .../ManageLists/ManageListsMod.tsx | 2 +- .../components/Settings/SettingsMod.tsx | 2 +- .../src/legacy/components/Toggle/index.tsx | 10 +- .../containers/ManageLists/index.cosmos.tsx | 32 +++++ .../containers/ManageLists/index.tsx | 56 ++++++++ .../containers/ManageLists/styled.ts | 16 +++ .../ManageListsAndTokens/index.cosmos.tsx | 19 +++ .../containers/ManageListsAndTokens/index.tsx | 44 ++++++ .../containers/ManageListsAndTokens/styled.ts | 37 +++++ .../containers/ManageTokens/index.tsx | 67 +++++++++ .../containers/ManageTokens/styled.ts | 54 ++++++++ .../SelectTokenModal/index.cosmos.tsx | 36 ++++- .../containers/SelectTokenModal/index.tsx | 118 ++++++++++++++-- .../SelectTokenModal/searchToken.ts | 55 ++++++++ .../containers/SelectTokenModal/styled.ts | 33 ++--- .../src/modules/tokensList/mocks.ts | 130 ++++++++++++++++++ .../tokensList/pure/AllTokensList/index.tsx | 11 +- .../tokensList/pure/AllTokensList/styled.ts | 22 --- .../pure/ImportListModal/index.cosmos.tsx | 24 ++++ .../tokensList/pure/ImportListModal/index.tsx | 65 +++++++++ .../tokensList/pure/ImportListModal/styled.ts | 50 +++++++ .../tokensList/pure/ImportTokenItem/index.tsx | 25 ++++ .../tokensList/pure/ImportTokenItem/styled.ts | 13 ++ .../pure/ImportTokenListItem/index.tsx | 23 ++++ .../pure/ImportTokenListItem/styled.ts | 9 ++ .../pure/ImportTokenModal/index.cosmos.tsx | 23 ++++ .../pure/ImportTokenModal/index.tsx | 51 +++++++ .../pure/ImportTokenModal/styled.ts | 56 ++++++++ .../pure/LoadedTokenListItem/index.tsx | 26 ++++ .../pure/LoadedTokenListItem/styled.ts | 17 +++ .../tokensList/pure/ModalHeader/index.tsx | 41 ++++++ .../tokensList/pure/TokenInfo/index.tsx | 25 ++++ .../tokensList/pure/TokenInfo/styled.ts | 17 +++ .../tokensList/pure/TokenListInfo/index.tsx | 30 ++++ .../tokensList/pure/TokenListInfo/styled.ts | 21 +++ .../tokensList/pure/TokenListItem/index.tsx | 53 +++++++ .../tokensList/pure/TokenListItem/styled.ts | 46 +++++++ .../tokensList/pure/TokenLogo/index.tsx | 38 +++++ .../pure/TokenSourceTitle/index.tsx | 45 ++++++ .../modules/tokensList/pure/commonElements.ts | 73 ++++++++++ .../src/modules/tokensList/types.ts | 10 ++ .../trade/pure/Settings/SettingsBox.tsx | 2 +- 42 files changed, 1452 insertions(+), 75 deletions(-) create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/searchToken.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/mocks.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/ModalHeader/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/TokenLogo/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx create mode 100644 apps/cowswap-frontend/src/modules/tokensList/pure/commonElements.ts diff --git a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx index 6a4abd745f..7f4cf67124 100644 --- a/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/SearchModal/ManageLists/ManageListsMod.tsx @@ -16,7 +16,7 @@ import Column, { AutoColumn } from 'legacy/components/Column' import ListLogo from 'legacy/components/ListLogo' import { CurrencyModalView } from 'legacy/components/SearchModal/CurrencySearchModal' import { PaddedColumn, SearchInput, Separator, SeparatorDark } from 'legacy/components/SearchModal/styleds' -import Toggle from 'legacy/components/Toggle' +import { Toggle } from 'legacy/components/Toggle' import { useFetchListCallback } from 'legacy/hooks/useFetchListCallback' import { useAppDispatch, useAppSelector } from 'legacy/state/hooks' import { useActiveListUrls, useAllLists, useIsListActive } from 'legacy/state/lists/hooks' diff --git a/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx b/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx index 7d20b49b10..76589bf0cb 100644 --- a/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Settings/SettingsMod.tsx @@ -15,7 +15,7 @@ import styled, { ThemeContext } from 'styled-components/macro' import { AutoColumn } from 'legacy/components/Column' import QuestionHelper from 'legacy/components/QuestionHelper' -import Toggle from 'legacy/components/Toggle' +import { Toggle } from 'legacy/components/Toggle' import TransactionSettings from 'legacy/components/TransactionSettings' import { useModalIsOpen, useToggleSettingsMenu } from 'legacy/state/application/hooks' import { ApplicationModal } from 'legacy/state/application/reducer' diff --git a/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx b/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx index 661c779e98..2b1a82c409 100644 --- a/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Toggle/index.tsx @@ -8,22 +8,22 @@ import { UI } from 'common/constants/theme' const turnOnToggle = keyframes` from { - margin-left: 0em; + margin-left: 0; margin-right: 2.2em; } to { margin-left: 2.2em; - margin-right: 0em; + margin-right: 0; } ` const turnOffToggle = keyframes` from { margin-left: 2.2em; - margin-right: 0em; + margin-right: 0; } to { - margin-left: 0em; + margin-left: 0; margin-right: 2.2em; } ` @@ -99,7 +99,7 @@ export interface ToggleProps extends WithClassName { isDisabled?: boolean // Mod } -export default function Toggle({ id, bgColor, isActive, toggle, className, isDisabled }: ToggleProps) { +export function Toggle({ id, bgColor, isActive, toggle, className, isDisabled }: ToggleProps) { const [isInitialToggleLoad, setIsInitialToggleLoad] = useState(true) const switchToggle = () => { diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.cosmos.tsx new file mode 100644 index 0000000000..b4b8802972 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.cosmos.tsx @@ -0,0 +1,32 @@ +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +import { importListsMock, listsMock } from '../../mocks' + +import { ManageLists } from './index' + +const Wrapper = styled.div` + width: 450px; + background: var(${UI.COLOR_CONTAINER_BG_01}); +` + +const Fixtures = { + default: ( + + + + ), + importList: ( + + + + ), + loadedLists: ( + + + + ), +} + +export default Fixtures diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.tsx new file mode 100644 index 0000000000..2aa322a3d6 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/index.tsx @@ -0,0 +1,56 @@ +import * as styledEl from './styled' + +import { PrimaryInput, PrimaryInputBox } from '../../pure/commonElements' +import { ImportTokenListItem } from '../../pure/ImportTokenListItem' +import { LoadedTokenListItem } from '../../pure/LoadedTokenListItem' +import { TokenListItem } from '../../pure/TokenListItem' +import { TokenList } from '../../types' + +export interface ManageListsProps { + lists: TokenList[] + loadedLists?: TokenList[] + listsToImport?: TokenList[] +} + +export function ManageLists(props: ManageListsProps) { + const { lists, loadedLists, listsToImport } = props + + const viewList = (id: string) => { + console.log('TODO viewList', id) + } + + const removeList = (id: string) => { + console.log('TODO removeList', id) + } + + const importList = (list: TokenList) => { + console.log('TODO importList', list.id) + } + + return ( + + + + + {!!loadedLists?.length && ( + + {loadedLists.map((list) => ( + + ))} + + )} + {!!listsToImport?.length && ( + + {listsToImport.map((list) => ( + + ))} + + )} + + {lists.map((list) => ( + + ))} + + + ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/styled.ts new file mode 100644 index 0000000000..f84c70adc6 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageLists/styled.ts @@ -0,0 +1,16 @@ +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +export const Wrapper = styled.div` + display: block; + width: 100%; +` + +export const ListsContainer = styled.div` + padding-bottom: 20px; +` + +export const ImportListsContainer = styled.div` + border-bottom: 1px solid var(${UI.COLOR_BORDER}); +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.cosmos.tsx new file mode 100644 index 0000000000..7df1d8115c --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.cosmos.tsx @@ -0,0 +1,19 @@ +import styled from 'styled-components/macro' + +import { customTokensMock, listsMock } from '../../mocks' + +import { ManageListsAndTokens } from './index' + +const Wrapper = styled.div` + width: 450px; +` + +const Fixtures = { + default: ( + + + + ), +} + +export default Fixtures diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.tsx new file mode 100644 index 0000000000..dc8d6234b7 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/index.tsx @@ -0,0 +1,44 @@ +import { useState } from 'react' + +import * as styledEl from './styled' + +import { ModalHeader } from '../../pure/ModalHeader' +import { TokenList, TokenWithLogo } from '../../types' +import { ManageLists } from '../ManageLists' +import { ManageTokens } from '../ManageTokens' + +export interface ManageListsAndTokensProps { + lists: TokenList[] + customTokens: TokenWithLogo[] +} + +export function ManageListsAndTokens(props: ManageListsAndTokensProps) { + const { lists, customTokens } = props + + const [currentTab, setCurrentTab] = useState<'tokens' | 'lists'>('lists') + + const onBack = () => { + console.log('TODO onBack') + } + + const onClose = () => { + console.log('TODO onClose') + } + + return ( + + + Manage + + + setCurrentTab('lists')}> + Lists + + setCurrentTab('tokens')}> + Tokens + + + {currentTab === 'lists' ? : } + + ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/styled.ts new file mode 100644 index 0000000000..bc39147ac1 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageListsAndTokens/styled.ts @@ -0,0 +1,37 @@ +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +import { blankButtonMixin } from '../../pure/commonElements' + +export const Wrapper = styled.div` + display: block; + width: 100%; + background: var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: 20px; +` + +export const TabsContainer = styled.div` + display: flex; + flex-direction: row; + flex-shrink: 0; + margin-top: 10px; + + > button { + width: 50%; + } +` + +export const Tab = styled.button<{ active$: boolean }>` + ${blankButtonMixin}; + + color: var(${UI.COLOR_TEXT1}); + opacity: ${({ active$ }) => (active$ ? 1 : 0.5)}; + padding: 10px; + font-size: 16px; + font-weight: 600; + + &:hover { + color: var(${UI.COLOR_TEXT2}); + } +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/index.tsx new file mode 100644 index 0000000000..c35b48b186 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/index.tsx @@ -0,0 +1,67 @@ +import { ExplorerDataType, getExplorerLink } from '@cowprotocol/common-utils' +import { TokenSymbol } from '@cowprotocol/ui' + +import { ExternalLink, Trash } from 'react-feather' + +import * as styledEl from './styled' + +import { PrimaryInput, PrimaryInputBox } from '../../pure/commonElements' +import { TokenLogo } from '../../pure/TokenLogo' +import { TokenWithLogo } from '../../types' + +export interface ManageTokensProps { + tokens: TokenWithLogo[] +} + +export function ManageTokens(props: ManageTokensProps) { + const { tokens } = props + + const clearAll = () => { + console.log('TODO clearAll') + } + + const removeToken = (token: TokenWithLogo) => { + console.log('TODO removeToken', token.symbol) + } + + return ( +
+ + + +
+ + {tokens.length} Custom Tokens + Clear all + +
+ {tokens.map((token) => { + return ( + + + + + +
+ removeToken(token)}> + + + + + + + +
+
+ ) + })} +
+ Tip: Custom tokens are stored locally in your browser +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/styled.ts new file mode 100644 index 0000000000..6586717106 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/ManageTokens/styled.ts @@ -0,0 +1,54 @@ +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +import { blankButtonMixin } from '../../pure/commonElements' + +const RowBox = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +` + +export const Header = styled(RowBox)` + padding: 20px; +` + +export const Title = styled.div` + font-weight: 600; + opacity: 0.65; +` + +export const LinkButton = styled.button` + ${blankButtonMixin}; + + font-size: 16px; + font-weight: 500; + color: var(${UI.COLOR_LINK}); + margin-left: 10px; + + &:hover { + opacity: 0.8; + } +` + +export const TokenItem = styled(RowBox)` + padding: 0 20px; + margin-bottom: 20px; +` + +export const TokenInfo = styled(RowBox)` + gap: 10px; + font-weight: 600; +` + +export const TipText = styled.div` + font-size: 13px; + font-weight: 500; + color: var(${UI.COLOR_LINK}); + text-align: center; + padding: 20px 0; + border-top: 1px solid var(${UI.COLOR_GREY}); + margin-top: 20px; +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx index 51e25e3a7a..651c415fb3 100644 --- a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.cosmos.tsx @@ -4,7 +4,7 @@ import { Currency } from '@uniswap/sdk-core' import styled from 'styled-components/macro' -import { allTokensMock, favouriteTokensMock } from './mocks' +import { allTokensMock, favouriteTokensMock } from '../../mocks' import { SelectTokenModal } from './index' @@ -23,15 +23,37 @@ const balances = allTokensMock.reduce<{ [key: string]: CurrencyAmount return acc }, {}) +const defaultProps = { + selectedToken, + balances, + allTokens: allTokensMock, + favouriteTokens: favouriteTokensMock, +} + const Fixtures = { default: ( - + + + ), + importByAddress: ( + + + + ), + NoTokenFound: ( + + + + ), + searchFromInactiveLists: ( + + + + ), + searchFromExternalSources: ( + + ), } diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx index 275adbbeba..92defb25f7 100644 --- a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/index.tsx @@ -1,40 +1,142 @@ +import { useEffect, useMemo, useState } from 'react' + +import { useDebounce, useNetworkName } from '@cowprotocol/common-hooks' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import { Edit, X } from 'react-feather' +import { searchToken, TokenSearchSource } from './searchToken' import * as styledEl from './styled' import { AllTokensList } from '../../pure/AllTokensList' +import { IconButton } from '../../pure/commonElements' import { FavouriteTokensList } from '../../pure/FavouriteTokensList' +import { ImportTokenItem } from '../../pure/ImportTokenItem' +import { TokenSourceTitle } from '../../pure/TokenSourceTitle' import { TokenWithLogo } from '../../types' - export interface SelectTokenModalProps { allTokens: TokenWithLogo[] favouriteTokens: TokenWithLogo[] balances: { [key: string]: CurrencyAmount } selectedToken?: TokenWithLogo + defaultInputValue?: string } export function SelectTokenModal(props: SelectTokenModalProps) { - const { favouriteTokens, allTokens, selectedToken, balances } = props + const { defaultInputValue = '', favouriteTokens, allTokens, selectedToken, balances } = props + + const networkName = useNetworkName() + + const [isSearchInProgress, setIsSearchInProgress] = useState(false) + const [inputValue, setInputValue] = useState(defaultInputValue) + const debouncedInputValue = useDebounce(inputValue, 500) + + const [tokensFromBlockChain, setTokensFromBlockChain] = useState([]) + const [tokensFromInactiveLists, setTokensFromInactiveLists] = useState([]) + const [tokensFromExternal, setTokensFromExternal] = useState([]) + + const importToken = (token: TokenWithLogo) => { + console.log('TODO: import token', token) + } + + const isTokenNotFound = useMemo(() => { + if (isSearchInProgress || !debouncedInputValue) return false + + return tokensFromExternal.length === 0 && tokensFromBlockChain.length === 0 && tokensFromInactiveLists.length === 0 + }, [debouncedInputValue, isSearchInProgress, tokensFromBlockChain, tokensFromInactiveLists, tokensFromExternal]) + + useEffect(() => { + if (!debouncedInputValue) return + + setIsSearchInProgress(true) + setTokensFromBlockChain([]) + setTokensFromInactiveLists([]) + setTokensFromExternal([]) + + searchToken(debouncedInputValue) + .then((result) => { + if (!result) { + return + } + + const { source, tokens } = result + + if (source === TokenSearchSource.Blockchain) { + setTokensFromBlockChain(tokens) + return + } + if (source === TokenSearchSource.InactiveList) { + setTokensFromInactiveLists(tokens) + return + } + if (source === TokenSearchSource.External) { + setTokensFromExternal(tokens) + return + } + }) + .finally(() => { + setIsSearchInProgress(false) + }) + }, [debouncedInputValue]) return (

Select a token

- +
- + setInputValue(e.target.value)} + type="text" + placeholder="Search name or past address" + /> -
- -
+ {isTokenNotFound && ( + No tokens found for this name in {networkName} + )} + {tokensFromBlockChain.length > 0 && ( +
+ {tokensFromBlockChain.map((token) => { + return + })} +
+ )} + {tokensFromInactiveLists.length > 0 && ( +
+ + Expanded results from inactive Token Lists + +
+ {tokensFromInactiveLists.map((token) => { + return + })} +
+
+ )} + {tokensFromExternal.length > 0 && ( +
+ + Additional Results from External Sources + +
+ {tokensFromExternal.map((token) => { + return + })} +
+
+ )} + {!debouncedInputValue && ( +
+ +
+ )}
Manage Token Lists diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/searchToken.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/searchToken.ts new file mode 100644 index 0000000000..04623a4139 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/searchToken.ts @@ -0,0 +1,55 @@ +import { TokenWithLogo } from '../../types' + +export enum TokenSearchSource { + Blockchain = 'Blockchain', + External = 'External', + InactiveList = 'InactiveList', +} + +type TokenSearchResult = { + source: TokenSearchSource + tokens: TokenWithLogo[] +} + +// TODO: implement search +export async function searchToken(input: string): Promise { + if (input === '0x252d98fab648203aa33310721bbbddfa8f1b6587') { + return { + source: TokenSearchSource.Blockchain, + tokens: [new TokenWithLogo(undefined, 5, '0x252d98fab648203aa33310721bbbddfa8f1b6587', 18, 'GSUc', 'GSU Coin')], + } + } + if (input === 'cDAI') { + return { + source: TokenSearchSource.InactiveList, + tokens: [ + new TokenWithLogo(undefined, 5, '0x822397d9a55d0fefd20F5c4bCaB33C5F65bd28Eb', 6, 'cDAI', 'Compound DAI'), + ], + } + } + if (input === 'Coo') { + return { + source: TokenSearchSource.External, + tokens: [ + new TokenWithLogo( + 'https://etherscan.io/token/images/indexcoop_new_32.png', + 5, + '0x0954906da0Bf32d5479e25f46056d22f08464cab', + 18, + 'INDEX', + 'Index DAI' + ), + new TokenWithLogo( + 'https://etherscan.io/token/images/ETH2x-FLI_32.png', + 5, + '0xAa6E8127831c9DE45ae56bB1b0d4D4Da6e5665BD', + 18, + 'ETH2x-FLI', + 'ETH 2x Flexible Leverage Index' + ), + ], + } + } + + return undefined +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts index 584cf6d591..dc00bb5fb7 100644 --- a/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts +++ b/apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenModal/styled.ts @@ -2,6 +2,8 @@ import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' +import { blankButtonMixin } from '../../pure/commonElements' + export const Wrapper = styled.div` display: flex; flex-direction: column; @@ -25,25 +27,6 @@ export const Header = styled.div` font-weight: 500; margin: 0; } - - > button { - margin: 0; - padding: 0; - border: none; - outline: none; - background: none; - cursor: pointer; - opacity: 0.6; - transition: opacity 0.2s ease-in-out; - - > svg { - color: var(${UI.COLOR_TEXT1}); - } - - &:hover { - opacity: 1; - } - } ` export const SearchInput = styled.input` @@ -70,6 +53,8 @@ export const SearchInput = styled.input` ` export const ActionButton = styled.button` + ${blankButtonMixin}; + display: flex; width: 100%; align-items: center; @@ -82,11 +67,15 @@ export const ActionButton = styled.button` font-size: 16px; font-weight: 500; color: var(${UI.COLOR_TEXT1}); - background: none; - border: 0; - outline: none; &:hover { opacity: 0.7; } ` + +export const TokenNotFound = styled.div` + color: var(${UI.COLOR_LINK}); + font-weight: 500; + padding: 10px 0; + text-align: center; +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/mocks.ts b/apps/cowswap-frontend/src/modules/tokensList/mocks.ts new file mode 100644 index 0000000000..016c5e101e --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/mocks.ts @@ -0,0 +1,130 @@ +import { TokenList, TokenWithLogo } from './types' + +export const allTokensMock: TokenWithLogo[] = [ + { + name: 'Gnosis', + chainId: 5, + symbol: 'GNO', + decimals: 18, + address: '0x02abbdbaaa7b1bb64b5c878f7ac17f8dda169532', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png', + }, + { + name: 'Basic Attention Token', + chainId: 5, + symbol: 'BAT', + decimals: 18, + address: '0x70cBa46d2e933030E2f274AE58c951C800548AeF', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0D8775F648430679A709E98d2b0Cb6250d2887EF/logo.png', + }, + { + name: 'CoW Protocol Token', + chainId: 5, + symbol: 'COW', + decimals: 18, + address: '0x91056D4A53E1faa1A84306D4deAEc71085394bC8', + logoURI: 'https://gnosis.mypinata.cloud/ipfs/Qme9B6jRpGtZsRFcPjHvA5T4ugFuL4c3SzWfxyMPa59AMo', + }, + { + name: 'USD Coin', + chainId: 5, + symbol: 'USDC', + decimals: 6, + address: '0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png', + }, + { + name: 'DAI', + chainId: 5, + symbol: 'DAI', + decimals: 18, + address: '0xdc31Ee1784292379Fbb2964b3B9C4124D8F89C60', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png', + }, + { + name: '0x', + chainId: 5, + symbol: 'ZRX', + decimals: 18, + address: '0xe4E81Fa6B16327D4B78CFEB83AAdE04bA7075165', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png', + }, +].map((item) => new TokenWithLogo(item.logoURI, item.chainId, item.address, item.decimals, item.symbol, item.name)) + +export const favouriteTokensMock: TokenWithLogo[] = [ + { + name: 'Basic Attention Token', + chainId: 5, + symbol: 'BAT', + decimals: 18, + address: '0x70cBa46d2e933030E2f274AE58c951C800548AeF', + logoURI: + 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x0D8775F648430679A709E98d2b0Cb6250d2887EF/logo.png', + }, + { + name: 'Polymath Network', + chainId: 5, + symbol: 'POLY', + decimals: 18, + address: '0x9e32c0EfF886B6Ccae99350Fd5e7002dCED55F15', + logoURI: 'https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034', + }, +].map((item) => new TokenWithLogo(item.logoURI, item.chainId, item.address, item.decimals, item.symbol, item.name)) + +export const customTokensMock: TokenWithLogo[] = [ + { + name: 'Tether USD', + chainId: 5, + symbol: 'USDT', + decimals: 6, + address: '0x7b77F953e703E80CD97F6911385c0b1ceabC96Bc', + logoURI: undefined, + }, + { + name: 'Euro Coin', + chainId: 5, + symbol: 'EUROC', + decimals: 6, + address: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c', + logoURI: + 'https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/ethereum/assets/0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c/logo.png', + }, +].map((item) => new TokenWithLogo(item.logoURI, item.chainId, item.address, item.decimals, item.symbol, item.name)) + +export const listsMock: TokenList[] = [ + { + id: '1', + name: 'CowSwap Goerli', + url: 'https://tokenlists.org/token-list?url=https://raw.githubusercontent.com/cowprotocol/cowswap/develop/apps/cowswap-frontend/src/tokens/goerli-token-list.json', + logoUrl: 'https://gnosis.mypinata.cloud/ipfs/Qme9B6jRpGtZsRFcPjHvA5T4ugFuL4c3SzWfxyMPa59AMo', + tokensCount: 7, + enabled: true, + version: 'v0.0.0', + }, + { + id: '2', + name: 'Compound', + url: 'https://tokenlists.org/token-list?url=https://raw.githubusercontent.com/compound-finance/token-list/master/compound.tokenlist.json', + logoUrl: 'https://raw.githubusercontent.com/compound-finance/token-list/master/assets/compound-interface.svg', + tokensCount: 16, + enabled: false, + version: 'v0.2.1', + }, +] + +export const importListsMock: TokenList[] = [ + { + id: '4', + name: 'CoW Swap', + url: 'https://files.cow.fi/tokens/CowSwap.json', + logoUrl: 'https://raw.githubusercontent.com/cowprotocol/token-lists/main/src/public/images/list-logo.png', + tokensCount: 113, + enabled: true, + version: 'v0.0.0', + }, +] diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx index 8e5e1ba4c3..a687a0b832 100644 --- a/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/index.tsx @@ -1,9 +1,10 @@ -import { TokenAmount, TokenSymbol } from '@cowprotocol/ui' +import { TokenAmount } from '@cowprotocol/ui' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' import * as styledEl from './styled' import { TokenWithLogo } from '../../types' +import { TokenInfo } from '../TokenInfo' export interface AllTokensListProps { tokens: TokenWithLogo[] @@ -21,13 +22,7 @@ export function AllTokensList(props: AllTokensListProps) { return ( - - -
- - {token.name} -
-
+ diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts index bb08a9d8b2..27b207ebf1 100644 --- a/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/AllTokensList/styled.ts @@ -31,25 +31,3 @@ export const TokenItem = styled.button` background-color: ${({ disabled }) => !disabled && `var(${UI.COLOR_GREY})`}; } ` - -export const TokenLogo = styled.img` - --size: 36px; - width: var(--size); - height: var(--size); - border-radius: 50%; - background: var(${UI.COLOR_LIGHT_BLUE}); -` - -export const TokenInfo = styled.div` - display: flex; - flex-direction: row; - text-align: left; - gap: 16px; - font-weight: 500; -` - -export const TokenName = styled.div` - font-size: 12px; - font-weight: 400; - color: var(${UI.COLOR_TEXT2}); -` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.cosmos.tsx new file mode 100644 index 0000000000..c12de15cad --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.cosmos.tsx @@ -0,0 +1,24 @@ +import styled from 'styled-components/macro' + +import { importListsMock } from '../../mocks' + +import { ImportListModal } from './index' + +const Wrapper = styled.div` + width: 450px; +` + +const Fixtures = { + default: ( + + console.log('onBack')} + onClose={() => console.log('onClose')} + onImport={() => console.log('onImport')} + /> + + ), +} + +export default Fixtures diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.tsx new file mode 100644 index 0000000000..7be3afa732 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.tsx @@ -0,0 +1,65 @@ +import { useState } from 'react' + +import { ButtonPrimary } from '@cowprotocol/ui' + +import { AlertTriangle } from 'react-feather' + +import * as styledEl from './styled' + +import { TokenList } from '../../types' +import { ModalHeader } from '../ModalHeader' +import { TokenLogo } from '../TokenLogo' + +export interface ImportListModalProps { + list: TokenList + onImport(): void + onBack(): void + onClose(): void +} + +export function ImportListModal(props: ImportListModalProps) { + const { list, onBack, onClose, onImport } = props + + const [isAccepted, setIsAccepted] = useState(false) + + return ( + + + Import List + + + +
+ + {list.name} · {list.tokensCount} tokens + + + {list.url} + +
+
+ + +

Import at your own risk

+

+ By adding this list you are implicitly trusting that the data is correct. Anyone can create a list, including + creating fake versions of existing lists and lists that claim to represent projects that do not have one. +

+

+ If you purchase a token from this list, you may not be able to sell it back. +

+
+ + setIsAccepted((state) => !state)} /> + I understand + +
+
+ + + Import + + +
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/styled.ts new file mode 100644 index 0000000000..d5d4221900 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/styled.ts @@ -0,0 +1,50 @@ +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +export const Wrapper = styled.div` + display: block; + width: 100%; + background: var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: 20px; +` + +export const Contents = styled.div` + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: 5px; + padding: 20px; + margin: 20px; + border-radius: 20px; + color: var(${UI.COLOR_RED}); + background: var(${UI.COLOR_DANGER_BG}); +` + +export const ActionButtonWrapper = styled.div` + padding: 0 20px 20px 20px; +` + +export const AcceptanceBox = styled.label` + display: flex; + gap: 6px; + cursor: pointer; +` + +export const ListInfo = styled.div` + display: flex; + flex-direction: row; + margin: 20px; + gap: 20px; + padding: 0 10px; +` + +export const ListTitle = styled.div` + font-weight: 600; + font-size: 18px; +` + +export const ListLink = styled.a` + font-size: 14px; +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/index.tsx new file mode 100644 index 0000000000..c9a158eaa5 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/index.tsx @@ -0,0 +1,25 @@ +import * as styledEl from './styled' + +import { TokenWithLogo } from '../../types' +import { ImportButton } from '../commonElements' +import { TokenInfo } from '../TokenInfo' + +export interface ImportTokenItemProps { + token: TokenWithLogo + importToken(token: TokenWithLogo): void + shadowed?: boolean +} + +export function ImportTokenItem(props: ImportTokenItemProps) { + const { token, importToken, shadowed } = props + return ( + +
+ +
+
+ importToken(token)}>Import +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/styled.ts new file mode 100644 index 0000000000..446ba08db5 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenItem/styled.ts @@ -0,0 +1,13 @@ +import styled from 'styled-components/macro' + +export const Wrapper = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 0 20px; + margin-bottom: 20px; + + &:last-child { + margin-bottom: 0; + } +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx new file mode 100644 index 0000000000..efd6d6b44a --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx @@ -0,0 +1,23 @@ +import * as styledEl from './styled' + +import { TokenList } from '../../types' +import { ImportButton } from '../commonElements' +import { TokenListInfo } from '../TokenListInfo' + +export interface ImportTokenListItemProps { + list: TokenList + importList(list: TokenList): void +} + +export function ImportTokenListItem(props: ImportTokenListItemProps) { + const { list } = props + + return ( + + +
+ Import +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/styled.ts new file mode 100644 index 0000000000..524b879730 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/styled.ts @@ -0,0 +1,9 @@ +import styled from 'styled-components/macro' + +export const Wrapper = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + margin: 20px; + padding: 0 10px; +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.cosmos.tsx new file mode 100644 index 0000000000..75bff5e775 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.cosmos.tsx @@ -0,0 +1,23 @@ +import styled from 'styled-components/macro' + +import { customTokensMock } from '../../mocks' + +import { ImportTokenModal } from './index' + +const Wrapper = styled.div` + width: 450px; +` + +const Fixtures = { + default: ( + + console.log('onBack')} + onClose={() => console.log('onClose')} + /> + + ), +} + +export default Fixtures diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.tsx new file mode 100644 index 0000000000..579ac595be --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/index.tsx @@ -0,0 +1,51 @@ +import { ExplorerDataType, getExplorerLink } from '@cowprotocol/common-utils' +import { ButtonPrimary } from '@cowprotocol/ui' + +import { AlertCircle } from 'react-feather' + +import * as styledEl from './styled' + +import { TokenWithLogo } from '../../types' +import { ModalHeader } from '../ModalHeader' +import { TokenLogo } from '../TokenLogo' + +export interface ImportTokenModalProps { + token: TokenWithLogo + onBack(): void + onClose(): void +} + +export function ImportTokenModal(props: ImportTokenModalProps) { + const { token, onBack, onClose } = props + + return ( + + + Import token + + + +

+ This token doesn't appear on the active token list(s). Make sure this is the token that you want to trade. +

+ + + + {token.name} + + {token.address} + + + + Unknown Source + + + Import token +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/styled.ts new file mode 100644 index 0000000000..4f99b6d7f4 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenModal/styled.ts @@ -0,0 +1,56 @@ +import { TokenSymbol } from '@cowprotocol/ui' + +import { AlertCircle } from 'react-feather' +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +export const Wrapper = styled.div` + display: block; + width: 100%; + background: var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: 20px; +` + +export const Contents = styled.div` + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: 20px; + padding: 20px; +` + +export const AlertIcon = styled(AlertCircle)` + color: var(${UI.COLOR_RED}); + margin-top: 20px; +` + +export const TokenInfo = styled.div` + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: 10px; + font-size: 14px; +` + +export const StyledTokenSymbol = styled(TokenSymbol)` + font-weight: 600; + font-size: 20px; +` + +export const TokenName = styled.div` + color: var(${UI.COLOR_LINK}); +` + +export const UnknownSourceWarning = styled.div` + display: flex; + gap: 8px; + align-items: center; + background: var(${UI.COLOR_DANGER_BG}); + color: var(${UI.COLOR_DANGER_TEXT}); + border-radius: 10px; + font-size: 13px; + padding: 6px 12px; +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/index.tsx new file mode 100644 index 0000000000..714a00b983 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/index.tsx @@ -0,0 +1,26 @@ +import { CheckCircle } from 'react-feather' + +import * as styledEl from './styled' + +import { TokenList } from '../../types' +import { TokenListInfo } from '../TokenListInfo' + +export interface LoadedTokenListItemProps { + list: TokenList +} + +export function LoadedTokenListItem(props: LoadedTokenListItemProps) { + const { list } = props + + return ( + + +
+ + + Loaded + +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/styled.ts new file mode 100644 index 0000000000..5125a5e65b --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/LoadedTokenListItem/styled.ts @@ -0,0 +1,17 @@ +import styled from 'styled-components/macro' + +export const Wrapper = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + margin: 20px; + padding: 0 10px; +` + +export const LoadedInfo = styled.div` + display: flex; + flex-direction: row; + gap: 10px; + align-items: center; +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ModalHeader/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ModalHeader/index.tsx new file mode 100644 index 0000000000..10ef4f5d85 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ModalHeader/index.tsx @@ -0,0 +1,41 @@ +import { ArrowLeft, X } from 'react-feather' +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +import { IconButton } from '../commonElements' + +const Header = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + font-weight: 500; + font-size: 20px; + padding: 20px; + border-bottom: 1px solid var(${UI.COLOR_BORDER}); +` + +export interface ModalHeaderProps { + children: string + onBack(): void + onClose(): void + className?: string +} + +export function ModalHeader({ children, className, onBack, onClose }: ModalHeaderProps) { + return ( +
+
+ + + +
+
{children}
+
+ + + +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/index.tsx new file mode 100644 index 0000000000..52c40d4936 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/index.tsx @@ -0,0 +1,25 @@ +import { TokenSymbol } from '@cowprotocol/ui' + +import * as styledEl from './styled' + +import { TokenWithLogo } from '../../types' +import { TokenLogo } from '../TokenLogo' + +export interface TokenInfoProps { + token: TokenWithLogo + className?: string +} + +export function TokenInfo(props: TokenInfoProps) { + const { token, className } = props + + return ( + + +
+ + {token.name} +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/styled.ts new file mode 100644 index 0000000000..0c0f1dabe9 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/styled.ts @@ -0,0 +1,17 @@ +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +export const Wrapper = styled.div` + display: flex; + flex-direction: row; + text-align: left; + gap: 16px; + font-weight: 500; +` + +export const TokenName = styled.div` + font-size: 12px; + font-weight: 400; + color: var(${UI.COLOR_TEXT2}); +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/index.tsx new file mode 100644 index 0000000000..53ade782b0 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/index.tsx @@ -0,0 +1,30 @@ +import { ReactNode } from 'react' + +import * as styledEl from './styled' + +import { TokenList } from '../../types' +import { TokenLogo } from '../TokenLogo' + +export interface TokenListItemProps { + list: TokenList + className?: string + children?: ReactNode +} + +export function TokenListInfo(props: TokenListItemProps) { + const { list, children, className } = props + + return ( + +
+ +
+
+ {list.name} + + {list.tokensCount} tokens {children} + +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/styled.ts new file mode 100644 index 0000000000..c97f74be3e --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListInfo/styled.ts @@ -0,0 +1,21 @@ +import styled from 'styled-components/macro' + +export const ListInfo = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + gap: 10px; + font-size: 12px; +` + +export const ListName = styled.div` + font-size: 16px; + font-weight: 600; + margin-bottom: 5px; +` + +export const TokensInfo = styled.div` + display: flex; + gap: 5px; +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/index.tsx new file mode 100644 index 0000000000..b7bc926eb4 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/index.tsx @@ -0,0 +1,53 @@ +import { useState } from 'react' + +import { Menu, MenuItem } from '@reach/menu-button' +import { Settings } from 'react-feather' + +import { Toggle } from 'legacy/components/Toggle' + +import * as styledEl from './styled' + +import { TokenList } from '../../types' +import { IconButton } from '../commonElements' +import { TokenListInfo } from '../TokenListInfo' + +export interface TokenListItemProps { + list: TokenList + removeList(id: string): void + viewList(id: string): void +} + +export function TokenListItem(props: TokenListItemProps) { + const { list, removeList, viewList } = props + + // TODO: bind logic + const [isActive, setIsActive] = useState(list.enabled) + + return ( + + + + + + + + + + void 0}> + {list.version} + + viewList(list.id)}> + View List + + removeList(list.id)}> + Remove list + + + + +
+ setIsActive((state) => !state)} /> +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts new file mode 100644 index 0000000000..f48bdcec19 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts @@ -0,0 +1,46 @@ +import { MenuButton, MenuList } from '@reach/menu-button' +import { transparentize } from 'polished' +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +import { blankButtonMixin } from '../commonElements' + +export const Wrapper = styled.div<{ $enabled: boolean }>` + display: flex; + flex-direction: row; + justify-content: space-between; + margin: 20px; + padding: 20px; + border-radius: 20px; + border: 1px solid var(${UI.COLOR_GREY}); + background-color: ${({ $enabled, theme }) => ($enabled ? transparentize(0.8, theme.bg2) : 'transparent')}; +` + +export const SettingsButton = styled(MenuButton)` + ${blankButtonMixin} +` + +export const SettingsContainer = styled(MenuList)` + background: var(${UI.COLOR_CONTAINER_BG_01}); + padding: 10px; + border-radius: 10px; + border: 1px solid var(${UI.COLOR_GREY}); +` + +export const SettingsAction = styled.div` + color: var(${UI.COLOR_LINK}); + cursor: pointer; + padding: 5px; + box-sizing: content-box; + + &:hover { + text-decoration: underline; + } +` + +export const ListVersion = styled.div` + color: var(${UI.COLOR_TEXT1_INACTIVE}); + border-bottom: 1px solid var(${UI.COLOR_GREY}); + padding: 0 5px 10px 5px; +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenLogo/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenLogo/index.tsx new file mode 100644 index 0000000000..4ffc0aed23 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenLogo/index.tsx @@ -0,0 +1,38 @@ +import { atom, useAtom } from 'jotai' + +import { Slash } from 'react-feather' +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +const invalidUrlsAtom = atom<{ [url: string]: boolean }>({}) + +const TokenLogoWrapper = styled.div` + display: inline-block; + background: var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: 50%; +` + +export interface TokenLogoProps { + logoURI: string | undefined + className?: string + size?: number +} + +export function TokenLogo({ logoURI, className, size = 36 }: TokenLogoProps) { + const [invalidUrls, setInvalidUrls] = useAtom(invalidUrlsAtom) + + const hasError = invalidUrls[logoURI!] + + const onError = () => setInvalidUrls({ ...invalidUrls, [logoURI!]: true }) + + return ( + + {hasError || !logoURI ? ( + + ) : ( + + )} + + ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx new file mode 100644 index 0000000000..36d55445ba --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx @@ -0,0 +1,45 @@ +import TokenListLogo from '@cowprotocol/assets/svg/tokenlist.svg' + +import styled from 'styled-components/macro' + +import { InfoIcon } from 'legacy/components/InfoIcon' + +const Wrapper = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + padding: 0 20px; +` + +const Title = styled.h4` + font-size: 13px; + font-weight: 500; + + > img { + width: 18px; + vertical-align: middle; + margin-right: 6px; + } +` + +export interface TokenSourceTitleProps { + children: string + tooltip: string +} + +export function TokenSourceTitle(props: TokenSourceTitleProps) { + const { children, tooltip } = props + + return ( + + + <img src={TokenListLogo} /> + {children} + +
+ +
+
+ ) +} diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/commonElements.ts b/apps/cowswap-frontend/src/modules/tokensList/pure/commonElements.ts new file mode 100644 index 0000000000..b8edf20eec --- /dev/null +++ b/apps/cowswap-frontend/src/modules/tokensList/pure/commonElements.ts @@ -0,0 +1,73 @@ +import { transparentize } from 'polished' +import styled, { css } from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +export const blankButtonMixin = css` + background: none; + padding: 0; + margin: 0; + outline: none; + border: 0; + cursor: pointer; + + &:disabled { + cursor: default; + } +` + +export const PrimaryInputBox = styled.div` + margin: 20px 0 10px 0; + padding: 0 20px 20px 20px; + border-bottom: 1px solid var(${UI.COLOR_GREY}); +` + +export const PrimaryInput = styled.input` + width: 100%; + border: none; + background: var(${UI.COLOR_GREY}); + font-size: 18px; + border-radius: 20px; + padding: 16px; + color: var(${UI.COLOR_TEXT1}); + outline: none; + + ::placeholder { + color: var(${UI.COLOR_TEXT1}); + } + + &:focus { + ::placeholder { + color: ${({ theme }) => transparentize(0.7, theme.text1)}; + } + } +` + +export const IconButton = styled.button` + ${blankButtonMixin} + + > svg { + color: var(${UI.COLOR_TEXT1}); + + &:hover { + color: var(${UI.COLOR_TEXT2}); + } + } +` + +export const ImportButton = styled.button` + ${blankButtonMixin}; + + background-color: var(${UI.COLOR_CONTAINER_BG_02}); + color: var(${UI.COLOR_WHITE}); + font-size: 16px; + font-weight: 600; + padding: 6px 15px; + border-radius: 24px; + cursor: pointer; + transition: background-color 0.2s ease-in-out; + + &:hover { + background-color: var(${UI.COLOR_LINK}); + } +` diff --git a/apps/cowswap-frontend/src/modules/tokensList/types.ts b/apps/cowswap-frontend/src/modules/tokensList/types.ts index 0b9cf90087..77a7608e7a 100644 --- a/apps/cowswap-frontend/src/modules/tokensList/types.ts +++ b/apps/cowswap-frontend/src/modules/tokensList/types.ts @@ -13,3 +13,13 @@ export class TokenWithLogo extends Token { super(chainId, address, decimals, symbol, name, bypassChecksum) } } + +export interface TokenList { + id: string + name: string + logoUrl: string + url: string + enabled: boolean + tokensCount: number + version: string +} diff --git a/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsBox.tsx b/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsBox.tsx index 13bd2385d2..18b1d6d72f 100644 --- a/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsBox.tsx +++ b/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsBox.tsx @@ -4,7 +4,7 @@ import { Trans } from '@lingui/macro' import { ThemeContext } from 'styled-components/macro' import QuestionHelper from 'legacy/components/QuestionHelper' -import Toggle from 'legacy/components/Toggle' +import { Toggle } from 'legacy/components/Toggle' import { SettingsBoxTitle, SettingsBoxWrapper } from './styled' From 488c9267879d721910c480708a8f68d3ca9ec4dc Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Mon, 2 Oct 2023 14:26:04 +0600 Subject: [PATCH 26/36] refactor: remove unused hooks (#3175) --- .../src/legacy/hooks/Tokens.ts | 97 ------------------- .../src/legacy/hooks/useIsSwapUnsupported.ts | 22 ----- 2 files changed, 119 deletions(-) delete mode 100644 apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts diff --git a/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts b/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts index 27bf4f5aec..4026518ad4 100644 --- a/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts +++ b/apps/cowswap-frontend/src/legacy/hooks/Tokens.ts @@ -1,9 +1,7 @@ import { useAtomValue } from 'jotai' import { useMemo } from 'react' -import { getChainInfo } from '@cowprotocol/common-const' import { doesTokenMatchSymbolOrAddress } from '@cowprotocol/common-utils' -import { SupportedChainId } from '@cowprotocol/cow-sdk' import { useWalletInfo } from '@cowprotocol/wallet' import { Currency, Token } from '@uniswap/sdk-core' @@ -16,106 +14,11 @@ import { getTokenFilter } from 'lib/hooks/useTokenList/filtering' import { useCurrencyFromMap, useTokenFromMapOrNetwork } from '../../lib/hooks/useCurrency' import { TokenAmounts, useOnchainBalances } from '../../modules/tokens' -import { TokenAddressMap, useUnsupportedTokenList } from '../state/lists/hooks' - -// reduce token map into standard address <-> Token mapping, optionally include user added tokens -export function useTokensFromMap(tokenMap: TokenAddressMap, includeUserAdded: boolean): { [address: string]: Token } { - const { chainId } = useWalletInfo() - const userAddedTokens = useUserAddedTokens() - - return useMemo(() => { - if (!chainId) return {} - - // reduce to just tokens - const mapWithoutUrls = Object.keys(tokenMap[chainId] ?? {}).reduce<{ [address: string]: Token }>( - (newMap, address) => { - newMap[address] = tokenMap[chainId][address].token - return newMap - }, - {} - ) - - if (includeUserAdded) { - return ( - userAddedTokens - // reduce into all ALL_TOKENS filtered by the current chain - .reduce<{ [address: string]: Token }>( - (tokenMap, token) => { - tokenMap[token.address] = token - return tokenMap - }, - // must make a copy because reduce modifies the map, and we do not - // want to make a copy in every iteration - { ...mapWithoutUrls } - ) - ) - } - - return mapWithoutUrls - }, [chainId, userAddedTokens, tokenMap, includeUserAdded]) -} export function useAllTokens(): TokensByAddress { return useAtomValue(tokensByAddressAtom) } -type BridgeInfo = Record< - SupportedChainId, - { - tokenAddress: string - originBridgeAddress: string - destBridgeAddress: string - } -> - -export function useUnsupportedTokens(): { [address: string]: Token } { - const { chainId } = useWalletInfo() - const listsByUrl = useAllLists() - const unsupportedTokensMap = useUnsupportedTokenList() - const unsupportedTokens = useTokensFromMap(unsupportedTokensMap, false) - - // checks the default L2 lists to see if `bridgeInfo` has an L1 address value that is unsupported - const l2InferredBlockedTokens: typeof unsupportedTokens = useMemo(() => { - if (!chainId) { - return {} - } - - if (!listsByUrl) { - return {} - } - - const listUrl = getChainInfo(chainId)?.defaultListUrl - - if (!listUrl) { - return {} - } - - const { current: list } = listsByUrl[listUrl] - if (!list) { - return {} - } - - const unsupportedSet = new Set(Object.keys(unsupportedTokens)) - - return list.tokens.reduce((acc, tokenInfo) => { - const bridgeInfo = tokenInfo.extensions?.bridgeInfo as unknown as BridgeInfo - if ( - bridgeInfo && - bridgeInfo[SupportedChainId.MAINNET] && - bridgeInfo[SupportedChainId.MAINNET].tokenAddress && - unsupportedSet.has(bridgeInfo[SupportedChainId.MAINNET].tokenAddress) - ) { - const address = bridgeInfo[SupportedChainId.MAINNET].tokenAddress - // don't rely on decimals--it's possible that a token could be bridged w/ different decimals on the L2 - return { ...acc, [address]: new Token(SupportedChainId.MAINNET, address, tokenInfo.decimals) } - } - return acc - }, {}) - }, [chainId, listsByUrl, unsupportedTokens]) - - return { ...unsupportedTokens, ...l2InferredBlockedTokens } -} - export function useSearchInactiveTokenLists( search: string | undefined, minResults = 10, diff --git a/apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts b/apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts deleted file mode 100644 index 607de3afcb..0000000000 --- a/apps/cowswap-frontend/src/legacy/hooks/useIsSwapUnsupported.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { useMemo } from 'react' - -import { Currency } from '@uniswap/sdk-core' - -import { useUnsupportedTokens } from './Tokens' - -/** - * Returns true if the input currency or output currency cannot be traded in the interface - * @param currencyIn the input currency to check - * @param currencyOut the output currency to check - */ -export function useIsSwapUnsupported(currencyIn?: Currency | null, currencyOut?: Currency | null): boolean { - const unsupportedTokens = useUnsupportedTokens() - return useMemo(() => { - if (!unsupportedTokens) { - return false - } - const currencyInUnsupported = Boolean(currencyIn?.isToken && unsupportedTokens[currencyIn.address]) - const currencyOutUnsupported = Boolean(currencyOut?.isToken && unsupportedTokens[currencyOut.address]) - return currencyInUnsupported || currencyOutUnsupported - }, [currencyIn, currencyOut, unsupportedTokens]) -} From 57637efaeef395dca607ccdb29781ba27f5f6c00 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Wed, 4 Oct 2023 10:24:33 +0600 Subject: [PATCH 27/36] refactor: remove unused code (#3181) --- libs/common-const/src/routing.ts | 94 +------------------------------- libs/common-const/src/tokens.ts | 73 ------------------------- 2 files changed, 2 insertions(+), 165 deletions(-) diff --git a/libs/common-const/src/routing.ts b/libs/common-const/src/routing.ts index 4ff9a047cb..fe6ba032f7 100644 --- a/libs/common-const/src/routing.ts +++ b/libs/common-const/src/routing.ts @@ -1,79 +1,17 @@ // a list of tokens by chain import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { Currency, Token } from '@uniswap/sdk-core' +import { Currency } from '@uniswap/sdk-core' -import { - AMPL, - COW, - DAI, - ETH2X_FLI, - EURE_GNOSIS_CHAIN, - FEI, - FRAX, - FXS, - renBTC, - rETH2, - sETH2, - SWISE, - TRIBE, - USDC_MAINNET, - USDT, - WBTC, - WRAPPED_NATIVE_CURRENCY, -} from './tokens' +import { COW, DAI, EURE_GNOSIS_CHAIN, USDC_MAINNET, USDT, WBTC, WRAPPED_NATIVE_CURRENCY } from './tokens' import { USDC_GNOSIS_CHAIN, WBTC_GNOSIS_CHAIN, WETH_GNOSIS_CHAIN } from './gnosis_chain/constants' import { DAI_GOERLI, USDC_GOERLI } from './goerli/constants' -type ChainTokenList = { - readonly [chainId: number]: Token[] -} - type ChainCurrencyList = { readonly [chainId: number]: Currency[] } -const WRAPPED_NATIVE_CURRENCIES_ONLY: ChainTokenList = Object.fromEntries( - Object.entries(WRAPPED_NATIVE_CURRENCY) - .map(([key, value]) => [key, [value]]) - .filter(Boolean) -) - -// used to construct intermediary pairs for trading -export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = { - ...WRAPPED_NATIVE_CURRENCIES_ONLY, - [SupportedChainId.MAINNET]: [ - ...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.MAINNET], - DAI, - USDC_MAINNET, - USDT, - WBTC, - ], -} -export const ADDITIONAL_BASES: { [chainId: number]: { [tokenAddress: string]: Token[] } } = { - [SupportedChainId.MAINNET]: { - '0xF16E4d813f4DcfDe4c5b44f305c908742De84eF0': [ETH2X_FLI], - [rETH2.address]: [sETH2], - [SWISE.address]: [sETH2], - [FEI.address]: [TRIBE], - [TRIBE.address]: [FEI], - [FRAX.address]: [FXS], - [FXS.address]: [FRAX], - [WBTC.address]: [renBTC], - [renBTC.address]: [WBTC], - }, -} -/** - * Some tokens can only be swapped via certain pairs, so we override the list of bases that are considered for these - * tokens. - */ -export const CUSTOM_BASES: { [chainId: number]: { [tokenAddress: string]: Token[] } } = { - [SupportedChainId.MAINNET]: { - [AMPL.address]: [DAI, WRAPPED_NATIVE_CURRENCY[SupportedChainId.MAINNET] as Token], - }, -} - /** * Shows up in the currency select for swap and add liquidity */ @@ -101,31 +39,3 @@ export const COMMON_BASES: ChainCurrencyList = { WBTC_GNOSIS_CHAIN, ], } - -// used to construct the list of all pairs we consider by default in the frontend -export const BASES_TO_TRACK_LIQUIDITY_FOR: ChainTokenList = { - ...WRAPPED_NATIVE_CURRENCIES_ONLY, - [SupportedChainId.MAINNET]: [ - ...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.MAINNET], - DAI, - USDC_MAINNET, - USDT, - WBTC, - ], -} -export const PINNED_PAIRS: { readonly [chainId: number]: [Token, Token][] } = { - [SupportedChainId.MAINNET]: [ - [ - new Token(SupportedChainId.MAINNET, '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643', 8, 'cDAI', 'Compound Dai'), - new Token( - SupportedChainId.MAINNET, - '0x39AA39c021dfbaE8faC545936693aC917d5E7563', - 8, - 'cUSDC', - 'Compound USD Coin' - ), - ], - [USDC_MAINNET, USDT], - [DAI, USDT], - ], -} diff --git a/libs/common-const/src/tokens.ts b/libs/common-const/src/tokens.ts index 11278f34f3..473ddb5cad 100644 --- a/libs/common-const/src/tokens.ts +++ b/libs/common-const/src/tokens.ts @@ -32,13 +32,6 @@ export const USDC_GOERLI = new Token( 'USDC', 'USD//C' ) -export const AMPL = new Token( - SupportedChainId.MAINNET, - '0xD46bA6D942050d489DBd938a2C909A5d5039A161', - 9, - 'AMPL', - 'Ampleforth' -) export const DAI = new Token( SupportedChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', @@ -65,70 +58,6 @@ export const WBTC = new Token( 'WBTC', 'Wrapped BTC' ) -export const FEI = new Token( - SupportedChainId.MAINNET, - '0x956F47F50A910163D8BF957Cf5846D573E7f87CA', - 18, - 'FEI', - 'Fei USD' -) -export const TRIBE = new Token( - SupportedChainId.MAINNET, - '0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B', - 18, - 'TRIBE', - 'Tribe' -) -export const FRAX = new Token( - SupportedChainId.MAINNET, - '0x853d955aCEf822Db058eb8505911ED77F175b99e', - 18, - 'FRAX', - 'Frax' -) -export const FXS = new Token( - SupportedChainId.MAINNET, - '0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0', - 18, - 'FXS', - 'Frax Share' -) -export const renBTC = new Token( - SupportedChainId.MAINNET, - '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D', - 8, - 'renBTC', - 'renBTC' -) -export const ETH2X_FLI = new Token( - SupportedChainId.MAINNET, - '0xAa6E8127831c9DE45ae56bB1b0d4D4Da6e5665BD', - 18, - 'ETH2x-FLI', - 'ETH 2x Flexible Leverage Index' -) -export const sETH2 = new Token( - SupportedChainId.MAINNET, - '0xFe2e637202056d30016725477c5da089Ab0A043A', - 18, - 'sETH2', - 'StakeWise Staked ETH2' -) -export const rETH2 = new Token( - SupportedChainId.MAINNET, - '0x20BC832ca081b91433ff6c17f85701B6e92486c5', - 18, - 'rETH2', - 'StakeWise Reward ETH2' -) -export const SWISE = new Token( - SupportedChainId.MAINNET, - '0x48C3399719B582dD63eB5AADf12A40B4C3f52FA2', - 18, - 'SWISE', - 'StakeWise' -) - export const WRAPPED_NATIVE_CURRENCY: { [chainId in SupportedChainId]: Token } = { [SupportedChainId.MAINNET]: WETH9[SupportedChainId.MAINNET], [SupportedChainId.GNOSIS_CHAIN]: WXDAI, @@ -185,8 +114,6 @@ export class GpEther extends Ether { throw new Error('Unsupported chain ID') } - private static _cachedExtendedEther: { [chainId: number]: NativeCurrency } = {} - public static onChain = nativeOnChain } From ed53662eedec3fb4ce3d880c9303df701f5059c1 Mon Sep 17 00:00:00 2001 From: Leandro Date: Thu, 5 Oct 2023 02:18:37 -0700 Subject: [PATCH 28/36] feat(permit): modals SWAP (#3158) * refactor: extract NewModal into its own folder * refactor: only set permitInfo if there is not enough allowance * refactor: use setter to load current state rather than relying on stale one * feat: store permit status on swap state * fix: remove hasEnoughAllowance from TradeFlowContext * chore: use relative imports inside the module * feat: add PermitModal pure and container * chore: export cosmos command for easier access * refactor: simplify TokenAmount interface (it was doubling Nullish<>) * refactor: sort imports * chore: pass trade and swapConfirmState to TransactionConfirmationModal * feat: add PermitModal to TransactionConfirmationModal * chore: redid the logic to update the signature requesting * refactor: always set permitSignatureState * chore: remove stale comment * chore: update handlePermit export to fix build warning * chore: outputAmountWithoutFee never needed to be optional * chore: use TradeAmounts instead of TradeGp --- .../common/containers/PermitModal/index.tsx | 15 ++ .../src/common/pure/Modal/index.cosmos.tsx | 73 ++------ .../src/common/pure/Modal/index.tsx | 162 +---------------- .../src/common/pure/NewModal/index.cosmos.tsx | 85 +++++++++ .../src/common/pure/NewModal/index.tsx | 163 ++++++++++++++++++ .../common/pure/PermitModal/index.cosmos.tsx | 49 ++++++ .../src/common/pure/PermitModal/index.tsx | 102 +++++++++++ .../src/common/pure/Stepper/index.tsx | 28 +-- .../TransactionConfirmationModal/index.tsx | 20 ++- .../swap/ConfirmSwapModal/index.tsx | 11 +- .../src/legacy/state/swap/TradeGp.ts | 4 +- .../src/mocks/tradeStateMock.ts | 1 - .../limitOrders/hooks/useTradeFlowContext.ts | 5 +- .../pure/LimitOrdersDetails/index.cosmos.tsx | 1 - .../limitOrders/services/tradeFlow/index.ts | 2 - .../src/modules/limitOrders/services/types.ts | 5 +- .../src/modules/permit/index.ts | 2 +- .../src/modules/permit/types.ts | 1 - .../src/modules/permit/utils/handlePermit.ts | 12 +- .../swap/hooks/useSwapConfirmManager.ts | 104 +++++++---- .../modules/swap/hooks/useSwapFlowContext.ts | 5 +- .../modules/swap/pure/SwapButtons/index.tsx | 2 +- .../modules/swap/services/swapFlow/index.ts | 4 +- .../src/modules/swap/services/types.ts | 4 +- .../src/modules/swap/state/swapConfirmAtom.ts | 2 + libs/ui/src/pure/TokenAmount/index.tsx | 5 +- package.json | 1 + 27 files changed, 569 insertions(+), 299 deletions(-) create mode 100644 apps/cowswap-frontend/src/common/containers/PermitModal/index.tsx create mode 100644 apps/cowswap-frontend/src/common/pure/NewModal/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/common/pure/NewModal/index.tsx create mode 100644 apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx create mode 100644 apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx diff --git a/apps/cowswap-frontend/src/common/containers/PermitModal/index.tsx b/apps/cowswap-frontend/src/common/containers/PermitModal/index.tsx new file mode 100644 index 0000000000..d2bb9c8d1a --- /dev/null +++ b/apps/cowswap-frontend/src/common/containers/PermitModal/index.tsx @@ -0,0 +1,15 @@ +import { useMemo } from 'react' + +import { Identicon, useWalletInfo } from '@cowprotocol/wallet' + +import { PermitModal as Pure, PermitModalProps } from '../../pure/PermitModal' + +export type PermitModalContainerProps = Omit + +export function PermitModal(props: PermitModalContainerProps) { + const { account } = useWalletInfo() + + const icon = useMemo(() => (account ? : undefined), [account]) + + return +} diff --git a/apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx index 3630b46c01..f07e58e4a5 100644 --- a/apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/common/pure/Modal/index.cosmos.tsx @@ -1,99 +1,46 @@ -import ICON_ARROW from 'assets/icon/arrow.svg' -import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' -import { MOCK_TOKEN, IMAGE_ACCOUNT } from 'common/constants/cosmos'; -import { UI } from 'common/constants/theme' -import { IconSpinner } from 'common/pure/IconSpinner' -import { Stepper } from 'common/pure/Stepper' - -import { Modal, CowModal, NewModal, NewModalContentTop, NewModalContentBottom } from './index' +import { CowModal, Modal } from './index' const Wrapper = styled.div` width: 100vw; height: 100vh; ` -const ArrowRight = styled(SVG)` - --size: 12px; - width: var(--size); - height: var(--size); - margin: auto; - - > path { - fill: var(${UI.COLOR_TEXT2}); - } -` - const ModalFixtures = { 'default modal': ( - console.log("Dismissed")}> + console.log('Dismissed')}> Default modal content here ), 'modal with minHeight and maxHeight': ( - console.log("Dismissed")} minHeight={50} maxHeight={80}> + console.log('Dismissed')} minHeight={50} maxHeight={80}> Modal with minHeight and maxHeight ), 'cow modal': ( - console.log("Cow Modal Dismissed")} maxWidth={400}> + console.log('Cow Modal Dismissed')} maxWidth={400}> Cow Modal Content ), 'cow modal with background color': ( - console.log("Cow Modal Dismissed")} maxWidth={400} backgroundColor="pink"> + console.log('Cow Modal Dismissed')} + maxWidth={400} + backgroundColor="pink" + > Cow Modal with Pink Background ), - 'new modal + content top/bottom': ( - - - - -

Approve spending AAVE
on CoW Swap

-
- - -

Sign (gas-free!) in your wallet...

- -
-
-
- ), - 'new modal + content top/bottom 2': ( - - - - - -

Confirm Swap

-

10 AAVE 564.7202 DAI

-
-
- - -

Sign (gas-free!) in your wallet...

- -
-
-
- ), - 'new modal + heading title': ( - - - - New Modal - - - - ), } export default ModalFixtures diff --git a/apps/cowswap-frontend/src/common/pure/Modal/index.tsx b/apps/cowswap-frontend/src/common/pure/Modal/index.tsx index 9b3c952155..6bc9d7681c 100644 --- a/apps/cowswap-frontend/src/common/pure/Modal/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/Modal/index.tsx @@ -4,8 +4,6 @@ import { isMobile } from '@cowprotocol/common-utils' import { useSpringValue, useTransition } from '@react-spring/web' import { useGesture } from '@use-gesture/react' -import CLOSE_ICON from 'assets/icon/x.svg' -import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' import { UI } from 'common/constants/theme' @@ -24,6 +22,9 @@ interface ModalProps { children?: React.ReactNode } +/** + * @deprecated use common/pure/NewModal instead + */ export function Modal({ isOpen, onDismiss, @@ -145,160 +146,3 @@ export const CowModal = styled(Modal)<{ } } ` - -// New Modal to be used going forward ================================= -const ModalInner = styled.div` - display: flex; - flex-direction: column; - width: 100%; - height: auto; - margin: auto; - background: var(${UI.COLOR_CONTAINER_BG_01}); - border-radius: var(${UI.BORDER_RADIUS_NORMAL}); - box-shadow: var(${UI.BOX_SHADOW_NORMAL}); - padding: 0; - - ${({ theme }) => theme.mediaWidth.upToSmall` - margin: 8vh 0 0; - border-radius: 0; - border-top-left-radius: var(${UI.BORDER_RADIUS_NORMAL}); - border-top-right-radius: var(${UI.BORDER_RADIUS_NORMAL}); - box-shadow: none; - `} -` - -const NewCowModal = styled.div<{ maxWidth?: number | string; minHeight?: number | string }>` - display: flex; - width: 100%; - height: 100%; - margin: auto; - background: var(${UI.MODAL_BACKDROP}); - overflow-y: auto; - - ${ModalInner} { - max-width: ${({ maxWidth }) => (maxWidth ? `${maxWidth}px` : '100%')}; - min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : '100%')}; - - ${({ theme }) => theme.mediaWidth.upToSmall` - max-width: 100%; - min-height: initial; - height: auto; - `} - } -` - -const Heading = styled.h2` - display: flex; - justify-content: space-between; - width: 100%; - height: auto; - padding: 18px; - margin: 0; - font-size: var(${UI.FONT_SIZE_MEDIUM}); - - ${({ theme }) => theme.mediaWidth.upToSmall` - position: sticky; - top: 0; - `} -` - -const IconX = styled.div` - position: fixed; - top: 18px; - right: 18px; - cursor: pointer; - opacity: 0.6; - transition: opacity 0.2s ease-in-out; - margin: 0 0 0 auto; - - > svg { - width: var(${UI.ICON_SIZE_NORMAL}); - height: var(${UI.ICON_SIZE_NORMAL}); - fill: var(${UI.ICON_COLOR_NORMAL}); - } - - &:hover { - opacity: 1; - } -` - -const NewModalContent = styled.div<{ paddingTop?: number }>` - display: flex; - align-items: center; - justify-content: center; - flex-flow: column wrap; - flex: 1; - width: 100%; - height: 100%; - padding: 0 var(${UI.PADDING_NORMAL}) var(${UI.PADDING_NORMAL}); - - h1, - h2, - h3 { - width: 100%; - font-size: var(${UI.FONT_SIZE_LARGER}); - font-weight: var(${UI.FONT_WEIGHT_BOLD}); - text-align: center; - line-height: 1.4; - margin: 0 auto; - } - - p { - font-size: var(${UI.FONT_SIZE_NORMAL}); - font-weight: var(${UI.FONT_WEIGHT_NORMAL}); - color: var(${UI.COLOR_TEXT2}); - margin: 0 auto; - padding: 0; - } -` - -export const NewModalContentTop = styled.div<{ paddingTop?: number }>` - display: flex; - flex-flow: column wrap; - align-items: center; - justify-content: center; - width: 100%; - margin: 0 0 auto; - padding: ${({ paddingTop = 0 }) => `${paddingTop}px`} 0 0; - gap: 24px; - - > span { - gap: 6px; - display: flex; - flex-flow: column wrap; - } - - p { - font-size: var(${UI.FONT_SIZE_MEDIUM}); - } -` - -export const NewModalContentBottom = styled(NewModalContentTop)` - margin: auto 0 0; - - p { - font-size: var(${UI.FONT_SIZE_NORMAL}); - } -` -interface NewModalProps { - maxWidth?: number - minHeight?: number - title?: string - onDismiss?: () => void - children?: React.ReactNode -} - -export function NewModal({ maxWidth = 450, minHeight = 450, title, children, onDismiss }: NewModalProps) { - return ( - - - {title && {title}} - {children} - - - onDismiss && onDismiss()}> - - - - ) -} diff --git a/apps/cowswap-frontend/src/common/pure/NewModal/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/NewModal/index.cosmos.tsx new file mode 100644 index 0000000000..72d1966d76 --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/NewModal/index.cosmos.tsx @@ -0,0 +1,85 @@ +import ICON_ARROW from 'assets/icon/arrow.svg' +import SVG from 'react-inlinesvg' +import styled from 'styled-components/macro' + +import { IMAGE_ACCOUNT, MOCK_TOKEN } from 'common/constants/cosmos' +import { UI } from 'common/constants/theme' +import { IconSpinner } from 'common/pure/IconSpinner' +import { Stepper } from 'common/pure/Stepper' + +import { NewModal, NewModalContentBottom, NewModalContentTop } from './index' + +const Wrapper = styled.div` + width: 100vw; + height: 100vh; +` + +const ArrowRight = styled(SVG)` + --size: 12px; + width: var(--size); + height: var(--size); + margin: auto; + + > path { + fill: var(${UI.COLOR_TEXT2}); + } +` + +const ModalFixtures = { + 'new modal + content top/bottom': ( + + + + +

+ Approve spending AAVE
on CoW Swap +

+
+ + +

Sign (gas-free!) in your wallet...

+ +
+
+
+ ), + 'new modal + content top/bottom 2': ( + + + + + +

Confirm Swap

+

+ 10 AAVE 564.7202 DAI +

+
+
+ + +

Sign (gas-free!) in your wallet...

+ +
+
+
+ ), + 'new modal + heading title': ( + + - New Modal - + + ), +} + +export default ModalFixtures diff --git a/apps/cowswap-frontend/src/common/pure/NewModal/index.tsx b/apps/cowswap-frontend/src/common/pure/NewModal/index.tsx new file mode 100644 index 0000000000..cab27ecbed --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/NewModal/index.tsx @@ -0,0 +1,163 @@ +import React from 'react' + +import CLOSE_ICON from 'assets/icon/x.svg' +import SVG from 'react-inlinesvg' +import styled from 'styled-components/macro' + +import { UI } from 'common/constants/theme' + +const ModalInner = styled.div` + display: flex; + flex-direction: column; + width: 100%; + height: auto; + margin: auto; + background: var(${UI.COLOR_CONTAINER_BG_01}); + border-radius: var(${UI.BORDER_RADIUS_NORMAL}); + box-shadow: var(${UI.BOX_SHADOW_NORMAL}); + padding: 0; + + ${({ theme }) => theme.mediaWidth.upToSmall` + margin: 8vh 0 0; + border-radius: 0; + border-top-left-radius: var(${UI.BORDER_RADIUS_NORMAL}); + border-top-right-radius: var(${UI.BORDER_RADIUS_NORMAL}); + box-shadow: none; + `} +` + +const Wrapper = styled.div<{ maxWidth?: number | string; minHeight?: number | string }>` + display: flex; + width: 100%; + height: 100%; + margin: auto; + background: var(${UI.MODAL_BACKDROP}); + overflow-y: auto; + + ${ModalInner} { + max-width: ${({ maxWidth }) => (maxWidth ? `${maxWidth}px` : '100%')}; + min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : '100%')}; + + ${({ theme }) => theme.mediaWidth.upToSmall` + max-width: 100%; + min-height: initial; + height: auto; + `} + } +` + +const Heading = styled.h2` + display: flex; + justify-content: space-between; + width: 100%; + height: auto; + padding: 18px; + margin: 0; + font-size: var(${UI.FONT_SIZE_MEDIUM}); + + ${({ theme }) => theme.mediaWidth.upToSmall` + position: sticky; + top: 0; + `} +` + +const IconX = styled.div` + position: fixed; + top: 18px; + right: 18px; + cursor: pointer; + opacity: 0.6; + transition: opacity 0.2s ease-in-out; + margin: 0 0 0 auto; + + > svg { + width: var(${UI.ICON_SIZE_NORMAL}); + height: var(${UI.ICON_SIZE_NORMAL}); + fill: var(${UI.ICON_COLOR_NORMAL}); + } + + &:hover { + opacity: 1; + } +` + +const NewModalContent = styled.div<{ paddingTop?: number }>` + display: flex; + align-items: center; + justify-content: center; + flex-flow: column wrap; + flex: 1; + width: 100%; + height: 100%; + padding: 0 var(${UI.PADDING_NORMAL}) var(${UI.PADDING_NORMAL}); + + h1, + h2, + h3 { + width: 100%; + font-size: var(${UI.FONT_SIZE_LARGER}); + font-weight: var(${UI.FONT_WEIGHT_BOLD}); + text-align: center; + line-height: 1.4; + margin: 0 auto; + } + + p { + font-size: var(${UI.FONT_SIZE_NORMAL}); + font-weight: var(${UI.FONT_WEIGHT_NORMAL}); + color: var(${UI.COLOR_TEXT2}); + margin: 0 auto; + padding: 0; + } +` + +export const NewModalContentTop = styled.div<{ paddingTop?: number }>` + display: flex; + flex-flow: column wrap; + align-items: center; + justify-content: center; + width: 100%; + margin: 0 0 auto; + padding: ${({ paddingTop = 0 }) => `${paddingTop}px`} 0 0; + gap: 24px; + + > span { + gap: 6px; + display: flex; + flex-flow: column wrap; + } + + p { + font-size: var(${UI.FONT_SIZE_MEDIUM}); + } +` + +export const NewModalContentBottom = styled(NewModalContentTop)` + margin: auto 0 0; + + p { + font-size: var(${UI.FONT_SIZE_NORMAL}); + } +` +export interface NewModalProps { + maxWidth?: number + minHeight?: number + title?: string + onDismiss?: () => void + children?: React.ReactNode +} + +export function NewModal({ maxWidth = 450, minHeight = 450, title, children, onDismiss }: NewModalProps) { + return ( + + + {title && {title}} + {children} + + + onDismiss && onDismiss()}> + + + + ) +} diff --git a/apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx new file mode 100644 index 0000000000..0c2f775874 --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx @@ -0,0 +1,49 @@ +import { USDC_MAINNET, WBTC } from '@cowprotocol/common-const' +import { Identicon } from '@cowprotocol/wallet' +import { CurrencyAmount } from '@uniswap/sdk-core' + +import styled from 'styled-components/macro' + +import { IconSpinner } from '../IconSpinner' + +import { PermitModal } from './index' + +const Wrapper = styled.div` + width: 100vw; + height: 100vh; +` + +const INPUT_AMOUNT = CurrencyAmount.fromRawAmount(USDC_MAINNET, 500_000 * 10 ** USDC_MAINNET.decimals) +const OUTPUT_AMOUNT = CurrencyAmount.fromRawAmount(WBTC, 1.2 * 10 ** WBTC.decimals) + +const WALLET_ICON = ( + + + +) + +const PermitModalFixtures = { + 'Pending permit signature': ( + + + + ), + 'Pending order signature': ( + + + + ), + // These two cases should happen, but including for completeness as the parameters allow it + 'Missing amounts on approve': ( + + + + ), + 'Missing amounts on submit': ( + + + + ), +} + +export default PermitModalFixtures diff --git a/apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx b/apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx new file mode 100644 index 0000000000..572e8091b6 --- /dev/null +++ b/apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx @@ -0,0 +1,102 @@ +import { useMemo } from 'react' + +import { TokenAmount, TokenSymbol } from '@cowprotocol/ui' +import { Currency, CurrencyAmount } from '@uniswap/sdk-core' + +import ICON_ARROW from 'assets/icon/arrow.svg' +import SVG from 'react-inlinesvg' +import styled from 'styled-components/macro' +import { Nullish } from 'types' + +import { UI } from '../../constants/theme' +import { IconSpinner } from '../IconSpinner' +import { NewModal, NewModalContentBottom, NewModalContentTop, NewModalProps } from '../NewModal' +import { Stepper, StepProps } from '../Stepper' + +export type PermitModalProps = NewModalProps & { + inputAmount: Nullish> + outputAmount: Nullish> + step: 'approve' | 'submit' + icon?: React.ReactNode +} + +/** + * You probably want to use containers/PermitModal instead + * This is the pure component for cosmos + */ +export function PermitModal(props: PermitModalProps) { + const { inputAmount, outputAmount, step, icon: inputIcon } = props + + const steps: StepProps[] = useMemo( + () => [ + { + stepState: step === 'approve' ? 'loading' : 'finished', + stepNumber: 1, + label: 'Approve' + (step === 'approve' ? '' : 'd'), + }, + { stepState: step === 'submit' ? 'loading' : 'active', stepNumber: 2, label: 'Submit' }, + ], + [step] + ) + const icon = useMemo( + () => + step === 'approve' ? ( + + ) : ( + {inputIcon} + ), + [inputAmount?.currency, inputIcon, step] + ) + + const title = useMemo( + () => + step === 'approve' ? ( + <> + Approve spending
+ on CoW Swap + + ) : ( + 'Confirm Swap' + ), + [inputAmount?.currency, step] + ) + + const body = useMemo( + () => + step === 'approve' ? null : ( +

+ {' '} + +

+ ), + [inputAmount, outputAmount, step] + ) + + return ( + + + {icon} + +

{title}

+ {body} +
+
+ + +

Sign (gas-free!) in your wallet...

+ +
+
+ ) +} + +const ArrowRight = styled(SVG)` + --size: 12px; + width: var(--size); + height: var(--size); + margin: auto; + + > path { + fill: var(${UI.COLOR_TEXT2}); + } +` diff --git a/apps/cowswap-frontend/src/common/pure/Stepper/index.tsx b/apps/cowswap-frontend/src/common/pure/Stepper/index.tsx index f3a9ee9957..b1673895b8 100644 --- a/apps/cowswap-frontend/src/common/pure/Stepper/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/Stepper/index.tsx @@ -7,7 +7,7 @@ import { IconSpinner } from 'common/pure/IconSpinner' type StepState = 'active' | 'finished' | 'disabled' | 'error' | 'loading' | 'open' -interface StepProps { +export interface StepProps { stepState: StepState stepNumber: number label: string @@ -24,7 +24,11 @@ interface StepStyles { const stateStyles: Record = { active: { dotBackground: UI.COLOR_LINK, dotColor: UI.COLOR_CONTAINER_BG_01, labelColor: UI.COLOR_TEXT1 }, finished: { dotBackground: UI.COLOR_LINK_OPACITY_10, dotColor: UI.COLOR_LINK, labelColor: UI.COLOR_TEXT1 }, - disabled: { dotBackground: UI.COLOR_TEXT1_OPACITY_25, dotColor: UI.COLOR_TEXT1_OPACITY_25, labelColor: UI.COLOR_TEXT1_OPACITY_25 }, + disabled: { + dotBackground: UI.COLOR_TEXT1_OPACITY_25, + dotColor: UI.COLOR_TEXT1_OPACITY_25, + labelColor: UI.COLOR_TEXT1_OPACITY_25, + }, error: { dotBackground: UI.COLOR_DANGER_BG, dotColor: UI.COLOR_DANGER, labelColor: UI.COLOR_DANGER }, loading: { dotBackground: UI.COLOR_LINK, dotColor: UI.COLOR_CONTAINER_BG_01, labelColor: UI.COLOR_LINK }, open: { dotBackground: UI.COLOR_TEXT1_OPACITY_10, dotColor: UI.COLOR_TEXT2, labelColor: UI.COLOR_TEXT2 }, @@ -81,7 +85,12 @@ const Step = styled.div` width: 100%; height: 1px; border: 0; - background: ${({ stepState }) => stepState === 'error' ? `var(${stateStyles['error'].dotBackground})` : stepState === 'finished' ? `var(${stateStyles['finished'].dotBackground})` : `var(${UI.COLOR_TEXT1_OPACITY_25})`}; + background: ${({ stepState }) => + stepState === 'error' + ? `var(${stateStyles['error'].dotBackground})` + : stepState === 'finished' + ? `var(${stateStyles['finished'].dotBackground})` + : `var(${UI.COLOR_TEXT1_OPACITY_25})`}; border-radius: var(${UI.BORDER_RADIUS_NORMAL}); } @@ -96,7 +105,7 @@ const Step = styled.div` const Wrapper = styled.div<{ maxWidth?: string; dotSize?: number }>` --dotSize: ${({ dotSize }) => `${dotSize}px`}; - width: ${({ maxWidth }) => maxWidth ? maxWidth : '100%'}; + width: ${({ maxWidth }) => (maxWidth ? maxWidth : '100%')}; display: flex; align-items: center; justify-content: space-between; @@ -121,14 +130,9 @@ export function Stepper({ steps, maxWidth, dotSize = 21 }: StepperProps) { {step.stepNumber} - ) : - {step.stepState === 'finished' ? ( - - ) : ( - step.stepNumber - )} - - } + ) : ( + {step.stepState === 'finished' ? : step.stepNumber} + )} {step.label}
diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx index c74ca9b696..18a87ea32e 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx @@ -9,11 +9,14 @@ import { useMultipleActivityDescriptors } from 'legacy/hooks/useRecentActivity' import { ConfirmOperationType } from 'legacy/state/types' import { useSetIsConfirmationModalOpen } from 'modules/swap/state/surplusModal' +import { SwapConfirmState } from 'modules/swap/state/swapConfirmAtom' import { handleFollowPendingTxPopupAtom } from 'modules/wallet/state/followPendingTxPopupAtom' +import { PermitModal } from 'common/containers/PermitModal' import { useGetSurplusData } from 'common/hooks/useGetSurplusFiatValue' import { CowModal } from 'common/pure/Modal' import { TransactionSubmittedContent } from 'common/pure/TransactionSubmittedContent' +import { TradeAmounts } from 'common/types' import { LegacyConfirmationPendingContent } from './LegacyConfirmationPendingContent' @@ -26,6 +29,8 @@ export interface ConfirmationModalProps { pendingText?: ReactNode currencyToAdd?: Currency | undefined operationType: ConfirmOperationType + tradeAmounts?: TradeAmounts | undefined + swapConfirmState?: SwapConfirmState | undefined } export function TransactionConfirmationModal({ @@ -37,6 +42,8 @@ export function TransactionConfirmationModal({ content, currencyToAdd, operationType, + tradeAmounts, + swapConfirmState, }: ConfirmationModalProps) { const { chainId } = useWalletInfo() const setShowFollowPendingTxPopup = useSetAtom(handleFollowPendingTxPopupAtom) @@ -70,7 +77,14 @@ export function TransactionConfirmationModal({ return ( - {attemptingTxn ? ( + {showPermitModal(swapConfirmState) ? ( + + ) : attemptingTxn ? ( ), - [onDismiss, modalBottom, modalHeader, swapErrorMessage] + [swapErrorMessage, onDismiss, modalHeader, modalBottom] + ) + + const tradeAmounts: TradeAmounts | undefined = useMemo( + () => + trade ? { inputAmount: trade.inputAmountWithoutFee, outputAmount: trade.outputAmountWithoutFee } : undefined, + [trade] ) return ( @@ -115,6 +122,8 @@ export function ConfirmSwapModal({ pendingText={} currencyToAdd={trade?.outputAmount.currency} operationType={ConfirmOperationType.ORDER_SIGN} + tradeAmounts={tradeAmounts} + swapConfirmState={swapConfirmState} /> ) } diff --git a/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts b/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts index 42089c4eb7..d98caa57cd 100644 --- a/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts +++ b/apps/cowswap-frontend/src/legacy/state/swap/TradeGp.ts @@ -1,6 +1,6 @@ import { ONE_FRACTION } from '@cowprotocol/common-const' import { CanonicalMarketParams, getCanonicalMarket } from '@cowprotocol/common-utils' -import { CurrencyAmount, Currency, TradeType, Price, Percent } from '@uniswap/sdk-core' +import { Currency, CurrencyAmount, Percent, Price, TradeType } from '@uniswap/sdk-core' interface PriceInformation { token: string @@ -94,7 +94,7 @@ export default class TradeGp { * The output amount for the trade assuming no slippage. */ readonly outputAmount: CurrencyAmount - readonly outputAmountWithoutFee?: CurrencyAmount + readonly outputAmountWithoutFee: CurrencyAmount /** * Trade fee */ diff --git a/apps/cowswap-frontend/src/mocks/tradeStateMock.ts b/apps/cowswap-frontend/src/mocks/tradeStateMock.ts index 84523caefd..20d5b09ac3 100644 --- a/apps/cowswap-frontend/src/mocks/tradeStateMock.ts +++ b/apps/cowswap-frontend/src/mocks/tradeStateMock.ts @@ -50,7 +50,6 @@ export const outputCurrencyInfoMock: CurrencyInfo = { } export const tradeContextMock: TradeFlowContext = { - hasEnoughAllowance: undefined, permitInfo: undefined, postOrderParams: { class: OrderClass.LIMIT, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts index 7d0f090eb3..f049ef4600 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts @@ -37,7 +37,7 @@ export function useTradeFlowContext(): TradeFlowContext | null { const permitInfo = useIsTokenPermittable(state.inputCurrency, TradeType.LIMIT_ORDER) const checkAllowanceAddress = GP_VAULT_RELAYER[chainId] - const { enoughAllowance: hasEnoughAllowance } = useEnoughBalanceAndAllowance({ + const { enoughAllowance } = useEnoughBalanceAndAllowance({ account, amount: state.slippageAdjustedSellAmount || undefined, checkAllowanceAddress, @@ -75,8 +75,7 @@ export function useTradeFlowContext(): TradeFlowContext | null { dispatch, provider, rateImpact, - permitInfo, - hasEnoughAllowance, + permitInfo: !enoughAllowance ? permitInfo : undefined, postOrderParams: { class: OrderClass.LIMIT, kind: state.orderKind, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx index 2a71f011a8..68a605eb1f 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx @@ -16,7 +16,6 @@ const inputCurrency = COW[SupportedChainId.MAINNET] const outputCurrency = GNO[SupportedChainId.MAINNET] const tradeContext: TradeFlowContext = { - hasEnoughAllowance: undefined, permitInfo: undefined, postOrderParams: { class: OrderClass.LIMIT, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts index b61ef7ffc8..d79a2008ba 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts @@ -29,7 +29,6 @@ export async function tradeFlow( permitInfo, provider, chainId, - hasEnoughAllowance, allowsOffchainSigning, settlementContract, dispatch, @@ -58,7 +57,6 @@ export async function tradeFlow( logTradeFlow('LIMIT ORDER FLOW', 'STEP 2: handle permit') postOrderParams.appData = await handlePermit({ permitInfo, - hasEnoughAllowance, inputToken: sellToken, provider, account, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts index 2c88ed15d9..2c55f9e369 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts @@ -6,7 +6,7 @@ import SafeAppsSDK from '@safe-global/safe-apps-sdk' import { AppDispatch } from 'legacy/state' import { PostOrderParams } from 'legacy/utils/trade' -import { PermitInfo } from 'modules/permit' +import { IsTokenPermittableResult } from 'modules/permit' export interface TradeFlowContext { // signer changes creates redundant re-renders @@ -19,8 +19,7 @@ export interface TradeFlowContext { provider: Web3Provider allowsOffchainSigning: boolean isGnosisSafeWallet: boolean - permitInfo: PermitInfo | undefined - hasEnoughAllowance: boolean | undefined + permitInfo: IsTokenPermittableResult } export interface SafeBundleFlowContext extends TradeFlowContext { diff --git a/apps/cowswap-frontend/src/modules/permit/index.ts b/apps/cowswap-frontend/src/modules/permit/index.ts index ef487d8884..6906fa3831 100644 --- a/apps/cowswap-frontend/src/modules/permit/index.ts +++ b/apps/cowswap-frontend/src/modules/permit/index.ts @@ -1,5 +1,5 @@ export { useAccountAgnosticPermitHookData } from './hooks/useAccountAgnosticPermitHookData' export { generatePermitHook } from './utils/generatePermitHook' export { useIsTokenPermittable } from './hooks/useIsTokenPermittable' -export { handlePermit } from './utils/handlePermit' +export * from './utils/handlePermit' export * from './types' diff --git a/apps/cowswap-frontend/src/modules/permit/types.ts b/apps/cowswap-frontend/src/modules/permit/types.ts index f0eaa79a7f..9017f2bfb2 100644 --- a/apps/cowswap-frontend/src/modules/permit/types.ts +++ b/apps/cowswap-frontend/src/modules/permit/types.ts @@ -36,7 +36,6 @@ export type PermitHookParams = { export type HandlePermitParams = Omit & { permitInfo: IsTokenPermittableResult - hasEnoughAllowance: undefined | boolean appData: AppDataInfo } diff --git a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts index 5f2d37ba91..e623fd8ec3 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts @@ -1,5 +1,8 @@ import { AppDataInfo, buildAppDataHooks, updateHooksOnAppData } from 'modules/appData' -import { generatePermitHook, HandlePermitParams } from 'modules/permit' + +import { generatePermitHook } from './generatePermitHook' + +import { HandlePermitParams } from '../types' /** * Handle token permit @@ -12,12 +15,11 @@ import { generatePermitHook, HandlePermitParams } from 'modules/permit' * Returns the updated appData */ export async function handlePermit(params: HandlePermitParams): Promise { - const { permitInfo, hasEnoughAllowance, inputToken, provider, account, chainId, appData } = params + const { permitInfo, inputToken, provider, account, chainId, appData } = params - if (permitInfo && !hasEnoughAllowance) { - // If token is permittable and there's not enough allowance, get the permit hook + if (permitInfo) { + // permitInfo will only be set if there's enough allowance - // TODO: maybe we need a modal to inform the user what they need to sign? const permitData = await generatePermitHook({ inputToken, provider, diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapConfirmManager.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapConfirmManager.ts index d771262739..0ba4f9b23c 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapConfirmManager.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapConfirmManager.ts @@ -1,75 +1,113 @@ -import { useAtom } from 'jotai' +import { useSetAtom } from 'jotai' import { useMemo } from 'react' import TradeGp from 'legacy/state/swap/TradeGp' import { useExpertModeManager } from 'legacy/state/user/hooks' -import { swapConfirmAtom } from 'modules/swap/state/swapConfirmAtom' +import { swapConfirmAtom, SwapConfirmState } from 'modules/swap/state/swapConfirmAtom' export interface SwapConfirmManager { setSwapError(swapErrorMessage: string): void - openSwapConfirmModal(tradeToConfirm: TradeGp): void + openSwapConfirmModal(tradeToConfirm: TradeGp, needsPermitSignature?: boolean): void acceptRateUpdates(tradeToConfirm: TradeGp): void closeSwapConfirm(): void sendTransaction(tradeToConfirm: TradeGp): void transactionSent(txHash: string): void + requestPermitSignature(): void + permitSigned(): void } export function useSwapConfirmManager(): SwapConfirmManager { - const [swapConfirmState, setSwapConfirmState] = useAtom(swapConfirmAtom) + const setSwapConfirmState = useSetAtom(swapConfirmAtom) const [isExpertMode] = useExpertModeManager() return useMemo( () => ({ setSwapError(swapErrorMessage: string) { - const state = { ...swapConfirmState, swapErrorMessage } - console.debug('[Swap confirm state] setSwapError: ', state) - setSwapConfirmState(state) + setSwapConfirmState((prev) => { + const state = { ...prev, swapErrorMessage, attemptingTxn: false, permitSignatureState: undefined } + console.debug('[Swap confirm state] setSwapError: ', state) + return state + }) }, openSwapConfirmModal(tradeToConfirm: TradeGp) { - const state = { + const state: SwapConfirmState = { tradeToConfirm, attemptingTxn: false, swapErrorMessage: undefined, showConfirm: true, txHash: undefined, + permitSignatureState: undefined, } console.debug('[Swap confirm state] openSwapConfirmModal: ', state) setSwapConfirmState(state) }, acceptRateUpdates(tradeToConfirm: TradeGp) { - const state = { ...swapConfirmState, tradeToConfirm } - console.debug('[Swap confirm state] acceptRateUpdates: ', state) - setSwapConfirmState(state) + setSwapConfirmState((prev) => { + const state = { ...prev, tradeToConfirm } + console.debug('[Swap confirm state] acceptRateUpdates: ', state) + return state + }) + }, + requestPermitSignature() { + setSwapConfirmState((prev) => { + const state: SwapConfirmState = { ...prev, permitSignatureState: 'requested' } + console.debug('[Swap confirm state] requestPermitSignature: ', state) + return state + }) + }, + permitSigned() { + setSwapConfirmState((prev) => { + // Move to `signed` state only if previous state was `requested` - which means the order is using the permit + // Set to `undefined` otherwise + const permitSignatureState = prev.permitSignatureState === 'requested' ? 'signed' : undefined + + const state: SwapConfirmState = { + ...prev, + permitSignatureState, + } + + console.debug('[Swap confirm state] permitSigned: ', state) + + return state + }) }, closeSwapConfirm() { - const state = { ...swapConfirmState, showConfirm: false } - console.debug('[Swap confirm state] closeSwapConfirm: ', state) - setSwapConfirmState(state) + setSwapConfirmState((prev) => { + const state = { ...prev, showConfirm: false, permitSignatureState: undefined } + console.debug('[Swap confirm state] closeSwapConfirm: ', state) + return state + }) }, sendTransaction(tradeToConfirm: TradeGp) { - const state = { - tradeToConfirm, - attemptingTxn: true, - swapErrorMessage: undefined, - showConfirm: true, - txHash: undefined, - } - console.debug('[Swap confirm state] sendTransaction: ', state) - setSwapConfirmState(state) + setSwapConfirmState((prev) => { + const state = { + ...prev, + tradeToConfirm, + attemptingTxn: true, + swapErrorMessage: undefined, + showConfirm: true, + txHash: undefined, + } + console.debug('[Swap confirm state] sendTransaction: ', state) + return state + }) }, transactionSent(txHash: string) { - const state = { - ...swapConfirmState, - attemptingTxn: false, - swapErrorMessage: undefined, - showConfirm: !isExpertMode, - txHash, - } - console.debug('[Swap confirm state] transactionSent: ', state) - setSwapConfirmState(state) + setSwapConfirmState((prev) => { + const state = { + ...prev, + attemptingTxn: false, + swapErrorMessage: undefined, + showConfirm: !isExpertMode, + txHash, + permitSignatureState: undefined, + } + console.debug('[Swap confirm state] transactionSent: ', state) + return state + }) }, }), - [swapConfirmState, setSwapConfirmState, isExpertMode] + [setSwapConfirmState, isExpertMode] ) } diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts index 85003357ad..f2c1329a80 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts @@ -16,7 +16,7 @@ export function useSwapFlowContext(): SwapFlowContext | null { const permitInfo = useIsTokenPermittable(sellCurrency, TradeType.SWAP) const checkAllowanceAddress = GP_VAULT_RELAYER[baseProps.chainId || SupportedChainId.MAINNET] - const { enoughAllowance: hasEnoughAllowance } = useEnoughBalanceAndAllowance({ + const { enoughAllowance } = useEnoughBalanceAndAllowance({ account: baseProps.account, amount: baseProps.inputAmountWithSlippage, checkAllowanceAddress, @@ -35,7 +35,6 @@ export function useSwapFlowContext(): SwapFlowContext | null { return { ...baseContext, contract, - permitInfo, - hasEnoughAllowance, + permitInfo: !enoughAllowance ? permitInfo : undefined, } } diff --git a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx index c1829a6e1b..8605cc9de6 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/SwapButtons/index.tsx @@ -3,7 +3,7 @@ import React, { ReactNode } from 'react' import { GpEther } from '@cowprotocol/common-const' import { genericPropsChecker } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' -import { ButtonSize, TokenSymbol, ButtonError, ButtonPrimary, AutoRow } from '@cowprotocol/ui' +import { AutoRow, ButtonError, ButtonPrimary, ButtonSize, TokenSymbol } from '@cowprotocol/ui' import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' import { Trans } from '@lingui/macro' diff --git a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts index 98de4a2c54..326f3889ed 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts @@ -27,9 +27,10 @@ export async function swapFlow( try { logTradeFlow('SWAP FLOW', 'STEP 2: handle permit') + if (input.permitInfo) input.swapConfirmManager.requestPermitSignature() + input.orderParams.appData = await handlePermit({ appData: input.orderParams.appData, - hasEnoughAllowance: input.hasEnoughAllowance, inputToken: input.context.trade.inputAmount.currency as Token, provider: input.orderParams.signer.provider as Web3Provider, @@ -37,6 +38,7 @@ export async function swapFlow( chainId: input.orderParams.chainId, permitInfo: input.permitInfo, }) + input.swapConfirmManager.permitSigned() logTradeFlow('SWAP FLOW', 'STEP 3: send transaction') tradeFlowAnalytics.trade(input.swapFlowAnalyticsContext) diff --git a/apps/cowswap-frontend/src/modules/swap/services/types.ts b/apps/cowswap-frontend/src/modules/swap/services/types.ts index 0b09b45fe1..6417e077aa 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/types.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/types.ts @@ -1,5 +1,4 @@ -import { GPv2Settlement, CoWSwapEthFlow } from '@cowprotocol/abis' -import { Erc20, Weth } from '@cowprotocol/abis' +import { CoWSwapEthFlow, Erc20, GPv2Settlement, Weth } from '@cowprotocol/abis' import { Web3Provider } from '@ethersproject/providers' import SafeAppsSDK from '@safe-global/safe-apps-sdk' import { Currency, CurrencyAmount } from '@uniswap/sdk-core' @@ -46,7 +45,6 @@ export interface BaseFlowContext { export type SwapFlowContext = BaseFlowContext & { contract: GPv2Settlement permitInfo: IsTokenPermittableResult - hasEnoughAllowance: boolean | undefined } export type EthFlowContext = BaseFlowContext & { diff --git a/apps/cowswap-frontend/src/modules/swap/state/swapConfirmAtom.ts b/apps/cowswap-frontend/src/modules/swap/state/swapConfirmAtom.ts index c69a80f056..0bd8d19589 100644 --- a/apps/cowswap-frontend/src/modules/swap/state/swapConfirmAtom.ts +++ b/apps/cowswap-frontend/src/modules/swap/state/swapConfirmAtom.ts @@ -8,6 +8,7 @@ export interface SwapConfirmState { attemptingTxn: boolean swapErrorMessage: string | undefined txHash: string | undefined + permitSignatureState: undefined | 'requested' | 'signed' } export const swapConfirmAtom = atom({ @@ -16,4 +17,5 @@ export const swapConfirmAtom = atom({ attemptingTxn: false, swapErrorMessage: undefined, txHash: undefined, + permitSignatureState: undefined, }) diff --git a/libs/ui/src/pure/TokenAmount/index.tsx b/libs/ui/src/pure/TokenAmount/index.tsx index 6046121b82..c6e9917427 100644 --- a/libs/ui/src/pure/TokenAmount/index.tsx +++ b/libs/ui/src/pure/TokenAmount/index.tsx @@ -1,6 +1,5 @@ import { LONG_PRECISION } from '@cowprotocol/common-const' -import { formatTokenAmount, FractionUtils } from '@cowprotocol/common-utils' -import { FeatureFlag } from '@cowprotocol/common-utils' +import { FeatureFlag, formatTokenAmount, FractionUtils } from '@cowprotocol/common-utils' import { darken, transparentize } from 'polished' import styled from 'styled-components' @@ -22,7 +21,7 @@ export const SymbolElement = styled.span<{ opacitySymbol?: boolean }>` export interface TokenAmountProps { amount: Nullish defaultValue?: string - tokenSymbol?: Nullish + tokenSymbol?: TokenSymbolProps['token'] className?: string hideTokenSymbol?: boolean round?: boolean diff --git a/package.json b/package.json index 87f4ad382b..7ac20597d8 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "start": "nx run cowswap-frontend:serve", "preview": "cross-env NODE_OPTIONS=--max-old-space-size=32768 nx run cowswap-frontend:preview", "cosmos:export": "cross-env NODE_OPTIONS=--max-old-space-size=32768 nx run cowswap-frontend:cosmos:export", + "cosmos": "nx run cowswap-frontend:cosmos:run", "test": "nx run-many -t test --output-style=stream", "e2e": "nx run-many -t e2e", "lint": "nx run-many -t lint", From 70e56534eaa17456e42e2ba30541537e44d76c78 Mon Sep 17 00:00:00 2001 From: Leandro Date: Thu, 5 Oct 2023 02:36:17 -0700 Subject: [PATCH 29/36] feat(permit): modals LIMIT (#3164) * chore: turn permit on for LIMIT * fix: typo * refactor: beforeTrade is always set * refactor: optimize/refactor derived atoms * feat: add permitSignatureState and setPermitSignatureRequestedTradeConfirmAtom * feat: add requestPermitSignature action * refactor: extract buildTradeAmounts local fn * feat: add beforePermit to limitOrders tradeFlow * feat: show PermitModal for LIMIT * feat: fix new cow modal styles (#3177) * feat: fix new cow modal styles * feat: fix new cow modal styles * feat: fix new cow modal styles --------- Co-authored-by: Michel * chore: add order type to PermitModal * refactor: clean up TradeConfirmalModal * fix: pass along PermitModal props to Pure component * chore: remove comment about backend PR, which has been merged --------- Co-authored-by: fairlight <31534717+fairlighteth@users.noreply.github.com> Co-authored-by: Michel --- .../src/common/constants/theme.ts | 1 + .../src/common/pure/Modal/index.tsx | 6 + .../src/common/pure/Modal/styled.tsx | 1 + .../src/common/pure/NewModal/index.tsx | 44 +++---- .../common/pure/PermitModal/index.cosmos.tsx | 46 ++++++- .../src/common/pure/PermitModal/index.tsx | 9 +- .../TransactionConfirmationModal/index.tsx | 1 + .../src/legacy/theme/baseTheme.tsx | 1 + .../hooks/useHandleOrderPlacement.test.ts | 3 + .../hooks/useHandleOrderPlacement.ts | 26 ++-- .../limitOrders/services/tradeFlow/index.ts | 8 +- .../src/modules/permit/const.ts | 2 +- .../containers/TradeConfirmModal/index.tsx | 112 +++++++++++++----- .../trade/hooks/useTradeConfirmActions.ts | 10 +- .../trade/state/tradeConfirmStateAtom.ts | 76 ++++++------ 15 files changed, 236 insertions(+), 110 deletions(-) diff --git a/apps/cowswap-frontend/src/common/constants/theme.ts b/apps/cowswap-frontend/src/common/constants/theme.ts index 3fb31faf81..6f4442824d 100644 --- a/apps/cowswap-frontend/src/common/constants/theme.ts +++ b/apps/cowswap-frontend/src/common/constants/theme.ts @@ -24,6 +24,7 @@ export enum UI { // Icons ICON_SIZE_NORMAL = '--cow-icon-size-normal', + ICON_SIZE_LARGE = '--cow-icon-size-large', ICON_COLOR_NORMAL = '--cow-icon-color-normal', // States diff --git a/apps/cowswap-frontend/src/common/pure/Modal/index.tsx b/apps/cowswap-frontend/src/common/pure/Modal/index.tsx index 6bc9d7681c..bc01d75991 100644 --- a/apps/cowswap-frontend/src/common/pure/Modal/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/Modal/index.tsx @@ -105,6 +105,7 @@ export const CowModal = styled(Modal)<{ transition: max-width 0.4s ease; background-color: var(${UI.COLOR_CONTAINER_BG_01}); overflow: hidden; + border-radius: var(${UI.BORDER_RADIUS_NORMAL}); ${({ theme }) => theme.mediaWidth.upToSmall` max-height: 100vh; @@ -146,3 +147,8 @@ export const CowModal = styled(Modal)<{ } } ` + +export const NewCowModal = styled(Modal)` + width: 100vw; + height: 100vh; +` \ No newline at end of file diff --git a/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx b/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx index 486755c464..a6e8b4e8e7 100644 --- a/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx +++ b/apps/cowswap-frontend/src/common/pure/Modal/styled.tsx @@ -59,6 +59,7 @@ export const StyledDialogOverlay = styled(AnimatedDialogOverlay)` justify-content: center; background-color: ${({ theme }) => theme.modalBG}; + backdrop-filter: blur(5px); } ` diff --git a/apps/cowswap-frontend/src/common/pure/NewModal/index.tsx b/apps/cowswap-frontend/src/common/pure/NewModal/index.tsx index cab27ecbed..090f5b9e5d 100644 --- a/apps/cowswap-frontend/src/common/pure/NewModal/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/NewModal/index.tsx @@ -12,27 +12,28 @@ const ModalInner = styled.div` width: 100%; height: auto; margin: auto; + background: transparent; + padding: 0; + position: relative; +` + +const Wrapper = styled.div<{ maxWidth?: number | string; minHeight?: number | string }>` + display: flex; + width: 100%; + height: 100%; + margin: auto; + overflow-y: auto; background: var(${UI.COLOR_CONTAINER_BG_01}); border-radius: var(${UI.BORDER_RADIUS_NORMAL}); box-shadow: var(${UI.BOX_SHADOW_NORMAL}); - padding: 0; ${({ theme }) => theme.mediaWidth.upToSmall` - margin: 8vh 0 0; + margin: 0; border-radius: 0; border-top-left-radius: var(${UI.BORDER_RADIUS_NORMAL}); border-top-right-radius: var(${UI.BORDER_RADIUS_NORMAL}); box-shadow: none; `} -` - -const Wrapper = styled.div<{ maxWidth?: number | string; minHeight?: number | string }>` - display: flex; - width: 100%; - height: 100%; - margin: auto; - background: var(${UI.MODAL_BACKDROP}); - overflow-y: auto; ${ModalInner} { max-width: ${({ maxWidth }) => (maxWidth ? `${maxWidth}px` : '100%')}; @@ -40,8 +41,7 @@ const Wrapper = styled.div<{ maxWidth?: number | string; minHeight?: number | st ${({ theme }) => theme.mediaWidth.upToSmall` max-width: 100%; - min-height: initial; - height: auto; + height: 100%; `} } ` @@ -62,18 +62,18 @@ const Heading = styled.h2` ` const IconX = styled.div` - position: fixed; - top: 18px; - right: 18px; + position: absolute; + top: 16px; + right: 10px; cursor: pointer; - opacity: 0.6; + opacity: 0.7; transition: opacity 0.2s ease-in-out; margin: 0 0 0 auto; > svg { width: var(${UI.ICON_SIZE_NORMAL}); height: var(${UI.ICON_SIZE_NORMAL}); - fill: var(${UI.ICON_COLOR_NORMAL}); + color: var(${UI.ICON_COLOR_NORMAL}); } &:hover { @@ -152,12 +152,12 @@ export function NewModal({ maxWidth = 450, minHeight = 450, title, children, onD {title && {title}} + onDismiss && onDismiss()}> + + + {children} - - onDismiss && onDismiss()}> - - ) } diff --git a/apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx b/apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx index 0c2f775874..c209c2aea0 100644 --- a/apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/common/pure/PermitModal/index.cosmos.tsx @@ -23,25 +23,59 @@ const WALLET_ICON = ( ) const PermitModalFixtures = { - 'Pending permit signature': ( + 'SWAP: Pending permit signature': ( - + ), - 'Pending order signature': ( + 'SWAP: Pending order signature': ( - + + + ), + 'LIMIT: Pending permit signature': ( + + + + ), + 'LIMIT: Pending order signature': ( + + ), // These two cases should happen, but including for completeness as the parameters allow it 'Missing amounts on approve': ( - + ), 'Missing amounts on submit': ( - + ), } diff --git a/apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx b/apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx index 572e8091b6..0157dacdc9 100644 --- a/apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx +++ b/apps/cowswap-frontend/src/common/pure/PermitModal/index.tsx @@ -17,6 +17,7 @@ export type PermitModalProps = NewModalProps & { inputAmount: Nullish> outputAmount: Nullish> step: 'approve' | 'submit' + orderType: 'Swap' | 'Limit Order' icon?: React.ReactNode } @@ -25,7 +26,7 @@ export type PermitModalProps = NewModalProps & { * This is the pure component for cosmos */ export function PermitModal(props: PermitModalProps) { - const { inputAmount, outputAmount, step, icon: inputIcon } = props + const { inputAmount, outputAmount, step, icon: inputIcon, orderType, ...rest } = props const steps: StepProps[] = useMemo( () => [ @@ -56,9 +57,9 @@ export function PermitModal(props: PermitModalProps) { on CoW Swap ) : ( - 'Confirm Swap' + `Confirm ${orderType}` ), - [inputAmount?.currency, step] + [inputAmount?.currency, orderType, step] ) const body = useMemo( @@ -73,7 +74,7 @@ export function PermitModal(props: PermitModalProps) { ) return ( - + {icon} diff --git a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx index 18a87ea32e..76dbd956da 100644 --- a/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/TransactionConfirmationModal/index.tsx @@ -83,6 +83,7 @@ export function TransactionConfirmationModal({ inputAmount={tradeAmounts?.inputAmount} outputAmount={tradeAmounts?.outputAmount} step={swapConfirmState?.permitSignatureState === 'signed' ? 'submit' : 'approve'} + orderType={'Swap'} /> ) : attemptingTxn ? ( { diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.ts index fed0708c3b..7cdf093500 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useHandleOrderPlacement.ts @@ -1,5 +1,4 @@ -import { useAtom } from 'jotai' -import { useSetAtom } from 'jotai' +import { useAtom, useSetAtom } from 'jotai' import { useCallback } from 'react' import { PriceImpact } from 'legacy/hooks/usePriceImpact' @@ -31,15 +30,16 @@ export function useHandleOrderPlacement( const safeBundleFlowContext = useSafeBundleFlowContext(tradeContext) const isSafeBundle = useIsSafeApprovalBundle(tradeContext?.postOrderParams.inputAmount) - const beforeTrade = useCallback(() => { + const beforePermit = useCallback(() => { if (!tradeContext) return - const tradeAmounts: TradeAmounts = { - inputAmount: tradeContext.postOrderParams.inputAmount, - outputAmount: tradeContext.postOrderParams.outputAmount, - } + tradeConfirmActions.requestPermitSignature(buildTradeAmounts(tradeContext)) + }, [tradeConfirmActions, tradeContext]) - tradeConfirmActions.onSign(tradeAmounts) + const beforeTrade = useCallback(() => { + if (!tradeContext) return + + tradeConfirmActions.onSign(buildTradeAmounts(tradeContext)) }, [tradeContext, tradeConfirmActions]) const tradeFn = useCallback(async () => { @@ -63,8 +63,9 @@ export function useHandleOrderPlacement( tradeContext.postOrderParams.partiallyFillable = partiallyFillableOverride ?? tradeContext.postOrderParams.partiallyFillable - return tradeFlow(tradeContext, priceImpact, settingsState, confirmPriceImpactWithoutFee, beforeTrade) + return tradeFlow(tradeContext, priceImpact, settingsState, confirmPriceImpactWithoutFee, beforePermit, beforeTrade) }, [ + beforePermit, beforeTrade, confirmPriceImpactWithoutFee, isSafeBundle, @@ -95,3 +96,10 @@ export function useHandleOrderPlacement( }) }, [tradeFn, tradeConfirmActions, updateLimitOrdersState, setPartiallyFillableOverride]) } + +function buildTradeAmounts(tradeContext: TradeFlowContext): TradeAmounts { + return { + inputAmount: tradeContext.postOrderParams.inputAmount, + outputAmount: tradeContext.postOrderParams.outputAmount, + } +} diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts index d79a2008ba..b2ff0d36a4 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts @@ -21,7 +21,8 @@ export async function tradeFlow( priceImpact: PriceImpact, settingsState: LimitOrdersSettingsState, confirmPriceImpactWithoutFee: (priceImpact: Percent) => Promise, - beforeTrade?: () => void + beforePermit: () => void, + beforeTrade: () => void ): Promise { const { postOrderParams, @@ -55,6 +56,8 @@ export async function tradeFlow( try { logTradeFlow('LIMIT ORDER FLOW', 'STEP 2: handle permit') + if (permitInfo) beforePermit() + postOrderParams.appData = await handlePermit({ permitInfo, inputToken: sellToken, @@ -66,7 +69,8 @@ export async function tradeFlow( logTradeFlow('LIMIT ORDER FLOW', 'STEP 3: send transaction') tradeFlowAnalytics.trade(swapFlowAnalyticsContext) - beforeTrade?.() + + beforeTrade() logTradeFlow('LIMIT ORDER FLOW', 'STEP 4: sign and post order') const { id: orderId, order } = await signAndPostOrder({ diff --git a/apps/cowswap-frontend/src/modules/permit/const.ts b/apps/cowswap-frontend/src/modules/permit/const.ts index 81f276485a..eeb9b673d0 100644 --- a/apps/cowswap-frontend/src/modules/permit/const.ts +++ b/apps/cowswap-frontend/src/modules/permit/const.ts @@ -26,6 +26,6 @@ export const DEFAULT_PERMIT_DURATION = ms`5 years` export const ORDER_TYPE_SUPPORTS_PERMIT: Record = { [TradeType.SWAP]: true, - [TradeType.LIMIT_ORDER]: false, + [TradeType.LIMIT_ORDER]: true, [TradeType.ADVANCED_ORDERS]: false, } diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx index 82857f2357..4d6e9c4fd3 100644 --- a/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx +++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeConfirmModal/index.tsx @@ -1,10 +1,13 @@ import { useAtomValue } from 'jotai' +import { SupportedChainId } from '@cowprotocol/cow-sdk' import { useIsSafeWallet, useWalletInfo } from '@cowprotocol/wallet' -import { CowModal } from 'common/pure/Modal' +import { PermitModal } from 'common/containers/PermitModal' +import { CowModal, NewCowModal } from 'common/pure/Modal' import { OrderSubmittedContent } from 'common/pure/OrderSubmittedContent' import { TransactionErrorContent } from 'common/pure/TransactionErrorContent' +import { TradeAmounts } from 'common/types' import { TradeConfirmPendingContent } from './TradeConfirmPendingContent' @@ -20,37 +23,90 @@ export function TradeConfirmModal(props: TradeConfirmModalProps) { const { chainId, account } = useWalletInfo() const isSafeWallet = useIsSafeWallet() - const { isOpen, pendingTrade, transactionHash, error } = useAtomValue(tradeConfirmStateAtom) + const { isOpen, permitSignatureState, pendingTrade, transactionHash, error } = useAtomValue(tradeConfirmStateAtom) const { onDismiss } = useTradeConfirmActions() if (!account) return null + const Modal = permitSignatureState ? NewCowModal : CowModal + return ( - - {(() => { - if (error) { - return - } - - if (pendingTrade) { - return - } - - // TODO: use for Swap - if (transactionHash) { - return ( - - ) - } - - return children - })()} - + + + {children} + + ) } + +type InnerComponentProps = { + children: JSX.Element + chainId: SupportedChainId + account: string + error: string | null + pendingTrade: TradeAmounts | null + transactionHash: string | null + onDismiss: () => void + permitSignatureState: string | undefined + isSafeWallet: boolean +} + +function InnerComponent(props: InnerComponentProps) { + const { + account, + chainId, + children, + error, + isSafeWallet, + onDismiss, + pendingTrade, + permitSignatureState, + transactionHash, + } = props + + if (error) { + return + } + + if (pendingTrade && permitSignatureState) { + // TODO: potentially replace TradeConfirmPendingContent completely with PermitModal + // We could use this not just for permit, but for any token, even already approved + const step = permitSignatureState === 'signed' ? 'submit' : 'approve' + return ( + + ) + } + + if (pendingTrade) { + return + } + + if (transactionHash) { + return ( + + ) + } + + return children +} diff --git a/apps/cowswap-frontend/src/modules/trade/hooks/useTradeConfirmActions.ts b/apps/cowswap-frontend/src/modules/trade/hooks/useTradeConfirmActions.ts index 1fa198cf14..867269f267 100644 --- a/apps/cowswap-frontend/src/modules/trade/hooks/useTradeConfirmActions.ts +++ b/apps/cowswap-frontend/src/modules/trade/hooks/useTradeConfirmActions.ts @@ -7,6 +7,7 @@ import { setErrorTradeConfirmAtom, setOpenTradeConfirmAtom, setPendingTradeConfirmAtom, + setPermitSignatureRequestedTradeConfirmAtom, setTxHashTradeConfirmAtom, } from '../state/tradeConfirmStateAtom' @@ -15,15 +16,17 @@ export interface TradeConfirmActions { onError(error: string): void onSuccess(transactionHash: string): void onOpen(): void + requestPermitSignature(pendingTrade: TradeAmounts): void onDismiss(): void } export function useTradeConfirmActions(): TradeConfirmActions { - const setOpenTradeConfim = useSetAtom(setOpenTradeConfirmAtom) + const setOpenTradeConfirm = useSetAtom(setOpenTradeConfirmAtom) const setCloseTradeConfirm = useSetAtom(setCloseTradeConfirmAtom) const setErrorTradeConfirm = useSetAtom(setErrorTradeConfirmAtom) const setPendingTradeConfirm = useSetAtom(setPendingTradeConfirmAtom) const setTxHashTradeConfirm = useSetAtom(setTxHashTradeConfirmAtom) + const setPermitSignatureRequested = useSetAtom(setPermitSignatureRequestedTradeConfirmAtom) return { onSign(pendingTrade: TradeAmounts) { @@ -36,7 +39,10 @@ export function useTradeConfirmActions(): TradeConfirmActions { setTxHashTradeConfirm(transactionHash) }, onOpen() { - setOpenTradeConfim() + setOpenTradeConfirm() + }, + requestPermitSignature(pendingTrade: TradeAmounts) { + setPermitSignatureRequested(pendingTrade) }, onDismiss() { setCloseTradeConfirm() diff --git a/apps/cowswap-frontend/src/modules/trade/state/tradeConfirmStateAtom.ts b/apps/cowswap-frontend/src/modules/trade/state/tradeConfirmStateAtom.ts index f2a06240e5..9e34917f6b 100644 --- a/apps/cowswap-frontend/src/modules/trade/state/tradeConfirmStateAtom.ts +++ b/apps/cowswap-frontend/src/modules/trade/state/tradeConfirmStateAtom.ts @@ -7,6 +7,7 @@ interface TradeConfirmModalState { pendingTrade: TradeAmounts | null transactionHash: string | null error: string | null + permitSignatureState: undefined | 'requested' | 'signed' } export const tradeConfirmStateAtom = atom({ @@ -14,63 +15,66 @@ export const tradeConfirmStateAtom = atom({ pendingTrade: null, transactionHash: null, error: null, + permitSignatureState: undefined, }) export const setOpenTradeConfirmAtom = atom(null, (get, set) => { - set(tradeConfirmStateAtom, () => { - return { - isOpen: true, - error: null, - pendingTrade: null, - transactionHash: null, - } - }) + set(tradeConfirmStateAtom, () => ({ + isOpen: true, + error: null, + pendingTrade: null, + transactionHash: null, + permitSignatureState: undefined, + })) }) export const setCloseTradeConfirmAtom = atom(null, (get, set) => { - set(tradeConfirmStateAtom, () => { - return { - ...get(tradeConfirmStateAtom), - isOpen: false, - } - }) + set(tradeConfirmStateAtom, () => ({ + ...get(tradeConfirmStateAtom), + isOpen: false, + permitSignatureState: undefined, + })) }) export const setErrorTradeConfirmAtom = atom(null, (get, set, error: string) => { - set(tradeConfirmStateAtom, () => { - const currentState = get(tradeConfirmStateAtom) + set(tradeConfirmStateAtom, () => ({ + ...get(tradeConfirmStateAtom), + error, + pendingTrade: null, + transactionHash: null, + permitSignatureState: undefined, + })) +}) - return { - isOpen: currentState.isOpen, - error, - pendingTrade: null, - transactionHash: null, - } - }) +export const setPermitSignatureRequestedTradeConfirmAtom = atom(null, (get, set, pendingTrade: TradeAmounts) => { + set(tradeConfirmStateAtom, () => ({ + ...get(tradeConfirmStateAtom), + pendingTrade, + permitSignatureState: 'requested', + })) }) export const setPendingTradeConfirmAtom = atom(null, (get, set, pendingTrade: TradeAmounts) => { - set(tradeConfirmStateAtom, () => { - const currentState = get(tradeConfirmStateAtom) + const currentState = get(tradeConfirmStateAtom) + set(tradeConfirmStateAtom, () => { return { - isOpen: currentState.isOpen, + ...currentState, error: null, pendingTrade, transactionHash: null, + // Only move to the next state if coming in the right sequence. + // Otherwise, reset it + permitSignatureState: currentState.permitSignatureState === 'requested' ? 'signed' : undefined, } }) }) export const setTxHashTradeConfirmAtom = atom(null, (get, set, transactionHash: string) => { - set(tradeConfirmStateAtom, () => { - const currentState = get(tradeConfirmStateAtom) - - return { - isOpen: currentState.isOpen, - error: null, - pendingTrade: null, - transactionHash, - } - }) + set(tradeConfirmStateAtom, () => ({ + ...get(tradeConfirmStateAtom), + error: null, + pendingTrade: null, + transactionHash, + })) }) From e902e36d6d6320dfa1649a448a834df49f115ce4 Mon Sep 17 00:00:00 2001 From: Leandro Date: Thu, 5 Oct 2023 08:33:26 -0700 Subject: [PATCH 30/36] feat(permit): refactor permit caching (#3183) * refactor: move permit/state/atoms.ts to permittableTokensAtom.ts * feat: add permitCacheAtoms * feat: add useGeneratePermitHook * feat: remove localStorage caching from generatePermitHook * feat: replace generatePermitHook with useGeneratePermitHook * test: update unit tests * refactor: export * from permit hooks rather than individual exports * chore: throw when permitData cannot be generated by generatePermitHook * chore: fix comment * refactor: there's no need to pass an extra preFetchedNonce param * refactor: create curried fn to avoid repetition --- .../src/mocks/tradeStateMock.ts | 1 + .../limitOrders/hooks/useTradeFlowContext.ts | 4 +- .../pure/LimitOrdersDetails/index.cosmos.tsx | 1 + .../limitOrders/services/tradeFlow/index.ts | 4 +- .../src/modules/limitOrders/services/types.ts | 3 +- .../hooks/useAccountAgnosticPermitHookData.ts | 22 ++-- .../permit/hooks/useGeneratePermitHook.ts | 59 ++++++++++ .../permit/hooks/useIsTokenPermittable.ts | 2 +- .../src/modules/permit/index.ts | 6 +- .../modules/permit/state/permitCacheAtom.ts | 106 ++++++++++++++++++ .../{atoms.ts => permittableTokensAtom.ts} | 0 .../src/modules/permit/types.ts | 29 ++++- .../permit/utils/generatePermitHook.ts | 80 +------------ .../src/modules/permit/utils/handlePermit.ts | 12 +- .../modules/swap/hooks/useSwapFlowContext.ts | 4 +- .../modules/swap/services/swapFlow/index.ts | 5 +- .../src/modules/swap/services/types.ts | 3 +- 17 files changed, 229 insertions(+), 112 deletions(-) create mode 100644 apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/state/permitCacheAtom.ts rename apps/cowswap-frontend/src/modules/permit/state/{atoms.ts => permittableTokensAtom.ts} (100%) diff --git a/apps/cowswap-frontend/src/mocks/tradeStateMock.ts b/apps/cowswap-frontend/src/mocks/tradeStateMock.ts index 20d5b09ac3..bd59d7fe92 100644 --- a/apps/cowswap-frontend/src/mocks/tradeStateMock.ts +++ b/apps/cowswap-frontend/src/mocks/tradeStateMock.ts @@ -51,6 +51,7 @@ export const outputCurrencyInfoMock: CurrencyInfo = { export const tradeContextMock: TradeFlowContext = { permitInfo: undefined, + generatePermitHook: (() => void 0) as any, postOrderParams: { class: OrderClass.LIMIT, account: '0x000', diff --git a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts index f049ef4600..488fa09af8 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/hooks/useTradeFlowContext.ts @@ -15,7 +15,7 @@ import { useAppData } from 'modules/appData' import { useRateImpact } from 'modules/limitOrders/hooks/useRateImpact' import { TradeFlowContext } from 'modules/limitOrders/services/types' import { limitOrdersSettingsAtom } from 'modules/limitOrders/state/limitOrdersSettingsAtom' -import { useIsTokenPermittable } from 'modules/permit' +import { useGeneratePermitHook, useIsTokenPermittable } from 'modules/permit' import { useEnoughBalanceAndAllowance } from 'modules/tokens' import { TradeType } from 'modules/trade' import { useTradeQuote } from 'modules/tradeQuote' @@ -42,6 +42,7 @@ export function useTradeFlowContext(): TradeFlowContext | null { amount: state.slippageAdjustedSellAmount || undefined, checkAllowanceAddress, }) + const generatePermitHook = useGeneratePermitHook() if ( !chainId || @@ -76,6 +77,7 @@ export function useTradeFlowContext(): TradeFlowContext | null { provider, rateImpact, permitInfo: !enoughAllowance ? permitInfo : undefined, + generatePermitHook, postOrderParams: { class: OrderClass.LIMIT, kind: state.orderKind, diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx index 68a605eb1f..66d3058a37 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/LimitOrdersDetails/index.cosmos.tsx @@ -17,6 +17,7 @@ const outputCurrency = GNO[SupportedChainId.MAINNET] const tradeContext: TradeFlowContext = { permitInfo: undefined, + generatePermitHook: () => Promise.resolve(undefined), postOrderParams: { class: OrderClass.LIMIT, account: '0x000', diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts index b2ff0d36a4..e6c7baf500 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/services/tradeFlow/index.ts @@ -34,6 +34,7 @@ export async function tradeFlow( settlementContract, dispatch, isGnosisSafeWallet, + generatePermitHook, } = params const { account, recipientAddressOrName, sellToken, buyToken, appData } = postOrderParams const marketLabel = [sellToken.symbol, buyToken.symbol].join(',') @@ -61,10 +62,9 @@ export async function tradeFlow( postOrderParams.appData = await handlePermit({ permitInfo, inputToken: sellToken, - provider, account, - chainId, appData, + generatePermitHook, }) logTradeFlow('LIMIT ORDER FLOW', 'STEP 3: send transaction') diff --git a/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts b/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts index 2c55f9e369..71d0f022e0 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts +++ b/apps/cowswap-frontend/src/modules/limitOrders/services/types.ts @@ -6,7 +6,7 @@ import SafeAppsSDK from '@safe-global/safe-apps-sdk' import { AppDispatch } from 'legacy/state' import { PostOrderParams } from 'legacy/utils/trade' -import { IsTokenPermittableResult } from 'modules/permit' +import { GeneratePermitHook, IsTokenPermittableResult } from 'modules/permit' export interface TradeFlowContext { // signer changes creates redundant re-renders @@ -20,6 +20,7 @@ export interface TradeFlowContext { allowsOffchainSigning: boolean isGnosisSafeWallet: boolean permitInfo: IsTokenPermittableResult + generatePermitHook: GeneratePermitHook } export interface SafeBundleFlowContext extends TradeFlowContext { diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts index b4d95a2d79..458cbe3e21 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useAccountAgnosticPermitHookData.ts @@ -1,17 +1,15 @@ import { useEffect, useState } from 'react' -import { useWalletInfo } from '@cowprotocol/wallet' import { Token } from '@uniswap/sdk-core' -import { useWeb3React } from '@web3-react/core' import { useDerivedTradeState } from 'modules/trade' import { useSafeMemo } from 'common/hooks/useSafeMemo' +import { useGeneratePermitHook } from './useGeneratePermitHook' import { useIsTokenPermittable } from './useIsTokenPermittable' -import { PermitHookData, PermitHookParams } from '../types' -import { generatePermitHook } from '../utils/generatePermitHook' +import { GeneratePermitHookParams, PermitHookData } from '../types' /** * Returns PermitHookData using an account agnostic signer if inputCurrency is permittable @@ -21,7 +19,8 @@ import { generatePermitHook } from '../utils/generatePermitHook' * If not permittable or not able to tell, returns undefined */ export function useAccountAgnosticPermitHookData(): PermitHookData | undefined { - const params = usePermitHookParams() + const params = useGeneratePermitHookParams() + const generatePermitHook = useGeneratePermitHook() const [data, setData] = useState(undefined) @@ -33,28 +32,23 @@ export function useAccountAgnosticPermitHookData(): PermitHookData | undefined { } generatePermitHook(params).then(setData) - }, [params]) + }, [generatePermitHook, params]) return data } -function usePermitHookParams(): PermitHookParams | undefined { - const { chainId } = useWalletInfo() - const { provider } = useWeb3React() - +function useGeneratePermitHookParams(): GeneratePermitHookParams | undefined { const { state } = useDerivedTradeState() const { inputCurrency, tradeType } = state || {} const permitInfo = useIsTokenPermittable(inputCurrency, tradeType) return useSafeMemo(() => { - if (!inputCurrency || !provider || !permitInfo) return undefined + if (!inputCurrency || !permitInfo) return undefined return { - chainId, - provider, inputToken: inputCurrency as Token, permitInfo, } - }, [inputCurrency, provider, permitInfo, chainId]) + }, [inputCurrency, permitInfo]) } diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts new file mode 100644 index 0000000000..0505914230 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts @@ -0,0 +1,59 @@ +import { useSetAtom } from 'jotai' +import { useCallback } from 'react' + +import { useWalletInfo } from '@cowprotocol/wallet' +import { useWeb3React } from '@web3-react/core' + +import { getPermitCacheAtom, storePermitCacheAtom } from '../state/permitCacheAtom' +import { GeneratePermitHook, GeneratePermitHookParams, PermitHookData } from '../types' +import { generatePermitHook } from '../utils/generatePermitHook' +import { getPermitUtilsInstance } from '../utils/getPermitUtilsInstance' + +/** + * Hook that returns callback to generate permit hook data + */ +export function useGeneratePermitHook(): GeneratePermitHook { + const getCachedPermit = useSetAtom(getPermitCacheAtom) + const storePermit = useSetAtom(storePermitCacheAtom) + const { chainId } = useWalletInfo() + const { provider } = useWeb3React() + + return useCallback( + async (params: GeneratePermitHookParams): Promise => { + const { inputToken, account, permitInfo } = params + + if (!provider) { + return + } + + const eip2162Utils = getPermitUtilsInstance(chainId, provider, account) + + // Always get the nonce for the real account, to know whether the cache should be invalidated + // Static account should never need to pre-check the nonce as it'll never change once cached + const nonce = account ? await eip2162Utils.getTokenNonce(inputToken.address, account) : undefined + + const permitParams = { chainId, tokenAddress: inputToken.address, account, nonce } + + const cachedPermit = getCachedPermit(permitParams) + + if (cachedPermit) { + return cachedPermit + } + + const hookData = await generatePermitHook({ + chainId, + inputToken, + provider, + permitInfo, + eip2162Utils, + account, + nonce, + }) + + storePermit({ ...permitParams, hookData }) + + return hookData + }, + [storePermit, chainId, getCachedPermit, provider] + ) +} diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts index 147db0402d..b804d3aaf5 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useIsTokenPermittable.ts @@ -13,7 +13,7 @@ import { TradeType } from 'modules/trade' import { useIsPermitEnabled } from 'common/hooks/featureFlags/useIsPermitEnabled' import { ORDER_TYPE_SUPPORTS_PERMIT } from '../const' -import { addPermitInfoForTokenAtom, permittableTokensAtom } from '../state/atoms' +import { addPermitInfoForTokenAtom, permittableTokensAtom } from '../state/permittableTokensAtom' import { IsTokenPermittableResult } from '../types' import { checkIsTokenPermittable } from '../utils/checkIsTokenPermittable' diff --git a/apps/cowswap-frontend/src/modules/permit/index.ts b/apps/cowswap-frontend/src/modules/permit/index.ts index 6906fa3831..5f70182cfc 100644 --- a/apps/cowswap-frontend/src/modules/permit/index.ts +++ b/apps/cowswap-frontend/src/modules/permit/index.ts @@ -1,5 +1,5 @@ -export { useAccountAgnosticPermitHookData } from './hooks/useAccountAgnosticPermitHookData' -export { generatePermitHook } from './utils/generatePermitHook' -export { useIsTokenPermittable } from './hooks/useIsTokenPermittable' +export * from './hooks/useAccountAgnosticPermitHookData' +export * from './hooks/useIsTokenPermittable' +export * from './hooks/useGeneratePermitHook' export * from './utils/handlePermit' export * from './types' diff --git a/apps/cowswap-frontend/src/modules/permit/state/permitCacheAtom.ts b/apps/cowswap-frontend/src/modules/permit/state/permitCacheAtom.ts new file mode 100644 index 0000000000..aac142e2a1 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/state/permitCacheAtom.ts @@ -0,0 +1,106 @@ +import { atom } from 'jotai' +import { atomWithStorage } from 'jotai/utils' + +import { + CachedPermitData, + GetPermitCacheParams, + PermitCache, + PermitCacheKeyParams, + StorePermitCacheParams, +} from '../types' + +/** + * Atom that stores permit data for static permit requests. + * Should never change once it has been created. + * Used exclusively for quote requests + */ +export const staticPermitCacheAtom = atomWithStorage('staticPermitCache:v0', {}) + +/** + * Atom that stores permit data for user permit requests. + * Should be updated whenever the permit nonce is updated. + * Used exclusively for order requests + */ +export const userPermitCacheAtom = atomWithStorage('userPermitCache:v0', {}) + +/** + * Atom to add/update permit cache data + * + * Input depends on the target type of cache: static or user + */ +export const storePermitCacheAtom = atom(null, (get, set, params: StorePermitCacheParams) => { + const atomToUpdate = params.account ? userPermitCacheAtom : staticPermitCacheAtom + + const key = buildKey(params) + + const dataToCache: CachedPermitData = { + hookData: params.hookData, + nonce: params.nonce, + } + + set(atomToUpdate, (permitCache) => ({ ...permitCache, [key]: JSON.stringify(dataToCache) })) +}) + +/** + * Atom to get the cached permit data. + * + * Returns either undefined when no cache or cache is outdated, or the cached permit hook data. + * + * When cache is outdated, it will remove the cache key from the target cache. + * For this reason it's a writable atom. + */ +export const getPermitCacheAtom = atom(null, (get, set, params: GetPermitCacheParams) => { + const atomToUpdate = params.account ? userPermitCacheAtom : staticPermitCacheAtom + + const permitCache = get(atomToUpdate) + const key = buildKey(params) + const cachedData = permitCache[key] + + if (!cachedData) { + return undefined + } + + try { + const { hookData, nonce: storedNonce }: CachedPermitData = JSON.parse(cachedData) + + if (params.account !== undefined) { + // User type permit cache, check the nonce + + const inputNonce = params.nonce + + if (storedNonce !== undefined && inputNonce !== undefined && storedNonce < inputNonce) { + // When both nonces exist and storedNonce < inputNonce, data is outdated + + // Remove cache key + set(atomToUpdate, removePermitCacheBuilder(key)) + + return undefined + } + } + + // Cache hit for both static and user permit types + return hookData + } catch (e) { + // Failed to parse stored data, clear cache and return nothing + + set(atomToUpdate, removePermitCacheBuilder(key)) + + console.info(`[getPermitCacheAtom] failed to parse stored data`, cachedData, e) + + return undefined + } +}) + +function buildKey({ chainId, tokenAddress, account }: PermitCacheKeyParams) { + const base = `${chainId}-${tokenAddress.toLowerCase()}` + + return account ? `${base}-${account.toLowerCase()}` : base +} + +const removePermitCacheBuilder = (key: string) => (permitCache: PermitCache) => { + const newPermitCache = { ...permitCache } + + delete newPermitCache[key] + + return newPermitCache +} diff --git a/apps/cowswap-frontend/src/modules/permit/state/atoms.ts b/apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts similarity index 100% rename from apps/cowswap-frontend/src/modules/permit/state/atoms.ts rename to apps/cowswap-frontend/src/modules/permit/state/permittableTokensAtom.ts diff --git a/apps/cowswap-frontend/src/modules/permit/types.ts b/apps/cowswap-frontend/src/modules/permit/types.ts index 9017f2bfb2..5993a6fa67 100644 --- a/apps/cowswap-frontend/src/modules/permit/types.ts +++ b/apps/cowswap-frontend/src/modules/permit/types.ts @@ -31,12 +31,19 @@ export type PermitHookParams = { chainId: SupportedChainId permitInfo: SupportedPermitInfo provider: Web3Provider - account?: string + eip2162Utils: Eip2612PermitUtils + account?: string | undefined + nonce?: number | undefined } -export type HandlePermitParams = Omit & { +export type GeneratePermitHookParams = Pick + +export type GeneratePermitHook = (params: GeneratePermitHookParams) => Promise + +export type HandlePermitParams = Omit & { permitInfo: IsTokenPermittableResult appData: AppDataInfo + generatePermitHook: GeneratePermitHook } export type PermitHookData = latest.CoWHook @@ -67,3 +74,21 @@ export type CheckIsTokenPermittableParams = { chainId: SupportedChainId provider: Web3Provider } + +export type PermitCache = Record + +export type CachedPermitData = { + hookData: PermitHookData + nonce: number | undefined +} + +export type PermitCacheKeyParams = { + chainId: SupportedChainId + tokenAddress: string + account: string | undefined + nonce: number | undefined +} + +export type StorePermitCacheParams = PermitCacheKeyParams & { hookData: PermitHookData } + +export type GetPermitCacheParams = PermitCacheKeyParams diff --git a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts index 1f2e295bab..7d781342aa 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/generatePermitHook.ts @@ -1,34 +1,17 @@ import { GP_VAULT_RELAYER } from '@cowprotocol/common-const' import { Web3Provider } from '@ethersproject/providers' -import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' - import { buildDaiLikePermitCallData, buildEip2162PermitCallData } from './buildPermitCallData' import { getPermitDeadline } from './getPermitDeadline' -import { getPermitUtilsInstance } from './getPermitUtilsInstance' import { DEFAULT_PERMIT_GAS_LIMIT, DEFAULT_PERMIT_VALUE, PERMIT_SIGNER } from '../const' import { PermitHookData, PermitHookParams } from '../types' -const CACHE_PREFIX = 'permitCache:v0-' const REQUESTS_CACHE: { [permitKey: string]: Promise } = {} export async function generatePermitHook(params: PermitHookParams): Promise { const permitKey = getCacheKey(params) - const { chainId, provider, account, inputToken } = params - - const eip2162Utils = getPermitUtilsInstance(chainId, provider, account) - - // Always get the nonce for the real account, to know whether the cache should be invalidated - // Static account should never need to pre-check the nonce as it'll never change once cached - const nonce = account ? await eip2162Utils.getTokenNonce(inputToken.address, account) : undefined - - const cachedResult = load(permitKey, nonce) - if (cachedResult) { - return cachedResult - } - const cachedRequest = REQUESTS_CACHE[permitKey] if (cachedRequest) { @@ -40,10 +23,7 @@ export async function generatePermitHook(params: PermitHookParams): Promise { - // Store permit in the cache - save(permitKey, nonce, permitHookData) - + const request = generatePermitHookRaw(params).then((permitHookData) => { // Remove consumed request to avoid stale data delete REQUESTS_CACHE[permitKey] @@ -55,10 +35,8 @@ export async function generatePermitHook(params: PermitHookParams): Promise { - const { inputToken, chainId, permitInfo, provider, account, eip2162Utils, preFetchedNonce } = params +async function generatePermitHookRaw(params: PermitHookParams): Promise { + const { inputToken, chainId, permitInfo, provider, account, eip2162Utils, nonce: preFetchedNonce } = params const tokenAddress = inputToken.address const tokenName = inputToken.name || tokenAddress @@ -142,55 +120,5 @@ async function calculateGasLimit( function getCacheKey(params: PermitHookParams): string { const { inputToken, chainId, account } = params - return `${CACHE_PREFIX}${inputToken.address.toLowerCase()}-${chainId}${account ? `-${account.toLowerCase()}` : ''}` -} - -type CachedData = PermitHookData & { - nonce: number | undefined -} - -/** - * Stores data based on `key` and `nonce` - */ -function save(key: string, nonce: number | undefined, data: PermitHookData): void { - const cachedData: CachedData = { nonce, ...data } - - localStorage.setItem(key, JSON.stringify(cachedData)) -} - -/** - * Loads stored data if still valid - * - * Validity is based on `nonce` and only applies to real accounts - * Static data never gets invalidated - */ -function load(key: string, nonce: number | undefined): PermitHookData | undefined { - const cachedData = localStorage.getItem(key) - - if (!cachedData) { - return undefined - } - - try { - const parsedData: CachedData = JSON.parse(cachedData) - - // Extract nonce out of cached data - const { nonce: storedNonce, ...permitHookData } = parsedData - - // TODO: if one is defined while the other is not, should also ignore the cache - if (nonce !== undefined && storedNonce !== undefined && storedNonce < nonce) { - // When both nonces exist and stored is < than new, data is outdated - - // Remove cache key - localStorage.removeItem(key) - - return undefined - } - - // Cache is valid, return it - return permitHookData - } catch { - // Failed to parse stored data, return nothing - return undefined - } + return `${inputToken.address.toLowerCase()}-${chainId}${account ? `-${account.toLowerCase()}` : ''}` } diff --git a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts index e623fd8ec3..38bc18b9c3 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/handlePermit.ts @@ -1,7 +1,5 @@ import { AppDataInfo, buildAppDataHooks, updateHooksOnAppData } from 'modules/appData' -import { generatePermitHook } from './generatePermitHook' - import { HandlePermitParams } from '../types' /** @@ -15,19 +13,21 @@ import { HandlePermitParams } from '../types' * Returns the updated appData */ export async function handlePermit(params: HandlePermitParams): Promise { - const { permitInfo, inputToken, provider, account, chainId, appData } = params + const { permitInfo, inputToken, account, appData, generatePermitHook } = params if (permitInfo) { - // permitInfo will only be set if there's enough allowance + // permitInfo will only be set if there's NOT enough allowance const permitData = await generatePermitHook({ inputToken, - provider, account, - chainId, permitInfo, }) + if (!permitData) { + throw new Error(`Unable to generate permit data`) + } + const hooks = buildAppDataHooks([permitData]) return updateHooksOnAppData(appData, hooks) diff --git a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts index f2c1329a80..086e4329ba 100644 --- a/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts +++ b/apps/cowswap-frontend/src/modules/swap/hooks/useSwapFlowContext.ts @@ -3,7 +3,7 @@ import { useGP2SettlementContract } from '@cowprotocol/common-hooks' import { OrderKind, SupportedChainId } from '@cowprotocol/cow-sdk' import { TradeType as UniTradeType } from '@uniswap/sdk-core' -import { useIsTokenPermittable } from 'modules/permit' +import { useGeneratePermitHook, useIsTokenPermittable } from 'modules/permit' import { FlowType, getFlowContext, useBaseFlowContextSetup } from 'modules/swap/hooks/useFlowContext' import { SwapFlowContext } from 'modules/swap/services/types' import { useEnoughBalanceAndAllowance } from 'modules/tokens' @@ -14,6 +14,7 @@ export function useSwapFlowContext(): SwapFlowContext | null { const baseProps = useBaseFlowContextSetup() const sellCurrency = baseProps.trade?.inputAmount?.currency const permitInfo = useIsTokenPermittable(sellCurrency, TradeType.SWAP) + const generatePermitHook = useGeneratePermitHook() const checkAllowanceAddress = GP_VAULT_RELAYER[baseProps.chainId || SupportedChainId.MAINNET] const { enoughAllowance } = useEnoughBalanceAndAllowance({ @@ -36,5 +37,6 @@ export function useSwapFlowContext(): SwapFlowContext | null { ...baseContext, contract, permitInfo: !enoughAllowance ? permitInfo : undefined, + generatePermitHook, } } diff --git a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts index 326f3889ed..ec49a936b3 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/swapFlow/index.ts @@ -1,4 +1,3 @@ -import { Web3Provider } from '@ethersproject/providers' import { Percent, Token } from '@uniswap/sdk-core' import { PriceImpact } from 'legacy/hooks/usePriceImpact' @@ -31,12 +30,10 @@ export async function swapFlow( input.orderParams.appData = await handlePermit({ appData: input.orderParams.appData, - inputToken: input.context.trade.inputAmount.currency as Token, - provider: input.orderParams.signer.provider as Web3Provider, account: input.orderParams.account, - chainId: input.orderParams.chainId, permitInfo: input.permitInfo, + generatePermitHook: input.generatePermitHook, }) input.swapConfirmManager.permitSigned() diff --git a/apps/cowswap-frontend/src/modules/swap/services/types.ts b/apps/cowswap-frontend/src/modules/swap/services/types.ts index 6417e077aa..52d3f55a30 100644 --- a/apps/cowswap-frontend/src/modules/swap/services/types.ts +++ b/apps/cowswap-frontend/src/modules/swap/services/types.ts @@ -10,7 +10,7 @@ import TradeGp from 'legacy/state/swap/TradeGp' import { PostOrderParams } from 'legacy/utils/trade' import { AppDataInfo, UploadAppDataParams } from 'modules/appData' -import { IsTokenPermittableResult } from 'modules/permit' +import { GeneratePermitHook, IsTokenPermittableResult } from 'modules/permit' import { SwapConfirmManager } from 'modules/swap/hooks/useSwapConfirmManager' import { SwapFlowAnalyticsContext } from 'modules/trade/utils/analytics' @@ -45,6 +45,7 @@ export interface BaseFlowContext { export type SwapFlowContext = BaseFlowContext & { contract: GPv2Settlement permitInfo: IsTokenPermittableResult + generatePermitHook: GeneratePermitHook } export type EthFlowContext = BaseFlowContext & { From f4700d9ac34bf281f6efb9bcbc60bebacb8ac68f Mon Sep 17 00:00:00 2001 From: Leandro Date: Wed, 11 Oct 2023 10:14:11 -0700 Subject: [PATCH 31/36] feat(permit): allowance warning (#3184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: remove unnecessary toString() * chore: fix typo * fix: transform BigNumber instances into hex strings for compatibility with 1inch lib * feat: add fullAppData to local order instance * feat: add decodeAppData to appData module * feat: add getAppDataHooks to appData module * feat: add useCheckHasValidPendingPermit to permit module * feat: add permit checking to OrderRow allowance warning * refactor: rename getParsedOrderFromItem to getParsedOrderFromTableItem * refactor: change isParsed order to be a bit more semantic * feat: add ordersPermitStatusAtom * feat: add PendingPermitUpdater * feat: add useGetOrdersPermitStatus * feat: pass down ordersPermitStatus * feat: add PendingPermitUpdater to OrdersTableWidget * chore: remove unused export * refactor: sort exports * fix: add back export. I removed the wrong one 🤦 * refactor: extract useGetOrdersToCheckPendingPermit * chore: debug statements * fix: force atoms to load so stored value is respected * refactor: use the handy atomWithPartialUpdate * refactor: move useGetOrdersToCheckPendingPermit to its own file --- .../common/updaters/orders/GpOrdersUpdater.ts | 3 +- .../src/legacy/state/orders/actions.ts | 4 + .../src/legacy/utils/trade.ts | 6 +- .../src/modules/appData/index.ts | 1 + .../modules/appData/utils/decodeAppData.ts | 24 ++++ .../modules/appData/utils/getAppDataHooks.ts | 21 +++ .../hooks/useGetOrdersToCheckPendingPermit.ts | 34 +++++ .../hooks/useOrdersTableList.ts | 6 +- .../containers/OrdersTableWidget/index.tsx | 13 +- .../OrdersTableContainer/OrderRow/index.tsx | 6 +- .../pure/OrdersTableContainer/OrdersTable.tsx | 25 ++-- .../OrdersTableContainer/index.cosmos.tsx | 1 + .../pure/OrdersTableContainer/index.tsx | 2 + .../utils/getOrderParams.ts | 4 +- .../ordersTable/utils/orderTableGroupUtils.ts | 7 +- .../src/modules/permit/const.ts | 2 + .../hooks/useCheckHasValidPendingPermit.ts | 121 ++++++++++++++++++ .../permit/hooks/useGeneratePermitHook.ts | 18 ++- .../permit/hooks/useOrdersPermitStatus.ts | 7 + .../src/modules/permit/index.ts | 6 +- .../permit/state/ordersPermitStatusAtom.ts | 9 ++ .../src/modules/permit/types.ts | 6 + .../permit/updaters/PendingPermitUpdater.ts | 39 ++++++ .../tokens/hooks/useBalancesAndAllowances.ts | 2 +- .../wallet/utils/PermitProviderConnector.ts | 28 +++- .../src/utils/orderUtils/parseOrder.ts | 2 + 26 files changed, 366 insertions(+), 31 deletions(-) create mode 100644 apps/cowswap-frontend/src/modules/appData/utils/decodeAppData.ts create mode 100644 apps/cowswap-frontend/src/modules/appData/utils/getAppDataHooks.ts create mode 100644 apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useGetOrdersToCheckPendingPermit.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/hooks/useOrdersPermitStatus.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/state/ordersPermitStatusAtom.ts create mode 100644 apps/cowswap-frontend/src/modules/permit/updaters/PendingPermitUpdater.ts diff --git a/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts index 88f51d14ca..c2cc7923c4 100644 --- a/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/GpOrdersUpdater.ts @@ -11,7 +11,7 @@ import { Order, OrderStatus } from 'legacy/state/orders/actions' import { useAddOrUpdateOrders, useClearOrdersStorage } from 'legacy/state/orders/hooks' import { classifyOrder, OrderTransitionStatus } from 'legacy/state/orders/utils' -import { useTokensForOrdersList, getTokensListFromOrders } from 'modules/orders' +import { getTokensListFromOrders, useTokensForOrdersList } from 'modules/orders' import { apiOrdersAtom } from 'modules/orders/state/apiOrdersAtom' import { useGpOrders } from 'api/gnosisProtocol/hooks' @@ -80,6 +80,7 @@ function _transformGpOrderToStoreOrder( summary: '', status, receiver: receiver || '', + fullAppData: order.fullAppData, apiAdditionalInfo: order, isCancelling: apiStatus === 'pending' && order.invalidated, // already cancelled in the API, not yet in the UI // EthFlow related diff --git a/apps/cowswap-frontend/src/legacy/state/orders/actions.ts b/apps/cowswap-frontend/src/legacy/state/orders/actions.ts index a08dd6ecd6..162055f7c8 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/actions.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/actions.ts @@ -59,6 +59,10 @@ export interface BaseOrder extends Omit { // Additional information from the order available in the API apiAdditionalInfo?: OrderInfoApi + // De-normalizing it as this is known at order placement time as `appData`, + // but when returned from the api is replaced with the `appDataHash` + // See this order response for example https://barn.api.cow.fi/goerli/api/v1/orders/0xc170856a42f38ba07a7af3ea8f299ea724ec0aa22445eb741cbad7f9dd4fcda05b0abe214ab7875562adee331deff0fe1912fe4265269bb1 + fullAppData?: EnrichedOrder['fullAppData'] // Wallet specific presignGnosisSafeTxHash?: string // Gnosis Safe tx diff --git a/apps/cowswap-frontend/src/legacy/utils/trade.ts b/apps/cowswap-frontend/src/legacy/utils/trade.ts index 55d856f7cc..9ab6869232 100644 --- a/apps/cowswap-frontend/src/legacy/utils/trade.ts +++ b/apps/cowswap-frontend/src/legacy/utils/trade.ts @@ -1,5 +1,5 @@ -import { RADIX_DECIMAL, NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' -import { isAddress, shortenAddress, formatTokenAmount, formatSymbol } from '@cowprotocol/common-utils' +import { NATIVE_CURRENCY_BUY_ADDRESS, RADIX_DECIMAL } from '@cowprotocol/common-const' +import { formatSymbol, formatTokenAmount, isAddress, shortenAddress } from '@cowprotocol/common-utils' import { EcdsaSigningScheme, OrderClass, @@ -156,6 +156,7 @@ export function mapUnsignedOrderToOrder({ unsignedOrder, additionalParams }: Map sellAmountBeforeFee, orderCreationHash, quoteId, + appData: { fullAppData }, } = additionalParams const status = _getOrderStatus(allowsOffchainSigning, isOnChain) @@ -170,6 +171,7 @@ export function mapUnsignedOrderToOrder({ unsignedOrder, additionalParams }: Map outputToken: buyToken, quoteId, class: additionalParams.class, + fullAppData, // Status status, diff --git a/apps/cowswap-frontend/src/modules/appData/index.ts b/apps/cowswap-frontend/src/modules/appData/index.ts index 96a003b233..770057cc7d 100644 --- a/apps/cowswap-frontend/src/modules/appData/index.ts +++ b/apps/cowswap-frontend/src/modules/appData/index.ts @@ -3,4 +3,5 @@ export * from './updater/AppDataUpdater' export { useAppData, useUploadAppData } from './hooks' export { updateHooksOnAppData, buildAppData } from './utils/buildAppData' export { buildAppDataHooks } from './utils/buildAppDataHooks' +export * from './utils/getAppDataHooks' export type { AppDataInfo, UploadAppDataParams } from './types' diff --git a/apps/cowswap-frontend/src/modules/appData/utils/decodeAppData.ts b/apps/cowswap-frontend/src/modules/appData/utils/decodeAppData.ts new file mode 100644 index 0000000000..b9aba4974c --- /dev/null +++ b/apps/cowswap-frontend/src/modules/appData/utils/decodeAppData.ts @@ -0,0 +1,24 @@ +import { AnyAppDataDocVersion } from '@cowprotocol/app-data' + +import { Nullish } from 'types' + +/** + * Decode appData from a string to a AnyAppDataDocVersion instance + * Keep in mind it can be a valid JSON but not necessarily a valid AppDataDoc + * + * Returns undefined if the given appData is not a valid JSON + */ +export function decodeAppData(appData: Nullish): AnyAppDataDocVersion | undefined { + if (!appData) { + return undefined + } + + try { + // TODO: returned value can be a valid JSON but not necessarily a valid AppDataDoc + return JSON.parse(appData) + } catch (e) { + console.info(`[decodeAppData] given appData is not a valid JSON`, appData) + + return undefined + } +} diff --git a/apps/cowswap-frontend/src/modules/appData/utils/getAppDataHooks.ts b/apps/cowswap-frontend/src/modules/appData/utils/getAppDataHooks.ts new file mode 100644 index 0000000000..7aa825789e --- /dev/null +++ b/apps/cowswap-frontend/src/modules/appData/utils/getAppDataHooks.ts @@ -0,0 +1,21 @@ +import { AnyAppDataDocVersion } from '@cowprotocol/app-data' + +import { Nullish } from 'types' + +import { decodeAppData } from './decodeAppData' + +import { AppDataHooks } from '../types' + +/** + * Get hooks from fullAppData, which can be JSON stringified or the instance + * + * Returns undefined if the fullAppData is falsy or if there are no hooks + */ +export function getAppDataHooks(fullAppData: Nullish): AppDataHooks | undefined { + const decodedAppData = typeof fullAppData === 'string' ? decodeAppData(fullAppData) : fullAppData + + if (!decodedAppData || !('hooks' in decodedAppData.metadata)) return undefined + + // TODO: this requires app-data v0.9.0. Might not work for newer versions... + return decodedAppData.metadata.hooks as AppDataHooks +} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useGetOrdersToCheckPendingPermit.ts b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useGetOrdersToCheckPendingPermit.ts new file mode 100644 index 0000000000..444c72662b --- /dev/null +++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useGetOrdersToCheckPendingPermit.ts @@ -0,0 +1,34 @@ +import { useMemo } from 'react' + +import { SupportedChainId } from '@cowprotocol/cow-sdk' + +import { BalancesAndAllowances } from 'modules/tokens' + +import { ParsedOrder } from 'utils/orderUtils/parseOrder' + +import { OrdersTableList } from './useOrdersTableList' + +import { getOrderParams } from '../../../pure/OrdersTableContainer/utils/getOrderParams' +import { isParsedOrder } from '../../../utils/orderTableGroupUtils' + +export function useGetOrdersToCheckPendingPermit( + ordersList: OrdersTableList, + chainId: SupportedChainId, + balancesAndAllowances: BalancesAndAllowances +) { + return useMemo(() => { + // Pick only the pending orders + return ordersList.pending.reduce((acc: ParsedOrder[], item) => { + // Only do it for regular orders (not TWAP) + if (isParsedOrder(item)) { + const { hasEnoughAllowance } = getOrderParams(chainId, balancesAndAllowances, item) + + // Only if the order has not enough allowance + if (hasEnoughAllowance === false) { + acc.push(item) + } + } + return acc + }, []) + }, [balancesAndAllowances, chainId, ordersList.pending]) +} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableList.ts b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableList.ts index d42302c4f1..186e89fe5e 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableList.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/hooks/useOrdersTableList.ts @@ -3,7 +3,7 @@ import { useMemo } from 'react' import { Order, PENDING_STATES } from 'legacy/state/orders/actions' import { groupOrdersTable } from '../../../utils/groupOrdersTable' -import { getParsedOrderFromItem, isParsedOrder, OrderTableItem } from '../../../utils/orderTableGroupUtils' +import { getParsedOrderFromTableItem, isParsedOrder, OrderTableItem } from '../../../utils/orderTableGroupUtils' export interface OrdersTableList { pending: OrderTableItem[] @@ -11,8 +11,8 @@ export interface OrdersTableList { } const ordersSorter = (a: OrderTableItem, b: OrderTableItem) => { - const aCreationTime = getParsedOrderFromItem(a).creationTime - const bCreationTime = getParsedOrderFromItem(b).creationTime + const aCreationTime = getParsedOrderFromTableItem(a).creationTime + const bCreationTime = getParsedOrderFromTableItem(b).creationTime return bCreationTime.getTime() - aCreationTime.getTime() } diff --git a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx index 19e4afc5c7..d98cc04619 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/containers/OrdersTableWidget/index.tsx @@ -17,20 +17,22 @@ import { OrdersReceiptModal } from 'modules/ordersTable/containers/OrdersReceipt import { useSelectReceiptOrder } from 'modules/ordersTable/containers/OrdersReceiptModal/hooks' import { OrderActions } from 'modules/ordersTable/pure/OrdersTableContainer/types' import { buildOrdersTableUrl, parseOrdersTableUrl } from 'modules/ordersTable/utils/buildOrdersTableUrl' +import { PendingPermitUpdater, useGetOrdersPermitStatus } from 'modules/permit' import { useBalancesAndAllowances } from 'modules/tokens' import { useCancelOrder } from 'common/hooks/useCancelOrder' +import { useCategorizeRecentActivity } from 'common/hooks/useCategorizeRecentActivity' import { ordersToCancelAtom, updateOrdersToCancelAtom } from 'common/hooks/useMultipleOrdersCancellation/state' import { CancellableOrder } from 'common/utils/isOrderCancellable' import { ParsedOrder } from 'utils/orderUtils/parseOrder' +import { useGetOrdersToCheckPendingPermit } from './hooks/useGetOrdersToCheckPendingPermit' import { OrdersTableList, useOrdersTableList } from './hooks/useOrdersTableList' import { useOrdersTableTokenApprove } from './hooks/useOrdersTableTokenApprove' import { useValidatePageUrlParams } from './hooks/useValidatePageUrlParams' -import { useCategorizeRecentActivity } from '../../../../common/hooks/useCategorizeRecentActivity' import { OrdersTableContainer, TabOrderTypes } from '../../pure/OrdersTableContainer' -import { getParsedOrderFromItem, OrderTableItem, tableItemsToOrders } from '../../utils/orderTableGroupUtils' +import { getParsedOrderFromTableItem, OrderTableItem, tableItemsToOrders } from '../../utils/orderTableGroupUtils' function getOrdersListByIndex(ordersList: OrdersTableList, id: string): OrderTableItem[] { return id === OPEN_TAB.id ? ordersList.pending : ordersList.history @@ -73,6 +75,7 @@ export function OrdersTableWidget({ const getSpotPrice = useGetSpotPrice() const selectReceiptOrder = useSelectReceiptOrder() const isSafeViaWc = useIsSafeViaWc() + const ordersPermitStatus = useGetOrdersPermitStatus() const spender = useMemo(() => (chainId ? GP_VAULT_RELAYER[chainId] : undefined), [chainId]) @@ -101,7 +104,7 @@ export function OrdersTableWidget({ const tokens = useMemo(() => { const pendingOrders = isOpenOrdersTab ? ordersList.pending : [] - return pendingOrders.map((item) => getParsedOrderFromItem(item).inputToken) + return pendingOrders.map((item) => getParsedOrderFromTableItem(item).inputToken) }, [isOpenOrdersTab, ordersList.pending]) // Get effective balance @@ -148,8 +151,11 @@ export function OrdersTableWidget({ useValidatePageUrlParams(orders.length, currentTabId, currentPageNumber) + const ordersToCheckPendingPermit = useGetOrdersToCheckPendingPermit(ordersList, chainId, balancesAndAllowances) + return ( <> + {isOpenOrdersTab && orders.length && } diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx index 21f8a63541..e71f7ff25d 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx @@ -148,6 +148,7 @@ export interface OrderRowProps { orderParams: OrderParams onClick: () => void orderActions: OrderActions + hasValidPendingPermit?: boolean | undefined children?: JSX.Element } @@ -164,6 +165,7 @@ export function OrderRow({ prices, spotPrice, children, + hasValidPendingPermit, }: OrderRowProps) { const { buyAmount, rateInfoParams, hasEnoughAllowance, hasEnoughBalance, chainId } = orderParams const { creationTime, expirationTime, status } = order @@ -174,7 +176,7 @@ export function OrderRow({ const showCancellationModal = orderActions.getShowCancellationModal(order) const withWarning = - (hasEnoughBalance === false || hasEnoughAllowance === false) && + (hasEnoughBalance === false || (hasEnoughAllowance === false && hasValidPendingPermit === false)) && // show the warning only for pending and scheduled orders (status === OrderStatus.PENDING || status === OrderStatus.SCHEDULED) const theme = useContext(ThemeContext) @@ -357,7 +359,7 @@ export function OrderRow({ {hasEnoughBalance === false && ( )} - {hasEnoughAllowance === false && ( + {hasEnoughAllowance === false && hasValidPendingPermit === false && ( orderActions.approveOrderToken(order.inputToken)} symbol={inputTokenSymbol} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx index 7fa718815c..b9d87eadb5 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrdersTable.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState, useEffect, useMemo, useRef } from 'react' +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import iconOrderExecution from '@cowprotocol/assets/cow-swap/orderExecution.svg' import { SupportedChainId } from '@cowprotocol/cow-sdk' @@ -11,19 +11,19 @@ import SVG from 'react-inlinesvg' import { useLocation } from 'react-router-dom' import styled from 'styled-components/macro' -import { QuestionWrapper } from 'legacy/components/QuestionHelper' -import QuestionHelper from 'legacy/components/QuestionHelper' +import QuestionHelper, { QuestionWrapper } from 'legacy/components/QuestionHelper' import { PendingOrdersPrices } from 'modules/orders/state/pendingOrdersPricesAtom' import { SpotPricesKeyParams } from 'modules/orders/state/spotPricesAtom' import { ORDERS_TABLE_PAGE_SIZE } from 'modules/ordersTable/const/tabs' import { + CheckboxCheckmark, TableHeader, TableRowCheckbox, TableRowCheckboxWrapper, - CheckboxCheckmark, } from 'modules/ordersTable/pure/OrdersTableContainer/styled' import { OrderActions } from 'modules/ordersTable/pure/OrdersTableContainer/types' +import { OrdersPermitStatus } from 'modules/permit' import { BalancesAndAllowances } from 'modules/tokens' import { ordersTableFeatures } from 'common/constants/featureFlags' @@ -40,7 +40,7 @@ import { getOrderParams } from './utils/getOrderParams' import { buildOrdersTableUrl } from '../../utils/buildOrdersTableUrl' import { - getParsedOrderFromItem, + getParsedOrderFromTableItem, isParsedOrder, OrderTableItem, tableItemsToOrders, @@ -206,6 +206,7 @@ export interface OrdersTableProps { balancesAndAllowances: BalancesAndAllowances getSpotPrice: (params: SpotPricesKeyParams) => Price | null orderActions: OrderActions + ordersPermitStatus: OrdersPermitStatus } export function OrdersTable({ @@ -219,6 +220,7 @@ export function OrdersTable({ getSpotPrice, orderActions, currentPageNumber, + ordersPermitStatus, }: OrdersTableProps) { const location = useLocation() const [isRateInverted, setIsRateInverted] = useState(false) @@ -261,14 +263,14 @@ export function OrdersTable({ }, [showOrdersExplainerBanner]) const cancellableOrders = useMemo( - () => ordersPage.filter((item) => isOrderOffChainCancellable(getParsedOrderFromItem(item))), + () => ordersPage.filter((item) => isOrderOffChainCancellable(getParsedOrderFromTableItem(item))), [ordersPage] ) const allOrdersSelected = useMemo(() => { if (!cancellableOrders.length) return false - return cancellableOrders.every((item) => selectedOrdersMap[getParsedOrderFromItem(item).id]) + return cancellableOrders.every((item) => selectedOrdersMap[getParsedOrderFromTableItem(item).id]) }, [cancellableOrders, selectedOrdersMap]) const getPageUrl = useCallback((index: number) => buildOrdersTableUrl(location, { pageNumber: index }), [location]) @@ -400,7 +402,7 @@ export function OrdersTable({ {ordersPage.map((item) => { - const { inputToken, outputToken } = getParsedOrderFromItem(item) + const { inputToken, outputToken } = getParsedOrderFromTableItem(item) const spotPrice = getSpotPrice({ chainId: chainId as SupportedChainId, sellTokenAddress: inputToken.address, @@ -410,6 +412,10 @@ export function OrdersTable({ if (isParsedOrder(item)) { const order = item + const orderParams = getOrderParams(chainId, balancesAndAllowances, order) + + const hasValidPendingPermit = ordersPermitStatus[order.id] + return ( orderActions.selectReceiptOrder(order)} + hasValidPendingPermit={hasValidPendingPermit} /> ) } else { diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx index 106ec79be7..0288e07a25 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.cosmos.tsx @@ -69,5 +69,6 @@ export default ( getSpotPrice={() => null} orderActions={orderActions} orderType={TabOrderTypes.LIMIT} + ordersPermitStatus={{}} /> ) diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx index 3572e28bbf..dcde2ae431 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/index.tsx @@ -167,6 +167,7 @@ export function OrdersTableContainer({ children, orderType, pendingActivities, + ordersPermitStatus, }: OrdersProps) { const content = () => { if (!isWalletConnected) { @@ -233,6 +234,7 @@ export function OrdersTableContainer({ balancesAndAllowances={balancesAndAllowances} getSpotPrice={getSpotPrice} orderActions={orderActions} + ordersPermitStatus={ordersPermitStatus} /> ) } diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts index c7e0077ed9..afda0bf5fd 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/utils/getOrderParams.ts @@ -23,8 +23,8 @@ export function getOrderParams( balancesAndAllowances: BalancesAndAllowances, order: ParsedOrder ): OrderParams { - const sellAmount = CurrencyAmount.fromRawAmount(order.inputToken, order.sellAmount.toString()) - const buyAmount = CurrencyAmount.fromRawAmount(order.outputToken, order.buyAmount.toString()) + const sellAmount = CurrencyAmount.fromRawAmount(order.inputToken, order.sellAmount) + const buyAmount = CurrencyAmount.fromRawAmount(order.outputToken, order.buyAmount) const rateInfoParams: RateInfoParams = { chainId, diff --git a/apps/cowswap-frontend/src/modules/ordersTable/utils/orderTableGroupUtils.ts b/apps/cowswap-frontend/src/modules/ordersTable/utils/orderTableGroupUtils.ts index 621ed72dd2..2f4db047ae 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/utils/orderTableGroupUtils.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/utils/orderTableGroupUtils.ts @@ -7,10 +7,11 @@ export interface OrderTableGroup { export type OrderTableItem = OrderTableGroup | ParsedOrder -export const isParsedOrder = (item: OrderTableItem): item is ParsedOrder => item.hasOwnProperty('creationTime') +export const isParsedOrder = (item: OrderTableItem): item is ParsedOrder => !('children' in item) -export const getParsedOrderFromItem = (item: OrderTableItem): ParsedOrder => (isParsedOrder(item) ? item : item.parent) +export const getParsedOrderFromTableItem = (item: OrderTableItem): ParsedOrder => + isParsedOrder(item) ? item : item.parent export function tableItemsToOrders(items: OrderTableItem[]): ParsedOrder[] { - return items.map(getParsedOrderFromItem) + return items.map(getParsedOrderFromTableItem) } diff --git a/apps/cowswap-frontend/src/modules/permit/const.ts b/apps/cowswap-frontend/src/modules/permit/const.ts index eeb9b673d0..516059f1f3 100644 --- a/apps/cowswap-frontend/src/modules/permit/const.ts +++ b/apps/cowswap-frontend/src/modules/permit/const.ts @@ -29,3 +29,5 @@ export const ORDER_TYPE_SUPPORTS_PERMIT: Record = { [TradeType.LIMIT_ORDER]: true, [TradeType.ADVANCED_ORDERS]: false, } + +export const PENDING_ORDER_PERMIT_CHECK_INTERVAL = ms`1min` diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts new file mode 100644 index 0000000000..6197865e15 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useCheckHasValidPendingPermit.ts @@ -0,0 +1,121 @@ +import { useCallback } from 'react' + +import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' +import { Web3Provider } from '@ethersproject/providers' +import { useWeb3React } from '@web3-react/core' + +import { DAI_PERMIT_SELECTOR, Eip2612PermitUtils, EIP_2612_PERMIT_SELECTOR } from '@1inch/permit-signed-approvals-utils' + +import { getAppDataHooks } from 'modules/appData' + +import { ParsedOrder } from 'utils/orderUtils/parseOrder' + +import { CheckHasValidPendingPermit } from '../types' +import { getPermitUtilsInstance } from '../utils/getPermitUtilsInstance' + +export function useCheckHasValidPendingPermit(): CheckHasValidPendingPermit { + const { chainId } = useWalletInfo() + const { provider } = useWeb3React() + + return useCallback( + async (order: ParsedOrder): Promise => { + if (!provider) { + // Missing required params, we can't tell + return undefined + } + + return checkHasValidPendingPermit(order, provider, chainId) + }, + [chainId, provider] + ) +} + +async function checkHasValidPendingPermit( + order: ParsedOrder, + provider: Web3Provider, + chainId: SupportedChainId +): Promise { + const { fullAppData, partiallyFillable, executionData } = order + const preHooks = getAppDataHooks(fullAppData)?.pre + + if ( + // No hooks === no permit + !preHooks || + // Permit is only executed for partially fillable orders in the first execution + // Thus, if there is any amount executed, partiallyFillable permit is no longer valid + (partiallyFillable && executionData.filledAmount.gt('0')) + ) { + // These cases we know for sure permit isn't valid or there is no permit + return false + } + + const eip2162Utils = getPermitUtilsInstance(chainId, provider, order.owner) + + const tokenAddress = order.inputToken.address + const tokenName = order.inputToken.name || tokenAddress + + const checkedHooks = await Promise.all( + preHooks.map(({ callData }) => + checkIsSingleCallDataAValidPermit(order, chainId, eip2162Utils, tokenAddress, tokenName, callData) + ) + ) + + const validPermits = checkedHooks.filter((v) => v !== undefined) + + if (!validPermits.length) { + // No permits means no preHook permits, we can say that there is no valid permit + return false + } + + // Only when all permits are valid, then the order permits are still valid + return validPermits.every(Boolean) +} + +async function checkIsSingleCallDataAValidPermit( + order: ParsedOrder, + chainId: SupportedChainId, + eip2162Utils: Eip2612PermitUtils, + tokenAddress: string, + tokenName: string, + callData: string +): Promise { + const params = { chainId, tokenName, tokenAddress, callData } + + let recoverPermitOwnerPromise: Promise | undefined = undefined + + // If pre-hook doesn't start with either selector, it's not a permit + if (callData.startsWith(EIP_2612_PERMIT_SELECTOR)) { + recoverPermitOwnerPromise = eip2162Utils.recoverPermitOwnerFromCallData({ + ...params, + // I don't know why this was removed, ok? + // We added it back on buildPermitCallData.ts + // But it looks like this is needed 🤷 + // Check the test for this method https://github.com/1inch/permit-signed-approvals-utils/blob/master/src/eip-2612-permit.test.ts#L85-L106 + callData: callData.replace(EIP_2612_PERMIT_SELECTOR, '0x'), + }) + } else if (callData.startsWith(DAI_PERMIT_SELECTOR)) { + recoverPermitOwnerPromise = eip2162Utils.recoverDaiLikePermitOwnerFromCallData({ + ...params, + callData: callData.replace(DAI_PERMIT_SELECTOR, '0x'), + }) + } + + if (!recoverPermitOwnerPromise) { + // The callData doesn't match any known permit type + return undefined + } + + try { + const recoveredOwner = await recoverPermitOwnerPromise + + // Permit is valid when recovered owner matches order owner + return recoveredOwner.toLowerCase() === order.owner.toLowerCase() + } catch (e) { + console.debug( + `[checkHasValidPendingPermit] Failed to check permit validity for order ${order.id} with callData ${callData}`, + e + ) + return false + } +} diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts index 0505914230..82edb237c0 100644 --- a/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts @@ -1,10 +1,15 @@ -import { useSetAtom } from 'jotai' +import { useAtomValue, useSetAtom } from 'jotai' import { useCallback } from 'react' import { useWalletInfo } from '@cowprotocol/wallet' import { useWeb3React } from '@web3-react/core' -import { getPermitCacheAtom, storePermitCacheAtom } from '../state/permitCacheAtom' +import { + getPermitCacheAtom, + staticPermitCacheAtom, + storePermitCacheAtom, + userPermitCacheAtom, +} from '../state/permitCacheAtom' import { GeneratePermitHook, GeneratePermitHookParams, PermitHookData } from '../types' import { generatePermitHook } from '../utils/generatePermitHook' import { getPermitUtilsInstance } from '../utils/getPermitUtilsInstance' @@ -15,6 +20,15 @@ import { getPermitUtilsInstance } from '../utils/getPermitUtilsInstance' export function useGeneratePermitHook(): GeneratePermitHook { const getCachedPermit = useSetAtom(getPermitCacheAtom) const storePermit = useSetAtom(storePermitCacheAtom) + + // Warming up stored atoms + // + // For some reason, atoms start always in the default state (`{}`) on load, + // even if localStorage contains data, wiping previously saved data. + // Here we force an individual read of each atom, which does populate them properly + useAtomValue(staticPermitCacheAtom) + useAtomValue(userPermitCacheAtom) + const { chainId } = useWalletInfo() const { provider } = useWeb3React() diff --git a/apps/cowswap-frontend/src/modules/permit/hooks/useOrdersPermitStatus.ts b/apps/cowswap-frontend/src/modules/permit/hooks/useOrdersPermitStatus.ts new file mode 100644 index 0000000000..b61aba3797 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/hooks/useOrdersPermitStatus.ts @@ -0,0 +1,7 @@ +import { useAtomValue } from 'jotai' + +import { ordersPermitStatusAtom } from '../state/ordersPermitStatusAtom' + +export function useGetOrdersPermitStatus() { + return useAtomValue(ordersPermitStatusAtom) +} diff --git a/apps/cowswap-frontend/src/modules/permit/index.ts b/apps/cowswap-frontend/src/modules/permit/index.ts index 5f70182cfc..9de2b7724e 100644 --- a/apps/cowswap-frontend/src/modules/permit/index.ts +++ b/apps/cowswap-frontend/src/modules/permit/index.ts @@ -1,5 +1,7 @@ export * from './hooks/useAccountAgnosticPermitHookData' -export * from './hooks/useIsTokenPermittable' export * from './hooks/useGeneratePermitHook' -export * from './utils/handlePermit' +export * from './hooks/useIsTokenPermittable' +export * from './hooks/useOrdersPermitStatus' export * from './types' +export * from './updaters/PendingPermitUpdater' +export * from './utils/handlePermit' diff --git a/apps/cowswap-frontend/src/modules/permit/state/ordersPermitStatusAtom.ts b/apps/cowswap-frontend/src/modules/permit/state/ordersPermitStatusAtom.ts new file mode 100644 index 0000000000..cf132cefc3 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/state/ordersPermitStatusAtom.ts @@ -0,0 +1,9 @@ +import { atom } from 'jotai' + +import { atomWithPartialUpdate } from '@cowprotocol/common-utils' + +import { OrdersPermitStatus } from '../types' + +export const { atom: ordersPermitStatusAtom, updateAtom: updateOrdersPermitStatusAtom } = atomWithPartialUpdate( + atom({}) +) diff --git a/apps/cowswap-frontend/src/modules/permit/types.ts b/apps/cowswap-frontend/src/modules/permit/types.ts index 5993a6fa67..d1cc15571f 100644 --- a/apps/cowswap-frontend/src/modules/permit/types.ts +++ b/apps/cowswap-frontend/src/modules/permit/types.ts @@ -7,6 +7,8 @@ import { Eip2612PermitUtils } from '@1inch/permit-signed-approvals-utils' import { AppDataInfo } from 'modules/appData' +import { ParsedOrder } from 'utils/orderUtils/parseOrder' + export type PermitType = 'dai-like' | 'eip-2612' export type SupportedPermitInfo = { @@ -92,3 +94,7 @@ export type PermitCacheKeyParams = { export type StorePermitCacheParams = PermitCacheKeyParams & { hookData: PermitHookData } export type GetPermitCacheParams = PermitCacheKeyParams + +export type CheckHasValidPendingPermit = (order: ParsedOrder) => Promise + +export type OrdersPermitStatus = Record diff --git a/apps/cowswap-frontend/src/modules/permit/updaters/PendingPermitUpdater.ts b/apps/cowswap-frontend/src/modules/permit/updaters/PendingPermitUpdater.ts new file mode 100644 index 0000000000..b286652ed9 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/permit/updaters/PendingPermitUpdater.ts @@ -0,0 +1,39 @@ +import { useSetAtom } from 'jotai' +import { useEffect, useRef } from 'react' + +import { ParsedOrder } from 'utils/orderUtils/parseOrder' + +import { PENDING_ORDER_PERMIT_CHECK_INTERVAL } from '../const' +import { useCheckHasValidPendingPermit } from '../hooks/useCheckHasValidPendingPermit' +import { updateOrdersPermitStatusAtom } from '../state/ordersPermitStatusAtom' + +export type PendingPermitUpdaterProps = { + orders: ParsedOrder[] +} + +export function PendingPermitUpdater({ orders }: PendingPermitUpdaterProps): null { + const ordersRef = useRef(orders) + ordersRef.current = orders + + const checkHasValidPendingPermit = useCheckHasValidPendingPermit() + const updateOrdersPermitStatus = useSetAtom(updateOrdersPermitStatusAtom) + + useEffect(() => { + const checkOrders = () => { + console.debug(`UpdatePendingPermit: checking orders`, ordersRef.current.length) + ordersRef.current.forEach((order) => { + checkHasValidPendingPermit(order).then((status) => { + console.debug(`UpdatePendingPermit: checked order ${order.id} with status ${status}`) + updateOrdersPermitStatus({ [order.id]: status }) + }) + }) + } + + checkOrders() + const interval = setInterval(checkOrders, PENDING_ORDER_PERMIT_CHECK_INTERVAL) + + return () => clearInterval(interval) + }, [checkHasValidPendingPermit, updateOrdersPermitStatus]) + + return null +} diff --git a/apps/cowswap-frontend/src/modules/tokens/hooks/useBalancesAndAllowances.ts b/apps/cowswap-frontend/src/modules/tokens/hooks/useBalancesAndAllowances.ts index 38dcbd6df8..7d16e34069 100644 --- a/apps/cowswap-frontend/src/modules/tokens/hooks/useBalancesAndAllowances.ts +++ b/apps/cowswap-frontend/src/modules/tokens/hooks/useBalancesAndAllowances.ts @@ -5,7 +5,7 @@ import { BalancesAndAllowances, BalancesAndAllowancesParams } from '../types' /** * Return the balances and allowances of the tokens. * - * This hooks is different than the useOnchainBalancesAndAllowance one in the fact that the user might contain some + * This hook is different from the useOnchainBalancesAndAllowance one in the fact that the user might contain some * un-commited transaction that might affect the balances. */ export function useBalancesAndAllowances(params: BalancesAndAllowancesParams): BalancesAndAllowances { diff --git a/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts b/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts index 126cb31acb..8a8f6c47c0 100644 --- a/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts +++ b/apps/cowswap-frontend/src/modules/wallet/utils/PermitProviderConnector.ts @@ -1,6 +1,7 @@ import { getContract } from '@cowprotocol/common-utils' import { defaultAbiCoder, ParamType } from '@ethersproject/abi' import { TypedDataField } from '@ethersproject/abstract-signer' +import { BigNumber } from '@ethersproject/bignumber' import type { Web3Provider } from '@ethersproject/providers' import { Wallet } from '@ethersproject/wallet' @@ -42,6 +43,31 @@ export class PermitProviderConnector implements ProviderConnector { return defaultAbiCoder.decode([type], hex)[0] } decodeABIParameters(types: AbiInput[], hex: string): T { - return defaultAbiCoder.decode(types as unknown as (ParamType | string)[], hex) as T + const decodedValues = defaultAbiCoder.decode(types as unknown as (ParamType | string)[], hex) as T + + // Ethersjs decodes numbers as BigNumber instances + // However, 1inch utils do not deal with BigNumber instances, + // so we need this mess to convert them to hex strings, which 1inch understands + // TODO: Any way to make this typing mess any cleaner? + if (decodedValues && typeof decodedValues === 'object') { + const copy: Record = {} + + Object.keys(decodedValues).forEach((key) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const value = decodedValues[key] + if (BigNumber.isBigNumber(value)) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + copy[key] = value.toHexString() + } else { + copy[key] = value + } + }) + + return copy as T + } + + return decodedValues } } diff --git a/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts b/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts index fec8eae063..a18121cfe9 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts @@ -48,6 +48,7 @@ export interface ParsedOrder { creationTime: Date expirationTime: Date composableCowInfo?: ComposableCowInfo + fullAppData: Order['fullAppData'] executionData: ParsedOrderExecutionData } @@ -110,6 +111,7 @@ export const parseOrder = (order: Order): ParsedOrder => { receiver: order.receiver || undefined, creationTime, expirationTime, + fullAppData: order.fullAppData, executionData, } } From 5de0df420ef988d880026cf7e56e66fa3c135393 Mon Sep 17 00:00:00 2001 From: Leandro Date: Wed, 11 Oct 2023 10:16:00 -0700 Subject: [PATCH 32/36] refactor(permit): refactor checkIsTokenPermittable (#3204) --- .../permit/utils/checkIsTokenPermittable.ts | 184 ++++++++++-------- 1 file changed, 104 insertions(+), 80 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts index 8eab04b4fc..6d7a05e65b 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts @@ -9,7 +9,7 @@ import { getPermitDeadline } from './getPermitDeadline' import { getPermitUtilsInstance } from './getPermitUtilsInstance' import { DEFAULT_PERMIT_VALUE, PERMIT_GAS_LIMIT_MIN, PERMIT_SIGNER } from '../const' -import { CheckIsTokenPermittableParams, EstimatePermitResult } from '../types' +import { CheckIsTokenPermittableParams, EstimatePermitResult, PermitType } from '../types' const EIP_2162_PERMIT_PARAMS = { value: DEFAULT_PERMIT_VALUE, @@ -56,97 +56,121 @@ async function actuallyCheckTokenIsPermittable(params: CheckIsTokenPermittablePa const owner = PERMIT_SIGNER.address + let nonce: number + try { - const nonce = await eip2612PermitUtils.getTokenNonce(tokenAddress, owner) + nonce = await eip2612PermitUtils.getTokenNonce(tokenAddress, owner) + } catch (e) { + console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${tokenAddress}`, e) - const data = await buildEip2162PermitCallData({ - eip2162Utils: eip2612PermitUtils, - callDataParams: [ - { - ...EIP_2162_PERMIT_PARAMS, - owner, - spender, - nonce, - }, - +chainId, - tokenName, - tokenAddress, - ], - }) + return false + } - const estimatedGas = await provider.estimateGas({ - data, - from: owner, - to: tokenAddress, - }) + const baseParams: BaseParams = { + chainId, + eip2612PermitUtils, + nonce, + spender, + tokenAddress, + tokenName, + walletAddress: owner, + } - const gasLimit = estimatedGas.toNumber() - - // Sometimes tokens implement the permit interface but don't actually implement it - // This check filters out possible cases where that happened by excluding - // gas limit which are bellow a minimum threshold - return gasLimit > PERMIT_GAS_LIMIT_MIN[chainId] - ? { - type: 'eip-2612', - gasLimit, - } - : false + try { + // Try to estimate with eip-2612 first + return await estimateTokenPermit({ ...baseParams, type: 'eip-2612', provider }) } catch (e) { + // Not eip-2612, try dai-like try { - return await estimateDaiLikeToken(tokenAddress, tokenName, chainId, owner, spender, provider, eip2612PermitUtils) + return await estimateTokenPermit({ ...baseParams, type: 'dai-like', provider }) } catch (e) { + // Not dai-like either, return error return { error: e.message || e.toString() } } } } -// TODO: refactor and make DAI like tokens work -function estimateDaiLikeToken( - tokenAddress: string, - tokenName: string, - chainId: SupportedChainId, - walletAddress: string, - spender: string, - provider: Web3Provider, +type BaseParams = { + tokenAddress: string + tokenName: string + chainId: SupportedChainId + walletAddress: string + spender: string eip2612PermitUtils: Eip2612PermitUtils -): Promise { - return eip2612PermitUtils.getPermitTypeHash(tokenAddress).then((permitTypeHash) => { - return permitTypeHash === DAI_LIKE_PERMIT_TYPEHASH - ? eip2612PermitUtils - .getTokenNonce(tokenAddress, walletAddress) - .then((nonce) => - buildDaiLikePermitCallData({ - eip2162Utils: eip2612PermitUtils, - callDataParams: [ - { - ...DAI_LIKE_PERMIT_PARAMS, - holder: walletAddress, - spender, - nonce, - }, - chainId as number, - tokenName, - tokenAddress, - ], - }) - ) - .then((data) => - provider.estimateGas({ - data, - from: walletAddress, - to: tokenAddress, - }) - ) - .then((res) => { - const gasLimit = res.toNumber() - - return gasLimit > PERMIT_GAS_LIMIT_MIN[chainId] - ? { - gasLimit, - type: 'dai-like', - } - : false - }) - : false + nonce: number +} + +type EstimateParams = BaseParams & { + type: PermitType + provider: Web3Provider +} + +async function estimateTokenPermit(params: EstimateParams) { + const { provider, chainId, walletAddress, tokenAddress, type } = params + + const getCallDataFn = type === 'eip-2612' ? getEip2612CallData : getDaiLikeCallData + + const data = await getCallDataFn(params) + + if (!data) { + return false + } + + const estimatedGas = await provider.estimateGas({ + data, + from: walletAddress, + to: tokenAddress, + }) + + const gasLimit = estimatedGas.toNumber() + + return gasLimit > PERMIT_GAS_LIMIT_MIN[chainId] + ? { + gasLimit, + type, + } + : false +} + +async function getEip2612CallData(params: BaseParams): Promise { + const { eip2612PermitUtils, walletAddress, spender, nonce, chainId, tokenName, tokenAddress } = params + return buildEip2162PermitCallData({ + eip2162Utils: eip2612PermitUtils, + callDataParams: [ + { + ...EIP_2162_PERMIT_PARAMS, + owner: walletAddress, + spender, + nonce, + }, + +chainId, + tokenName, + tokenAddress, + ], }) } + +async function getDaiLikeCallData(params: BaseParams): Promise { + const { eip2612PermitUtils, tokenAddress, walletAddress, spender, nonce, chainId, tokenName } = params + + const permitTypeHash = await eip2612PermitUtils.getPermitTypeHash(tokenAddress) + + if (permitTypeHash === DAI_LIKE_PERMIT_TYPEHASH) { + return buildDaiLikePermitCallData({ + eip2162Utils: eip2612PermitUtils, + callDataParams: [ + { + ...DAI_LIKE_PERMIT_PARAMS, + holder: walletAddress, + spender, + nonce, + }, + chainId as number, + tokenName, + tokenAddress, + ], + }) + } + + return false +} From 29e5178a4c15eb56568f5da0d0a30990a47bc76f Mon Sep 17 00:00:00 2001 From: Leandro Date: Thu, 12 Oct 2023 07:38:19 -0700 Subject: [PATCH 33/36] feat(permit): disable permit for SC wallets (#3213) --- .../src/common/hooks/featureFlags/useIsPermitEnabled.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsPermitEnabled.ts b/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsPermitEnabled.ts index 56dff4497e..04e42129b7 100644 --- a/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsPermitEnabled.ts +++ b/apps/cowswap-frontend/src/common/hooks/featureFlags/useIsPermitEnabled.ts @@ -1,10 +1,17 @@ import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useIsSmartContractWallet } from '@cowprotocol/wallet' import { useFeatureFlags } from './useFeatureFlags' export function useIsPermitEnabled(chainId: SupportedChainId | undefined): boolean { + const isSmartContractWallet = useIsSmartContractWallet() const { permitEnabledMainnet, permitEnabledGoerli, permitEnabledGnosis } = useFeatureFlags() + // Permit is only available for EOAs + if (isSmartContractWallet) { + return false + } + switch (chainId) { case SupportedChainId.MAINNET: return !!permitEnabledMainnet From 99df6d2ca9fd5040624977f385e03b2442587c15 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Mon, 16 Oct 2023 16:51:25 +0600 Subject: [PATCH 34/36] fix(swap): handle errors from order posting API (#3224) * fix(swap): handle errors from order posting API * chore: capitalize first letter of error * chore: move capitalizeFirstLetter to lib --- .../cowswap-frontend/src/api/gnosisProtocol/api.ts | 14 ++++---------- .../api/gnosisProtocol/getIsOrderBookTypedError.ts | 10 ++++++++++ .../src/api/gnosisProtocol/index.ts | 1 + .../src/modules/trade/utils/swapErrorHelper.ts | 12 ++++++++++-- libs/common-utils/src/capitalizeFirstLetter.ts | 5 +++++ libs/common-utils/src/index.ts | 1 + 6 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 apps/cowswap-frontend/src/api/gnosisProtocol/getIsOrderBookTypedError.ts create mode 100644 libs/common-utils/src/capitalizeFirstLetter.ts diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts b/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts index 87646e78ea..c4fa3e3061 100644 --- a/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts +++ b/apps/cowswap-frontend/src/api/gnosisProtocol/api.ts @@ -5,7 +5,6 @@ import { CowEnv, EnrichedOrder, NativePriceResponse, - OrderBookApiError, OrderKind, OrderQuoteRequest, OrderQuoteResponse, @@ -25,9 +24,11 @@ import { LegacyFeeQuoteParams as FeeQuoteParams } from 'legacy/state/price/types import { getAppData } from 'modules/appData' -import { ApiErrorCodes, ApiErrorObject } from 'api/gnosisProtocol/errors/OperatorError' +import { ApiErrorCodes } from 'api/gnosisProtocol/errors/OperatorError' import GpQuoteError, { GpQuoteErrorDetails, mapOperatorErrorToQuoteError } from 'api/gnosisProtocol/errors/QuoteError' +import { getIsOrderBookTypedError } from './getIsOrderBookTypedError' + function getProfileUrl(): Partial> { if (isLocal || isDev || isPr || isBarn) { return { @@ -165,7 +166,7 @@ export async function getQuote(params: FeeQuoteParams): Promise { - if (isOrderbookTypedError(error)) { + if (getIsOrderBookTypedError(error)) { const errorObject = mapOperatorErrorToQuoteError(error.body) return Promise.reject(errorObject ? new GpQuoteError(errorObject) : error) @@ -175,13 +176,6 @@ export async function getQuote(params: FeeQuoteParams): Promise - -function isOrderbookTypedError(e: any): e is OrderbookTypedError { - const error = e as OrderbookTypedError - return error.body.errorType !== undefined && error.body.description !== undefined -} - export async function getOrder(chainId: ChainId, orderId: string, env?: CowEnv): Promise { const contextOverride = { chainId, diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/getIsOrderBookTypedError.ts b/apps/cowswap-frontend/src/api/gnosisProtocol/getIsOrderBookTypedError.ts new file mode 100644 index 0000000000..61726597af --- /dev/null +++ b/apps/cowswap-frontend/src/api/gnosisProtocol/getIsOrderBookTypedError.ts @@ -0,0 +1,10 @@ +import { OrderBookApiError } from '@cowprotocol/cow-sdk' + +import { ApiErrorObject } from './errors/OperatorError' + +export type OrderBookTypedError = OrderBookApiError + +export function getIsOrderBookTypedError(e: any): e is OrderBookTypedError { + const error = e as OrderBookTypedError + return error.body.errorType !== undefined && error.body.description !== undefined +} diff --git a/apps/cowswap-frontend/src/api/gnosisProtocol/index.ts b/apps/cowswap-frontend/src/api/gnosisProtocol/index.ts index ede6377c72..901a8a4395 100644 --- a/apps/cowswap-frontend/src/api/gnosisProtocol/index.ts +++ b/apps/cowswap-frontend/src/api/gnosisProtocol/index.ts @@ -2,6 +2,7 @@ import * as realApi from './api' import * as mockApi from './mock' export type { UnsupportedToken, OrderID } from './api' +export { getIsOrderBookTypedError } from './getIsOrderBookTypedError' const useMock = process.env.REACT_APP_MOCK === 'true' diff --git a/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts b/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts index 9e9e4df301..14d0416ed8 100644 --- a/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts +++ b/apps/cowswap-frontend/src/modules/trade/utils/swapErrorHelper.ts @@ -1,4 +1,6 @@ -import { getProviderErrorMessage, isRejectRequestProviderError } from '@cowprotocol/common-utils' +import { capitalizeFirstLetter, getProviderErrorMessage, isRejectRequestProviderError } from '@cowprotocol/common-utils' + +import { getIsOrderBookTypedError } from 'api/gnosisProtocol' export const USER_SWAP_REJECTED_ERROR = 'User rejected signing the order' @@ -6,6 +8,12 @@ export function getSwapErrorMessage(error: Error): string { if (isRejectRequestProviderError(error)) { return USER_SWAP_REJECTED_ERROR } else { - return getProviderErrorMessage(error) + const defaultErrorMessage = getProviderErrorMessage(error) + + if (getIsOrderBookTypedError(error)) { + return capitalizeFirstLetter(error.body?.description) || defaultErrorMessage + } + + return defaultErrorMessage } } diff --git a/libs/common-utils/src/capitalizeFirstLetter.ts b/libs/common-utils/src/capitalizeFirstLetter.ts new file mode 100644 index 0000000000..263cb0ec2e --- /dev/null +++ b/libs/common-utils/src/capitalizeFirstLetter.ts @@ -0,0 +1,5 @@ +export function capitalizeFirstLetter(str: string): string { + if (!str) return str + + return str.charAt(0).toUpperCase() + str.slice(1) +} diff --git a/libs/common-utils/src/index.ts b/libs/common-utils/src/index.ts index 411a4ccc8b..ef8fd97326 100644 --- a/libs/common-utils/src/index.ts +++ b/libs/common-utils/src/index.ts @@ -50,4 +50,5 @@ export * from './getRandomInt' export * from './isEnoughAmount' export * from './tryParseFractionalAmount' export * from './maxAmountSpend' +export * from './capitalizeFirstLetter' export * from './jotai/atomWithPartialUpdate' From 79cb48aa9cd21689d64e13fe57044c4f345c4118 Mon Sep 17 00:00:00 2001 From: Leandro Date: Mon, 16 Oct 2023 03:51:44 -0700 Subject: [PATCH 35/36] fix(permit): improve permittable detection (#3226) * chore: return `false` only when it's a known failure * refactor: add return type * chore: improve permit detection logging * chore: update every package related to @web3-react/walletconnect-v2 - Removed @web3-react/walletconnect - Added @walletconnect/ethereum-provider as it's a dependency of @web3-react/walletconnect-v2 - Moved @web3-react/types to dev deps * chore: add more logging to permit utils creation * fix: lib @walletconnect/ethereum-provider path changed * fix: remove aliases no longer needed * fix: update async connector provider on network changes from wallet * chore: reduce some logging --------- Co-authored-by: Alexandr Kazachenko --- .../permit/utils/checkIsTokenPermittable.ts | 14 +- .../permit/utils/getPermitUtilsInstance.ts | 12 +- apps/cowswap-frontend/vite.config.ts | 14 - .../web3-react/connection/asyncConnector.ts | 5 + package.json | 22 +- ...lletconnect+universal-provider+2.9.2.patch | 11 - .../@web3-react+walletconnect-v2+8.3.7.patch | 13 - yarn.lock | 632 ++++-------------- 8 files changed, 185 insertions(+), 538 deletions(-) delete mode 100644 patches/@walletconnect+universal-provider+2.9.2.patch delete mode 100644 patches/@web3-react+walletconnect-v2+8.3.7.patch diff --git a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts index 6d7a05e65b..8093044c24 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/checkIsTokenPermittable.ts @@ -61,9 +61,17 @@ async function actuallyCheckTokenIsPermittable(params: CheckIsTokenPermittablePa try { nonce = await eip2612PermitUtils.getTokenNonce(tokenAddress, owner) } catch (e) { + if (e === 'nonce not supported' || e.message === 'nonce is NaN') { + console.debug(`[checkTokenIsPermittable] Not a permittable token ${tokenAddress}`, e?.message || e) + // Here we know it's not supported, return false + // See https://github.com/1inch/permit-signed-approvals-utils/blob/b190197a45c3289867ee4e6da93f10dea51ef276/src/eip-2612-permit.utils.ts#L309 + // and https://github.com/1inch/permit-signed-approvals-utils/blob/b190197a45c3289867ee4e6da93f10dea51ef276/src/eip-2612-permit.utils.ts#L325 + return false + } console.debug(`[checkTokenIsPermittable] Failed to get nonce for ${tokenAddress}`, e) - return false + // Otherwise, it might have been a network issue or another temporary failure, return error + return { error: e.message || e.toString() } } const baseParams: BaseParams = { @@ -81,10 +89,12 @@ async function actuallyCheckTokenIsPermittable(params: CheckIsTokenPermittablePa return await estimateTokenPermit({ ...baseParams, type: 'eip-2612', provider }) } catch (e) { // Not eip-2612, try dai-like + console.debug(`[checkTokenIsPermittable] Failed to estimate eip-2612 permit for ${tokenAddress}`, e) try { return await estimateTokenPermit({ ...baseParams, type: 'dai-like', provider }) } catch (e) { // Not dai-like either, return error + console.debug(`[checkTokenIsPermittable] Failed to estimate dai-like permit for ${tokenAddress}`, e) return { error: e.message || e.toString() } } } @@ -105,7 +115,7 @@ type EstimateParams = BaseParams & { provider: Web3Provider } -async function estimateTokenPermit(params: EstimateParams) { +async function estimateTokenPermit(params: EstimateParams): Promise { const { provider, chainId, walletAddress, tokenAddress, type } = params const getCallDataFn = type === 'eip-2612' ? getEip2612CallData : getDaiLikeCallData diff --git a/apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts b/apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts index 94d76191bf..daeba06d33 100644 --- a/apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts +++ b/apps/cowswap-frontend/src/modules/permit/utils/getPermitUtilsInstance.ts @@ -14,7 +14,7 @@ const CHAIN_UTILS_CACHE = new Map() /** * Cache by provider. Here we cache per provider as each account should have its own instance */ -const PROVIDER_UTILS_CACHE = new Map() +const PROVIDER_UTILS_CACHE = new Map() export function getPermitUtilsInstance( chainId: SupportedChainId, @@ -26,7 +26,8 @@ export function getPermitUtilsInstance( if (!account && chainCache) { return chainCache } - const providerCache = PROVIDER_UTILS_CACHE.get(provider) + const providerCacheKey = `${chainId}-${account}` + const providerCache = PROVIDER_UTILS_CACHE.get(providerCacheKey) if (providerCache) { return providerCache @@ -36,9 +37,14 @@ export function getPermitUtilsInstance( const eip2612PermitUtils = new Eip2612PermitUtils(web3ProviderConnector) if (!account) { + console.log(`[getPermitUtilsInstance] Set cached chain utils for chain ${chainId}`, eip2612PermitUtils) CHAIN_UTILS_CACHE.set(chainId, eip2612PermitUtils) } else { - PROVIDER_UTILS_CACHE.set(provider, eip2612PermitUtils) + console.log( + `[getPermitUtilsInstance] Set cached provider utils for chain ${chainId}-${account}`, + eip2612PermitUtils + ) + PROVIDER_UTILS_CACHE.set(providerCacheKey, eip2612PermitUtils) } return eip2612PermitUtils diff --git a/apps/cowswap-frontend/vite.config.ts b/apps/cowswap-frontend/vite.config.ts index 0a183f0aaa..ba713e5870 100644 --- a/apps/cowswap-frontend/vite.config.ts +++ b/apps/cowswap-frontend/vite.config.ts @@ -10,8 +10,6 @@ import { VitePWA } from 'vite-plugin-pwa' import svgr from 'vite-plugin-svgr' import viteTsConfigPaths from 'vite-tsconfig-paths' -import * as path from 'path' - import { getReactProcessEnv } from '../../tools/getReactProcessEnv' // eslint-disable-next-line no-restricted-imports @@ -102,18 +100,6 @@ export default defineConfig(({ mode }) => { resolve: { alias: { 'node-fetch': 'isomorphic-fetch', - /** - * Temporary fix for walletconnect - * https://github.com/Uniswap/web3-react/issues/861 - */ - '@walletconnect/ethereum-provider': path.resolve( - __dirname, - '../../node_modules/@walletconnect/ethereum-provider/dist/umd/index.min.js' - ), - '@walletconnect/universal-provider': path.resolve( - __dirname, - '../../node_modules/@walletconnect/universal-provider/dist/index.cjs.js' - ), }, }, diff --git a/libs/wallet/src/web3-react/connection/asyncConnector.ts b/libs/wallet/src/web3-react/connection/asyncConnector.ts index 566d6d4759..d8e2a3059a 100644 --- a/libs/wallet/src/web3-react/connection/asyncConnector.ts +++ b/libs/wallet/src/web3-react/connection/asyncConnector.ts @@ -11,6 +11,11 @@ function initCustomProvider(self: AsyncConnector, connector: Connector, chainId: } self.events.emit(ASYNC_CUSTOM_PROVIDER_EVENT, self.customProvider) + + // Update provider when network is changed on wallet side + connector.provider?.on('chainChanged', (chainIdHex: string) => { + initCustomProvider(self, connector, +chainIdHex) + }) } /** diff --git a/package.json b/package.json index 7ac20597d8..3bf56e0fe3 100644 --- a/package.json +++ b/package.json @@ -88,17 +88,16 @@ "@uniswap/sdk-core": "^3.0.1", "@uniswap/token-lists": "^1.0.0-beta.30", "@use-gesture/react": "^10.2.23", - "@web3-react/coinbase-wallet": "^8.2.0", - "@web3-react/core": "^8.2.0", - "@web3-react/eip1193": "^8.2.0", - "@web3-react/empty": "^8.2.0", - "@web3-react/gnosis-safe": "^8.2.0", - "@web3-react/metamask": "^8.2.1", - "@web3-react/network": "^8.2.0", - "@web3-react/types": "^8.2.0", - "@web3-react/url": "^8.2.0", - "@web3-react/walletconnect": "^8.2.0", - "@web3-react/walletconnect-v2": "^8.3.7", + "@walletconnect/ethereum-provider": "^2.10.2", + "@web3-react/coinbase-wallet": "^8.2.3", + "@web3-react/core": "^8.2.3", + "@web3-react/eip1193": "^8.2.3", + "@web3-react/empty": "^8.2.3", + "@web3-react/gnosis-safe": "^8.2.4", + "@web3-react/metamask": "^8.2.4", + "@web3-react/network": "^8.2.3", + "@web3-react/url": "^8.2.3", + "@web3-react/walletconnect-v2": "^8.5.1", "bnc-sdk": "^4.6.0", "buffer": "^6.0.3", "cids": "^1.0.0", @@ -214,6 +213,7 @@ "@vitejs/plugin-react-swc": "^3.3.2", "@vitest/coverage-c8": "~0.32.0", "@vitest/ui": "~0.32.0", + "@web3-react/types": "^8.2.3", "babel-jest": "^29.6.2", "babel-plugin-styled-components": "2.1.4", "babel-plugin-transform-import-meta": "^2.2.0", diff --git a/patches/@walletconnect+universal-provider+2.9.2.patch b/patches/@walletconnect+universal-provider+2.9.2.patch deleted file mode 100644 index 978361c8fa..0000000000 --- a/patches/@walletconnect+universal-provider+2.9.2.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff --git a/node_modules/@walletconnect/universal-provider/dist/index.cjs.js b/node_modules/@walletconnect/universal-provider/dist/index.cjs.js -index a8c3659..f6e93ff 100644 ---- a/node_modules/@walletconnect/universal-provider/dist/index.cjs.js -+++ b/node_modules/@walletconnect/universal-provider/dist/index.cjs.js -@@ -24,5 +24,5 @@ __p += '`),H&&(m+=`' + - function print() { __p += __j.call(arguments, '') } - `:`; - `)+m+`return __p --}`;var b=va(function(){return $(o,C+"return "+m).apply(i,f)});if(b.source=m,xi(b))throw b;return b}function Hd(n){return U(n).toLowerCase()}function $d(n){return U(n).toUpperCase()}function Ud(n,t,e){if(n=U(n),n&&(e||t===i))return Es(n);if(!n||!(t=pn(t)))return n;var r=On(n),s=On(t),o=ys(r,s),f=Ss(r,s)+1;return at(r,o,f).join("")}function Wd(n,t,e){if(n=U(n),n&&(e||t===i))return n.slice(0,Os(n)+1);if(!n||!(t=pn(t)))return n;var r=On(n),s=Ss(r,On(t))+1;return at(r,0,s).join("")}function Fd(n,t,e){if(n=U(n),n&&(e||t===i))return n.replace(xr,"");if(!n||!(t=pn(t)))return n;var r=On(n),s=ys(r,On(t));return at(r,s).join("")}function Md(n,t){var e=Ta,r=La;if(K(t)){var s="separator"in t?t.separator:s;e="length"in t?O(t.length):e,r="omission"in t?pn(t.omission):r}n=U(n);var o=n.length;if(Tt(n)){var f=On(n);o=f.length}if(e>=o)return n;var c=e-Lt(r);if(c<1)return r;var l=f?at(f,0,c).join(""):n.slice(0,c);if(s===i)return l+r;if(f&&(c+=l.length-c),Ei(s)){if(n.slice(c).search(s)){var v,_=l;for(s.global||(s=qr(s.source,U(Yi.exec(s))+"g")),s.lastIndex=0;v=s.exec(_);)var m=v.index;l=l.slice(0,m===i?c:m)}}else if(n.indexOf(pn(s),c)!=c){var w=l.lastIndexOf(s);w>-1&&(l=l.slice(0,w))}return l+r}function qd(n){return n=U(n),n&&Qa.test(n)?n.replace(Ki,vf):n}var Bd=Ft(function(n,t,e){return n+(e?" ":"")+t.toUpperCase()}),Ri=_u("toUpperCase");function ga(n,t,e){return n=U(n),t=e?i:t,t===i?hf(n)?wf(n):tf(n):n.match(t)||[]}var va=T(function(n,t){try{return hn(n,i,t)}catch(e){return xi(e)?e:new S(e)}}),Gd=Zn(function(n,t){return wn(t,function(e){e=Fn(e),Jn(n,e,Ci(n[e],n))}),n});function Kd(n){var t=n==null?0:n.length,e=x();return n=t?G(n,function(r){if(typeof r[1]!="function")throw new Pn(F);return[e(r[0]),r[1]]}):[],T(function(r){for(var s=-1;++sjn)return[];var e=$n,r=nn(n,$n);t=x(t),n-=$n;for(var s=Wr(r,t);++e0||t<0)?new N(e):(n<0?e=e.takeRight(-n):n&&(e=e.drop(n)),t!==i&&(t=O(t),e=t<0?e.dropRight(-t):e.take(t-n)),e)},N.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},N.prototype.toArray=function(){return this.take($n)},Un(N.prototype,function(n,t){var e=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),s=a[r?"take"+(t=="last"?"Right":""):t],o=r||/^find/.test(t);s&&(a.prototype[t]=function(){var f=this.__wrapped__,c=r?[1]:arguments,l=f instanceof N,v=c[0],_=l||R(f),m=function(L){var H=s.apply(a,tt([L],c));return r&&w?H[0]:H};_&&e&&typeof v=="function"&&v.length!=1&&(l=_=!1);var w=this.__chain__,C=!!this.__actions__.length,E=o&&!w,b=l&&!C;if(!o&&_){f=b?f:new N(this);var y=n.apply(f,c);return y.__actions__.push({func:tr,args:[m],thisArg:i}),new An(y,w)}return E&&b?n.apply(this,c):(y=this.thru(m),E?r?y.value()[0]:y.value():y)})}),wn(["pop","push","shift","sort","splice","unshift"],function(n){var t=Se[n],e=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",r=/^(?:pop|shift)$/.test(n);a.prototype[n]=function(){var s=arguments;if(r&&!this.__chain__){var o=this.value();return t.apply(R(o)?o:[],s)}return this[e](function(f){return t.apply(R(f)?f:[],s)})}}),Un(N.prototype,function(n,t){var e=a[t];if(e){var r=e.name+"";W.call($t,r)||($t[r]=[]),$t[r].push({name:t,func:e})}}),$t[Ze(i,ct).name]=[{name:"wrapper",func:i}],N.prototype.clone=qf,N.prototype.reverse=Bf,N.prototype.value=Gf,a.prototype.at=ml,a.prototype.chain=wl,a.prototype.commit=Pl,a.prototype.next=Al,a.prototype.plant=Il,a.prototype.reverse=xl,a.prototype.toJSON=a.prototype.valueOf=a.prototype.value=El,a.prototype.first=a.prototype.head,ne&&(a.prototype[ne]=Cl),a},Dt=Pf();lt?((lt.exports=Dt)._=Dt,br._=Dt):k._=Dt}).call(de)})($i,$i.exports);var Hg=Object.defineProperty,$g=Object.defineProperties,Ug=Object.getOwnPropertyDescriptors,xa=Object.getOwnPropertySymbols,Wg=Object.prototype.hasOwnProperty,Fg=Object.prototype.propertyIsEnumerable,Ea=(A,u,i)=>u in A?Hg(A,u,{enumerable:!0,configurable:!0,writable:!0,value:i}):A[u]=i,fr=(A,u)=>{for(var i in u||(u={}))Wg.call(u,i)&&Ea(A,i,u[i]);if(xa)for(var i of xa(u))Fg.call(u,i)&&Ea(A,i,u[i]);return A},Mg=(A,u)=>$g(A,Ug(u));function yn(A,u,i){let p;const I=Ui(A);return u.rpcMap&&(p=u.rpcMap[I]),p||(p=`${Ng}?chainId=eip155:${I}&projectId=${i}`),p}function Ui(A){return A.includes("eip155")?Number(A.split(":")[1]):Number(A)}function ya(A){return A.map(u=>`${u.split(":")[0]}:${u.split(":")[1]}`)}function qg(A,u){const i=Object.keys(u.namespaces).filter(I=>I.includes(A));if(!i.length)return[];const p=[];return i.forEach(I=>{const D=u.namespaces[I].accounts;p.push(...D)}),p}function Bg(A={},u={}){const i=Sa(A),p=Sa(u);return $i.exports.merge(i,p)}function Sa(A){var u,i,p,I;const D={};if(!cn.isValidObject(A))return D;for(const[F,Mn]of Object.entries(A)){const Kt=cn.isCaipNamespace(F)?[F]:Mn.chains,lr=Mn.methods||[],Ct=Mn.events||[],Dn=Mn.rpcMap||{},qn=cn.parseNamespaceKey(F);D[qn]=Mg(fr(fr({},D[qn]),Mn),{chains:cn.mergeArrays(Kt,(u=D[qn])==null?void 0:u.chains),methods:cn.mergeArrays(lr,(i=D[qn])==null?void 0:i.methods),events:cn.mergeArrays(Ct,(p=D[qn])==null?void 0:p.events),rpcMap:fr(fr({},Dn),(I=D[qn])==null?void 0:I.rpcMap)})}return D}function Gg(A){return A.includes(":")?A.split(":")[2]:A}function Kg(A){const u={};for(const[i,p]of Object.entries(A)){const I=p.methods||[],D=p.events||[],F=p.accounts||[],Mn=cn.isCaipNamespace(i)?[i]:p.chains?p.chains:ya(p.accounts);u[i]={chains:Mn,methods:I,events:D,accounts:F}}return u}const Ra={},Z=A=>Ra[A],Wi=(A,u)=>{Ra[A]=u};class zg{constructor(u){this.name="polkadot",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(this.chainId=u,!this.httpProviders[u]){const p=i||yn(`${this.name}:${u}`,this.namespace);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2])||[]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;u[i]=this.createHttpProvider(i,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||yn(u,this.namespace);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}class Jg{constructor(u){this.name="eip155",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.httpProviders=this.createHttpProviders(),this.chainId=parseInt(this.getDefaultChain())}async request(u){switch(u.request.method){case"eth_requestAccounts":return this.getAccounts();case"eth_accounts":return this.getAccounts();case"wallet_switchEthereumChain":return await this.handleSwitchChain(u);case"eth_chainId":return parseInt(this.getDefaultChain())}return this.namespace.methods.includes(u.request.method)?await this.client.request(u):this.getHttpProvider().request(u.request)}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}setDefaultChain(u,i){const p=Ui(u);if(!this.httpProviders[p]){const I=i||yn(`${this.name}:${p}`,this.namespace,this.client.core.projectId);if(!I)throw new Error(`No RPC url provided for chainId: ${p}`);this.setHttpProvider(p,I)}this.chainId=p,this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${p}`)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId.toString();if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}createHttpProvider(u,i){const p=i||yn(`${this.name}:${u}`,this.namespace,this.client.core.projectId);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Aa.HttpConnection(p,Z("disableProviderPing")))}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;const I=Ui(i);u[I]=this.createHttpProvider(I,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}getHttpProvider(){const u=this.chainId,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}async handleSwitchChain(u){var i,p;let I=u.request.params?(i=u.request.params[0])==null?void 0:i.chainId:"0x0";I=I.startsWith("0x")?I:`0x${I}`;const D=parseInt(I,16);if(this.isChainApproved(D))this.setDefaultChain(`${D}`);else if(this.namespace.methods.includes("wallet_switchEthereumChain"))await this.client.request({topic:u.topic,request:{method:u.request.method,params:[{chainId:I}]},chainId:(p=this.namespace.chains)==null?void 0:p[0]}),this.setDefaultChain(`${D}`);else throw new Error(`Failed to switch to chain 'eip155:${D}'. The chain is not approved or the wallet does not support 'wallet_switchEthereumChain' method.`);return null}isChainApproved(u){return this.namespace.chains.includes(`${this.name}:${u}`)}}class Yg{constructor(u){this.name="solana",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(!this.httpProviders[u]){const p=i||yn(`${this.name}:${u}`,this.namespace,this.client.core.projectId);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.chainId=u,this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;u[i]=this.createHttpProvider(i,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||yn(u,this.namespace,this.client.core.projectId);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}class Zg{constructor(u){this.name="cosmos",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(this.chainId=u,!this.httpProviders[u]){const p=i||yn(`${this.name}:${u}`,this.namespace,this.client.core.projectId);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;u[i]=this.createHttpProvider(i,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||yn(u,this.namespace,this.client.core.projectId);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}class Xg{constructor(u){this.name="cip34",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(this.chainId=u,!this.httpProviders[u]){const p=i||this.getCardanoRPCUrl(u);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{const p=this.getCardanoRPCUrl(i);u[i]=this.createHttpProvider(i,p)}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}getCardanoRPCUrl(u){const i=this.namespace.rpcMap;if(i)return i[u]}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||this.getCardanoRPCUrl(u);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}class Qg{constructor(u){this.name="elrond",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(!this.httpProviders[u]){const p=i||yn(`${this.name}:${u}`,this.namespace,this.client.core.projectId);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.chainId=u,this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;u[i]=this.createHttpProvider(i,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||yn(u,this.namespace,this.client.core.projectId);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}class Vg{constructor(u){this.name="multiversx",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(!this.httpProviders[u]){const p=i||yn(`${this.name}:${u}`,this.namespace,this.client.core.projectId);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.chainId=u,this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;u[i]=this.createHttpProvider(i,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||yn(u,this.namespace,this.client.core.projectId);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}var kg=Object.defineProperty,jg=Object.defineProperties,nv=Object.getOwnPropertyDescriptors,Oa=Object.getOwnPropertySymbols,tv=Object.prototype.hasOwnProperty,ev=Object.prototype.propertyIsEnumerable,ba=(A,u,i)=>u in A?kg(A,u,{enumerable:!0,configurable:!0,writable:!0,value:i}):A[u]=i,cr=(A,u)=>{for(var i in u||(u={}))tv.call(u,i)&&ba(A,i,u[i]);if(Oa)for(var i of Oa(u))ev.call(u,i)&&ba(A,i,u[i]);return A},Fi=(A,u)=>jg(A,nv(u));class hr{constructor(u){this.events=new bg.default,this.rpcProviders={},this.shouldAbortPairingAttempt=!1,this.maxPairingAttempts=10,this.disableProviderPing=!1,this.providerOpts=u,this.logger=typeof u?.logger<"u"&&typeof u?.logger!="string"?u.logger:Pa.pino(Pa.getDefaultLoggerOptions({level:u?.logger||Ca})),this.disableProviderPing=u?.disableProviderPing||!1}static async init(u){const i=new hr(u);return await i.initialize(),i}async request(u,i){const[p,I]=this.validateChain(i);if(!this.session)throw new Error("Please call connect() before request()");return await this.getProvider(p).request({request:cr({},u),chainId:`${p}:${I}`,topic:this.session.topic})}sendAsync(u,i,p){this.request(u,p).then(I=>i(null,I)).catch(I=>i(I,void 0))}async enable(){if(!this.client)throw new Error("Sign Client not initialized");return this.session||await this.connect({namespaces:this.namespaces,optionalNamespaces:this.optionalNamespaces,sessionProperties:this.sessionProperties}),await this.requestAccounts()}async disconnect(){var u;if(!this.session)throw new Error("Please call connect() before enable()");await this.client.disconnect({topic:(u=this.session)==null?void 0:u.topic,reason:cn.getSdkError("USER_DISCONNECTED")}),await this.cleanup()}async connect(u){if(!this.client)throw new Error("Sign Client not initialized");if(this.setNamespaces(u),await this.cleanupPendingPairings(),!u.skipPairing)return await this.pair(u.pairingTopic)}on(u,i){this.events.on(u,i)}once(u,i){this.events.once(u,i)}removeListener(u,i){this.events.removeListener(u,i)}off(u,i){this.events.off(u,i)}get isWalletConnect(){return!0}async pair(u){this.shouldAbortPairingAttempt=!1;let i=0;do{if(this.shouldAbortPairingAttempt)throw new Error("Pairing aborted");if(i>=this.maxPairingAttempts)throw new Error("Max auto pairing attempts reached");const{uri:p,approval:I}=await this.client.connect({pairingTopic:u,requiredNamespaces:this.namespaces,optionalNamespaces:this.optionalNamespaces,sessionProperties:this.sessionProperties});p&&(this.uri=p,this.events.emit("display_uri",p)),await I().then(D=>{this.session=D,this.namespaces||(this.namespaces=Kg(D.namespaces),this.persist("namespaces",this.namespaces))}).catch(D=>{if(D.message!==wa.PROPOSAL_EXPIRY_MESSAGE)throw D;i++})}while(!this.session);return this.onConnect(),this.session}setDefaultChain(u,i){try{if(!this.session)return;const[p,I]=this.validateChain(u);this.getProvider(p).setDefaultChain(I,i)}catch(p){if(!/Please call connect/.test(p.message))throw p}}async cleanupPendingPairings(u={}){this.logger.info("Cleaning up inactive pairings...");const i=this.client.pairing.getAll();if(cn.isValidArray(i)){for(const p of i)u.deletePairings?this.client.core.expirer.set(p.topic,0):await this.client.core.relayer.subscriber.unsubscribe(p.topic);this.logger.info(`Inactive pairings cleared: ${i.length}`)}}abortPairingAttempt(){this.shouldAbortPairingAttempt=!0}async checkStorage(){if(this.namespaces=await this.getFromStore("namespaces"),this.optionalNamespaces=await this.getFromStore("optionalNamespaces")||{},this.client.session.length){const u=this.client.session.keys.length-1;this.session=this.client.session.get(this.client.session.keys[u]),this.createProviders()}}async initialize(){this.logger.trace("Initialized"),await this.createClient(),await this.checkStorage(),this.registerEventListeners()}async createClient(){this.client=this.providerOpts.client||await Og.default.init({logger:this.providerOpts.logger||Ca,relayUrl:this.providerOpts.relayUrl||Tg,projectId:this.providerOpts.projectId,metadata:this.providerOpts.metadata,storageOptions:this.providerOpts.storageOptions,storage:this.providerOpts.storage,name:this.providerOpts.name}),this.logger.trace("SignClient Initialized")}createProviders(){if(!this.client)throw new Error("Sign Client not initialized");if(!this.session)throw new Error("Session not initialized. Please call connect() before enable()");const u=[...new Set(Object.keys(this.session.namespaces).map(i=>cn.parseNamespaceKey(i)))];Wi("client",this.client),Wi("events",this.events),Wi("disableProviderPing",this.disableProviderPing),u.forEach(i=>{if(!this.session)return;const p=qg(i,this.session),I=ya(p),D=Bg(this.namespaces,this.optionalNamespaces),F=Fi(cr({},D[i]),{accounts:p,chains:I});switch(i){case"eip155":this.rpcProviders[i]=new Jg({namespace:F});break;case"solana":this.rpcProviders[i]=new Yg({namespace:F});break;case"cosmos":this.rpcProviders[i]=new Zg({namespace:F});break;case"polkadot":this.rpcProviders[i]=new zg({namespace:F});break;case"cip34":this.rpcProviders[i]=new Xg({namespace:F});break;case"elrond":this.rpcProviders[i]=new Qg({namespace:F});break;case"multiversx":this.rpcProviders[i]=new Vg({namespace:F});break}})}registerEventListeners(){if(typeof this.client>"u")throw new Error("Sign Client is not initialized");this.client.on("session_ping",u=>{this.events.emit("session_ping",u)}),this.client.on("session_event",u=>{const{params:i}=u,{event:p}=i;if(p.name==="accountsChanged"){const I=p.data;I&&cn.isValidArray(I)&&this.events.emit("accountsChanged",I.map(Gg))}else p.name==="chainChanged"?this.onChainChanged(i.chainId):this.events.emit(p.name,p.data);this.events.emit("session_event",u)}),this.client.on("session_update",({topic:u,params:i})=>{var p;const{namespaces:I}=i,D=(p=this.client)==null?void 0:p.session.get(u);this.session=Fi(cr({},D),{namespaces:I}),this.onSessionUpdate(),this.events.emit("session_update",{topic:u,params:i})}),this.client.on("session_delete",async u=>{await this.cleanup(),this.events.emit("session_delete",u),this.events.emit("disconnect",Fi(cr({},cn.getSdkError("USER_DISCONNECTED")),{data:u.topic}))}),this.on(ft.DEFAULT_CHAIN_CHANGED,u=>{this.onChainChanged(u,!0)})}getProvider(u){if(!this.rpcProviders[u])throw new Error(`Provider not found: ${u}`);return this.rpcProviders[u]}onSessionUpdate(){Object.keys(this.rpcProviders).forEach(u=>{var i;this.getProvider(u).updateNamespace((i=this.session)==null?void 0:i.namespaces[u])})}setNamespaces(u){const{namespaces:i,optionalNamespaces:p,sessionProperties:I}=u;i&&Object.keys(i).length&&(this.namespaces=i),p&&Object.keys(p).length&&(this.optionalNamespaces=p),this.sessionProperties=I,this.persist("namespaces",i),this.persist("optionalNamespaces",p)}validateChain(u){const[i,p]=u?.split(":")||["",""];if(!this.namespaces||!Object.keys(this.namespaces).length)return[i,p];if(i&&!Object.keys(this.namespaces||{}).map(F=>cn.parseNamespaceKey(F)).includes(i))throw new Error(`Namespace '${i}' is not configured. Please call connect() first with namespace config.`);if(i&&p)return[i,p];const I=cn.parseNamespaceKey(Object.keys(this.namespaces)[0]),D=this.rpcProviders[I].getDefaultChain();return[I,D]}async requestAccounts(){const[u]=this.validateChain();return await this.getProvider(u).requestAccounts()}onChainChanged(u,i=!1){var p;if(!this.namespaces)return;const[I,D]=this.validateChain(u);i||this.getProvider(I).setDefaultChain(D),((p=this.namespaces[I])!=null?p:this.namespaces[`${I}:${D}`]).defaultChain=D,this.persist("namespaces",this.namespaces),this.events.emit("chainChanged",D)}onConnect(){this.createProviders(),this.events.emit("connect",{session:this.session})}async cleanup(){this.session=void 0,this.namespaces=void 0,this.optionalNamespaces=void 0,this.sessionProperties=void 0,this.persist("namespaces",void 0),this.persist("optionalNamespaces",void 0),this.persist("sessionProperties",void 0),await this.cleanupPendingPairings({deletePairings:!0})}persist(u,i){this.client.core.storage.setItem(`${Ia}/${u}`,i)}async getFromStore(u){return await this.client.core.storage.getItem(`${Ia}/${u}`)}}const rv=hr;exports.UniversalProvider=rv,exports.default=hr; -+}`;var b=va(function(){return $(o,C+"return "+m).apply(i,f)});if(b.source=m,xi(b))throw b;return b}function Hd(n){return U(n).toLowerCase()}function $d(n){return U(n).toUpperCase()}function Ud(n,t,e){if(n=U(n),n&&(e||t===i))return Es(n);if(!n||!(t=pn(t)))return n;var r=On(n),s=On(t),o=ys(r,s),f=Ss(r,s)+1;return at(r,o,f).join("")}function Wd(n,t,e){if(n=U(n),n&&(e||t===i))return n.slice(0,Os(n)+1);if(!n||!(t=pn(t)))return n;var r=On(n),s=Ss(r,On(t))+1;return at(r,0,s).join("")}function Fd(n,t,e){if(n=U(n),n&&(e||t===i))return n.replace(xr,"");if(!n||!(t=pn(t)))return n;var r=On(n),s=ys(r,On(t));return at(r,s).join("")}function Md(n,t){var e=Ta,r=La;if(K(t)){var s="separator"in t?t.separator:s;e="length"in t?O(t.length):e,r="omission"in t?pn(t.omission):r}n=U(n);var o=n.length;if(Tt(n)){var f=On(n);o=f.length}if(e>=o)return n;var c=e-Lt(r);if(c<1)return r;var l=f?at(f,0,c).join(""):n.slice(0,c);if(s===i)return l+r;if(f&&(c+=l.length-c),Ei(s)){if(n.slice(c).search(s)){var v,_=l;for(s.global||(s=qr(s.source,U(Yi.exec(s))+"g")),s.lastIndex=0;v=s.exec(_);)var m=v.index;l=l.slice(0,m===i?c:m)}}else if(n.indexOf(pn(s),c)!=c){var w=l.lastIndexOf(s);w>-1&&(l=l.slice(0,w))}return l+r}function qd(n){return n=U(n),n&&Qa.test(n)?n.replace(Ki,vf):n}var Bd=Ft(function(n,t,e){return n+(e?" ":"")+t.toUpperCase()}),Ri=_u("toUpperCase");function ga(n,t,e){return n=U(n),t=e?i:t,t===i?hf(n)?wf(n):tf(n):n.match(t)||[]}var va=T(function(n,t){try{return hn(n,i,t)}catch(e){return xi(e)?e:new S(e)}}),Gd=Zn(function(n,t){return wn(t,function(e){e=Fn(e),Jn(n,e,Ci(n[e],n))}),n});function Kd(n){var t=n==null?0:n.length,e=x();return n=t?G(n,function(r){if(typeof r[1]!="function")throw new Pn(F);return[e(r[0]),r[1]]}):[],T(function(r){for(var s=-1;++sjn)return[];var e=$n,r=nn(n,$n);t=x(t),n-=$n;for(var s=Wr(r,t);++e0||t<0)?new N(e):(n<0?e=e.takeRight(-n):n&&(e=e.drop(n)),t!==i&&(t=O(t),e=t<0?e.dropRight(-t):e.take(t-n)),e)},N.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},N.prototype.toArray=function(){return this.take($n)},Un(N.prototype,function(n,t){var e=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),s=a[r?"take"+(t=="last"?"Right":""):t],o=r||/^find/.test(t);s&&(a.prototype[t]=function(){var f=this.__wrapped__,c=r?[1]:arguments,l=f instanceof N,v=c[0],_=l||R(f),m=function(L){var H=s.apply(a,tt([L],c));return r&&w?H[0]:H};_&&e&&typeof v=="function"&&v.length!=1&&(l=_=!1);var w=this.__chain__,C=!!this.__actions__.length,E=o&&!w,b=l&&!C;if(!o&&_){f=b?f:new N(this);var y=n.apply(f,c);return y.__actions__.push({func:tr,args:[m],thisArg:i}),new An(y,w)}return E&&b?n.apply(this,c):(y=this.thru(m),E?r?y.value()[0]:y.value():y)})}),wn(["pop","push","shift","sort","splice","unshift"],function(n){var t=Se[n],e=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",r=/^(?:pop|shift)$/.test(n);a.prototype[n]=function(){var s=arguments;if(r&&!this.__chain__){var o=this.value();return t.apply(R(o)?o:[],s)}return this[e](function(f){return t.apply(R(f)?f:[],s)})}}),Un(N.prototype,function(n,t){var e=a[t];if(e){var r=e.name+"";W.call($t,r)||($t[r]=[]),$t[r].push({name:t,func:e})}}),$t[Ze(i,ct).name]=[{name:"wrapper",func:i}],N.prototype.clone=qf,N.prototype.reverse=Bf,N.prototype.value=Gf,a.prototype.at=ml,a.prototype.chain=wl,a.prototype.commit=Pl,a.prototype.next=Al,a.prototype.plant=Il,a.prototype.reverse=xl,a.prototype.toJSON=a.prototype.valueOf=a.prototype.value=El,a.prototype.first=a.prototype.head,ne&&(a.prototype[ne]=Cl),a},Dt=Pf();lt?((lt.exports=Dt)._=Dt,br._=Dt):k._=Dt}).call(de)})($i,$i.exports);var Hg=Object.defineProperty,$g=Object.defineProperties,Ug=Object.getOwnPropertyDescriptors,xa=Object.getOwnPropertySymbols,Wg=Object.prototype.hasOwnProperty,Fg=Object.prototype.propertyIsEnumerable,Ea=(A,u,i)=>u in A?Hg(A,u,{enumerable:!0,configurable:!0,writable:!0,value:i}):A[u]=i,fr=(A,u)=>{for(var i in u||(u={}))Wg.call(u,i)&&Ea(A,i,u[i]);if(xa)for(var i of xa(u))Fg.call(u,i)&&Ea(A,i,u[i]);return A},Mg=(A,u)=>$g(A,Ug(u));function yn(A,u,i){let p;const I=Ui(A);return u.rpcMap&&(p=u.rpcMap[I]),p||(p=`${Ng}?chainId=eip155:${I}&projectId=${i}`),p}function Ui(A){return A.includes("eip155")?Number(A.split(":")[1]):Number(A)}function ya(A){return A.map(u=>`${u.split(":")[0]}:${u.split(":")[1]}`)}function qg(A,u){const i=Object.keys(u.namespaces).filter(I=>I.includes(A));if(!i.length)return[];const p=[];return i.forEach(I=>{const D=u.namespaces[I].accounts;p.push(...D)}),p}function Bg(A={},u={}){const i=Sa(A),p=Sa(u);return $i.exports.merge(i,p)}function Sa(A){var u,i,p,I;const D={};if(!cn.isValidObject(A))return D;for(const[F,Mn]of Object.entries(A)){const Kt=cn.isCaipNamespace(F)?[F]:Mn.chains,lr=Mn.methods||[],Ct=Mn.events||[],Dn=Mn.rpcMap||{},qn=cn.parseNamespaceKey(F);D[qn]=Mg(fr(fr({},D[qn]),Mn),{chains:cn.mergeArrays(Kt,(u=D[qn])==null?void 0:u.chains),methods:cn.mergeArrays(lr,(i=D[qn])==null?void 0:i.methods),events:cn.mergeArrays(Ct,(p=D[qn])==null?void 0:p.events),rpcMap:fr(fr({},Dn),(I=D[qn])==null?void 0:I.rpcMap)})}return D}function Gg(A){return A.includes(":")?A.split(":")[2]:A}function Kg(A){const u={};for(const[i,p]of Object.entries(A)){const I=p.methods||[],D=p.events||[],F=p.accounts||[],Mn=cn.isCaipNamespace(i)?[i]:p.chains?p.chains:ya(p.accounts);u[i]={chains:Mn,methods:I,events:D,accounts:F}}return u}const Ra={},Z=A=>Ra[A],Wi=(A,u)=>{Ra[A]=u};class zg{constructor(u){this.name="polkadot",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(this.chainId=u,!this.httpProviders[u]){const p=i||yn(`${this.name}:${u}`,this.namespace);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2])||[]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;u[i]=this.createHttpProvider(i,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||yn(u,this.namespace);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}class Jg{constructor(u){this.name="eip155",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.httpProviders=this.createHttpProviders(),this.chainId=parseInt(this.getDefaultChain())}async request(u){switch(u.request.method){case"eth_requestAccounts":return this.getAccounts();case"eth_accounts":return this.getAccounts();case"wallet_switchEthereumChain":return await this.handleSwitchChain(u);case"eth_chainId":return parseInt(this.getDefaultChain())}return this.namespace.methods.includes(u.request.method)?await this.client.request(u):this.getHttpProvider().request(u.request)}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}setDefaultChain(u,i){const p=Ui(u);if(!this.httpProviders[p]){const I=i||yn(`${this.name}:${p}`,this.namespace,this.client.core.projectId);if(!I)throw new Error(`No RPC url provided for chainId: ${p}`);this.setHttpProvider(p,I)}this.chainId=p,this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${p}`)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId.toString();if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}createHttpProvider(u,i){const p=i||yn(`${this.name}:${u}`,this.namespace,this.client.core.projectId);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Aa.HttpConnection(p,Z("disableProviderPing")))}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;const I=Ui(i);u[I]=this.createHttpProvider(I,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}getHttpProvider(){const u=this.chainId,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}async handleSwitchChain(u){var i,p;let I=u.request.params?(i=u.request.params[0])==null?void 0:i.chainId:"0x0";I=I.startsWith("0x")?I:`0x${I}`;const D=parseInt(I,16);if(this.isChainApproved(D))this.setDefaultChain(`${D}`);else if(this.namespace.methods.includes("wallet_switchEthereumChain"))await this.client.request({topic:u.topic,request:{method:u.request.method,params:[{chainId:I}]},chainId:(p=this.namespace.chains)==null?void 0:p[0]}),this.setDefaultChain(`${D}`);else throw new Error(`Failed to switch to chain 'eip155:${D}'. The chain is not approved or the wallet does not support 'wallet_switchEthereumChain' method.`);return null}isChainApproved(u){return this.namespace.chains.includes(`${this.name}:${u}`)}}class Yg{constructor(u){this.name="solana",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(!this.httpProviders[u]){const p=i||yn(`${this.name}:${u}`,this.namespace,this.client.core.projectId);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.chainId=u,this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;u[i]=this.createHttpProvider(i,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||yn(u,this.namespace,this.client.core.projectId);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}class Zg{constructor(u){this.name="cosmos",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(this.chainId=u,!this.httpProviders[u]){const p=i||yn(`${this.name}:${u}`,this.namespace,this.client.core.projectId);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;u[i]=this.createHttpProvider(i,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||yn(u,this.namespace,this.client.core.projectId);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}class Xg{constructor(u){this.name="cip34",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(this.chainId=u,!this.httpProviders[u]){const p=i||this.getCardanoRPCUrl(u);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{const p=this.getCardanoRPCUrl(i);u[i]=this.createHttpProvider(i,p)}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}getCardanoRPCUrl(u){const i=this.namespace.rpcMap;if(i)return i[u]}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||this.getCardanoRPCUrl(u);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}class Qg{constructor(u){this.name="elrond",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(!this.httpProviders[u]){const p=i||yn(`${this.name}:${u}`,this.namespace,this.client.core.projectId);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.chainId=u,this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;u[i]=this.createHttpProvider(i,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||yn(u,this.namespace,this.client.core.projectId);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}class Vg{constructor(u){this.name="multiversx",this.namespace=u.namespace,this.events=Z("events"),this.client=Z("client"),this.chainId=this.getDefaultChain(),this.httpProviders=this.createHttpProviders()}updateNamespace(u){this.namespace=Object.assign(this.namespace,u)}requestAccounts(){return this.getAccounts()}request(u){return this.namespace.methods.includes(u.request.method)?this.client.request(u):this.getHttpProvider().request(u.request)}setDefaultChain(u,i){if(!this.httpProviders[u]){const p=i||yn(`${this.name}:${u}`,this.namespace,this.client.core.projectId);if(!p)throw new Error(`No RPC url provided for chainId: ${u}`);this.setHttpProvider(u,p)}this.chainId=u,this.events.emit(ft.DEFAULT_CHAIN_CHANGED,`${this.name}:${this.chainId}`)}getDefaultChain(){if(this.chainId)return this.chainId;if(this.namespace.defaultChain)return this.namespace.defaultChain;const u=this.namespace.chains[0];if(!u)throw new Error("ChainId not found");return u.split(":")[1]}getAccounts(){const u=this.namespace.accounts;return u?[...new Set(u.filter(i=>i.split(":")[1]===this.chainId.toString()).map(i=>i.split(":")[2]))]:[]}createHttpProviders(){const u={};return this.namespace.chains.forEach(i=>{var p;u[i]=this.createHttpProvider(i,(p=this.namespace.rpcMap)==null?void 0:p[i])}),u}getHttpProvider(){const u=`${this.name}:${this.chainId}`,i=this.httpProviders[u];if(typeof i>"u")throw new Error(`JSON-RPC provider for ${u} not found`);return i}setHttpProvider(u,i){const p=this.createHttpProvider(u,i);p&&(this.httpProviders[u]=p)}createHttpProvider(u,i){const p=i||yn(u,this.namespace,this.client.core.projectId);return typeof p>"u"?void 0:new At.JsonRpcProvider(new Gt.default(p,Z("disableProviderPing")))}}var kg=Object.defineProperty,jg=Object.defineProperties,nv=Object.getOwnPropertyDescriptors,Oa=Object.getOwnPropertySymbols,tv=Object.prototype.hasOwnProperty,ev=Object.prototype.propertyIsEnumerable,ba=(A,u,i)=>u in A?kg(A,u,{enumerable:!0,configurable:!0,writable:!0,value:i}):A[u]=i,cr=(A,u)=>{for(var i in u||(u={}))tv.call(u,i)&&ba(A,i,u[i]);if(Oa)for(var i of Oa(u))ev.call(u,i)&&ba(A,i,u[i]);return A},Fi=(A,u)=>jg(A,nv(u));class hr{constructor(u){this.events=new bg.default,this.rpcProviders={},this.shouldAbortPairingAttempt=!1,this.maxPairingAttempts=10,this.disableProviderPing=!1,this.providerOpts=u,this.logger=typeof u?.logger<"u"&&typeof u?.logger!="string"?u.logger:Pa.pino(Pa.getDefaultLoggerOptions({level:u?.logger||Ca})),this.disableProviderPing=u?.disableProviderPing||!1}static async init(u){const i=new hr(u);return await i.initialize(),i}async request(u,i){const[p,I]=this.validateChain(i);if(!this.session)throw new Error("Please call connect() before request()");return await this.getProvider(p).request({request:cr({},u),chainId:`${p}:${I}`,topic:this.session.topic})}sendAsync(u,i,p){this.request(u,p).then(I=>i(null,I)).catch(I=>i(I,void 0))}async enable(){if(!this.client)throw new Error("Sign Client not initialized");return this.session||await this.connect({namespaces:this.namespaces,optionalNamespaces:this.optionalNamespaces,sessionProperties:this.sessionProperties}),await this.requestAccounts()}async disconnect(){var u;if(!this.session)throw new Error("Please call connect() before enable()");await this.client.disconnect({topic:(u=this.session)==null?void 0:u.topic,reason:cn.getSdkError("USER_DISCONNECTED")}),await this.cleanup()}async connect(u){if(!this.client)throw new Error("Sign Client not initialized");if(this.setNamespaces(u),await this.cleanupPendingPairings(),!u.skipPairing)return await this.pair(u.pairingTopic)}on(u,i){this.events.on(u,i)}once(u,i){this.events.once(u,i)}removeListener(u,i){this.events.removeListener(u,i)}off(u,i){this.events.off(u,i)}get isWalletConnect(){return!0}async pair(u){this.shouldAbortPairingAttempt=!1;let i=0;do{if(this.shouldAbortPairingAttempt)throw new Error("Pairing aborted");if(i>=this.maxPairingAttempts)throw new Error("Max auto pairing attempts reached");const{uri:p,approval:I}=await this.client.connect({pairingTopic:u,requiredNamespaces:this.namespaces,optionalNamespaces:this.optionalNamespaces,sessionProperties:this.sessionProperties});p&&(this.uri=p,this.events.emit("display_uri",p)),await I().then(D=>{this.session=D,this.namespaces||(this.namespaces=Kg(D.namespaces),this.persist("namespaces",this.namespaces))}).catch(D=>{if(D.message!==wa.PROPOSAL_EXPIRY_MESSAGE)throw D;i++})}while(!this.session);return this.onConnect(),this.session}setDefaultChain(u,i){try{if(!this.session)return;const[p,I]=this.validateChain(u);this.getProvider(p).setDefaultChain(I,i)}catch(p){if(!/Please call connect/.test(p.message))throw p}}async cleanupPendingPairings(u={}){this.logger.info("Cleaning up inactive pairings...");const i=this.client.pairing.getAll();if(cn.isValidArray(i)){for(const p of i)u.deletePairings?this.client.core.expirer.set(p.topic,0):await this.client.core.relayer.subscriber.unsubscribe(p.topic);this.logger.info(`Inactive pairings cleared: ${i.length}`)}}abortPairingAttempt(){this.shouldAbortPairingAttempt=!0}async checkStorage(){if(this.namespaces=await this.getFromStore("namespaces"),this.optionalNamespaces=await this.getFromStore("optionalNamespaces")||{},this.client.session.length){const u=this.client.session.keys.length-1;this.session=this.client.session.get(this.client.session.keys[u]),this.createProviders()}}async initialize(){this.logger.trace("Initialized"),await this.createClient(),await this.checkStorage(),this.registerEventListeners()}async createClient(){this.client=this.providerOpts.client||await (Og.default.init || Og.default.default.init)({logger:this.providerOpts.logger||Ca,relayUrl:this.providerOpts.relayUrl||Tg,projectId:this.providerOpts.projectId,metadata:this.providerOpts.metadata,storageOptions:this.providerOpts.storageOptions,storage:this.providerOpts.storage,name:this.providerOpts.name}),this.logger.trace("SignClient Initialized")}createProviders(){if(!this.client)throw new Error("Sign Client not initialized");if(!this.session)throw new Error("Session not initialized. Please call connect() before enable()");const u=[...new Set(Object.keys(this.session.namespaces).map(i=>cn.parseNamespaceKey(i)))];Wi("client",this.client),Wi("events",this.events),Wi("disableProviderPing",this.disableProviderPing),u.forEach(i=>{if(!this.session)return;const p=qg(i,this.session),I=ya(p),D=Bg(this.namespaces,this.optionalNamespaces),F=Fi(cr({},D[i]),{accounts:p,chains:I});switch(i){case"eip155":this.rpcProviders[i]=new Jg({namespace:F});break;case"solana":this.rpcProviders[i]=new Yg({namespace:F});break;case"cosmos":this.rpcProviders[i]=new Zg({namespace:F});break;case"polkadot":this.rpcProviders[i]=new zg({namespace:F});break;case"cip34":this.rpcProviders[i]=new Xg({namespace:F});break;case"elrond":this.rpcProviders[i]=new Qg({namespace:F});break;case"multiversx":this.rpcProviders[i]=new Vg({namespace:F});break}})}registerEventListeners(){if(typeof this.client>"u")throw new Error("Sign Client is not initialized");this.client.on("session_ping",u=>{this.events.emit("session_ping",u)}),this.client.on("session_event",u=>{const{params:i}=u,{event:p}=i;if(p.name==="accountsChanged"){const I=p.data;I&&cn.isValidArray(I)&&this.events.emit("accountsChanged",I.map(Gg))}else p.name==="chainChanged"?this.onChainChanged(i.chainId):this.events.emit(p.name,p.data);this.events.emit("session_event",u)}),this.client.on("session_update",({topic:u,params:i})=>{var p;const{namespaces:I}=i,D=(p=this.client)==null?void 0:p.session.get(u);this.session=Fi(cr({},D),{namespaces:I}),this.onSessionUpdate(),this.events.emit("session_update",{topic:u,params:i})}),this.client.on("session_delete",async u=>{await this.cleanup(),this.events.emit("session_delete",u),this.events.emit("disconnect",Fi(cr({},cn.getSdkError("USER_DISCONNECTED")),{data:u.topic}))}),this.on(ft.DEFAULT_CHAIN_CHANGED,u=>{this.onChainChanged(u,!0)})}getProvider(u){if(!this.rpcProviders[u])throw new Error(`Provider not found: ${u}`);return this.rpcProviders[u]}onSessionUpdate(){Object.keys(this.rpcProviders).forEach(u=>{var i;this.getProvider(u).updateNamespace((i=this.session)==null?void 0:i.namespaces[u])})}setNamespaces(u){const{namespaces:i,optionalNamespaces:p,sessionProperties:I}=u;i&&Object.keys(i).length&&(this.namespaces=i),p&&Object.keys(p).length&&(this.optionalNamespaces=p),this.sessionProperties=I,this.persist("namespaces",i),this.persist("optionalNamespaces",p)}validateChain(u){const[i,p]=u?.split(":")||["",""];if(!this.namespaces||!Object.keys(this.namespaces).length)return[i,p];if(i&&!Object.keys(this.namespaces||{}).map(F=>cn.parseNamespaceKey(F)).includes(i))throw new Error(`Namespace '${i}' is not configured. Please call connect() first with namespace config.`);if(i&&p)return[i,p];const I=cn.parseNamespaceKey(Object.keys(this.namespaces)[0]),D=this.rpcProviders[I].getDefaultChain();return[I,D]}async requestAccounts(){const[u]=this.validateChain();return await this.getProvider(u).requestAccounts()}onChainChanged(u,i=!1){var p;if(!this.namespaces)return;const[I,D]=this.validateChain(u);i||this.getProvider(I).setDefaultChain(D),((p=this.namespaces[I])!=null?p:this.namespaces[`${I}:${D}`]).defaultChain=D,this.persist("namespaces",this.namespaces),this.events.emit("chainChanged",D)}onConnect(){this.createProviders(),this.events.emit("connect",{session:this.session})}async cleanup(){this.session=void 0,this.namespaces=void 0,this.optionalNamespaces=void 0,this.sessionProperties=void 0,this.persist("namespaces",void 0),this.persist("optionalNamespaces",void 0),this.persist("sessionProperties",void 0),await this.cleanupPendingPairings({deletePairings:!0})}persist(u,i){this.client.core.storage.setItem(`${Ia}/${u}`,i)}async getFromStore(u){return await this.client.core.storage.getItem(`${Ia}/${u}`)}}const rv=hr;exports.UniversalProvider=rv,exports.default=hr; - //# sourceMappingURL=index.cjs.js.map diff --git a/patches/@web3-react+walletconnect-v2+8.3.7.patch b/patches/@web3-react+walletconnect-v2+8.3.7.patch deleted file mode 100644 index c841e8394e..0000000000 --- a/patches/@web3-react+walletconnect-v2+8.3.7.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/node_modules/@web3-react/walletconnect-v2/dist/index.js b/node_modules/@web3-react/walletconnect-v2/dist/index.js -index b5bc5a9..cd92c3c 100644 ---- a/node_modules/@web3-react/walletconnect-v2/dist/index.js -+++ b/node_modules/@web3-react/walletconnect-v2/dist/index.js -@@ -83,7 +83,7 @@ class WalletConnect extends types_1.Connector { - return this.eagerConnection; - const rpcMap = this.rpcMap ? (0, utils_1.getBestUrlMap)(this.rpcMap, this.timeout) : undefined; - const chains = desiredChainId ? (0, utils_1.getChainsWithDefault)(this.chains, desiredChainId) : this.chains; -- return (this.eagerConnection = Promise.resolve().then(() => __importStar(require('@walletconnect/ethereum-provider'))).then((ethProviderModule) => __awaiter(this, void 0, void 0, function* () { -+ return (this.eagerConnection = Promise.resolve().then(() => __importStar(require('../node_modules/@walletconnect/ethereum-provider/dist/index.cjs'))).then((ethProviderModule) => __awaiter(this, void 0, void 0, function* () { - const provider = (this.provider = yield ethProviderModule.default.init(Object.assign(Object.assign({}, this.options), { chains, rpcMap: yield rpcMap }))); - return provider - .on('disconnect', this.disconnectListener) diff --git a/yarn.lock b/yarn.lock index e7e2220bf9..ba044c2b34 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3071,31 +3071,6 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@json-rpc-tools/provider@^1.5.5": - version "1.7.6" - resolved "https://registry.yarnpkg.com/@json-rpc-tools/provider/-/provider-1.7.6.tgz#8a17c34c493fa892632e278fd9331104e8491ec6" - integrity sha512-z7D3xvJ33UfCGv77n40lbzOYjZKVM3k2+5cV7xS8G6SCvKTzMkhkUYuD/qzQUNT4cG/lv0e9mRToweEEVLVVmA== - dependencies: - "@json-rpc-tools/utils" "^1.7.6" - axios "^0.21.0" - safe-json-utils "^1.1.1" - ws "^7.4.0" - -"@json-rpc-tools/types@^1.7.6": - version "1.7.6" - resolved "https://registry.yarnpkg.com/@json-rpc-tools/types/-/types-1.7.6.tgz#5abd5fde01364a130c46093b501715bcce5bdc0e" - integrity sha512-nDSqmyRNEqEK9TZHtM15uNnDljczhCUdBmRhpNZ95bIPKEDQ+nTDmGMFd2lLin3upc5h2VVVd9tkTDdbXUhDIQ== - dependencies: - keyvaluestorage-interface "^1.0.0" - -"@json-rpc-tools/utils@^1.7.6": - version "1.7.6" - resolved "https://registry.yarnpkg.com/@json-rpc-tools/utils/-/utils-1.7.6.tgz#67f04987dbaa2e7adb6adff1575367b75a9a9ba1" - integrity sha512-HjA8x/U/Q78HRRe19yh8HVKoZ+Iaoo3YZjakJYxR+rw52NHo6jM+VE9b8+7ygkCFXl/EHID5wh/MkXaE/jGyYw== - dependencies: - "@json-rpc-tools/types" "^1.7.6" - "@pedrouid/environment" "^1.0.1" - "@juggle/resize-observer@^3.3.1": version "3.4.0" resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" @@ -3952,11 +3927,6 @@ node-addon-api "^3.2.1" node-gyp-build "^4.3.0" -"@pedrouid/environment@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@pedrouid/environment/-/environment-1.0.1.tgz#858f0f8a057340e0b250398b75ead77d6f4342ec" - integrity sha512-HaW78NszGzRZd9SeoI3JD11JqY+lubnaOx7Pewj5pfjqWXOEATpeKIFb9Z4t2WBUK2iryiXX3lzWwmYWgUL0Ug== - "@phenomnomnominal/tsquery@~5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz#a2a5abc89f92c01562a32806655817516653a388" @@ -6860,31 +6830,10 @@ resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-1.6.0.tgz#eb992ad28dbaaab729b5bcab3e5b461e8a035656" integrity sha512-5FRlVxse5P4ZaHG3GTvxwVANSmYJas1eQrTBHhjxVtqXoorm0aLmCHbhmN8Xo1yu09PaWKlleEvfE98yH4AgIw== -"@walletconnect/browser-utils@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/browser-utils/-/browser-utils-1.8.0.tgz#33c10e777aa6be86c713095b5206d63d32df0951" - integrity sha512-Wcqqx+wjxIo9fv6eBUFHPsW1y/bGWWRboni5dfD8PtOmrihrEpOCmvRJe4rfl7xgJW8Ea9UqKEaq0bIRLHlK4A== - dependencies: - "@walletconnect/safe-json" "1.0.0" - "@walletconnect/types" "^1.8.0" - "@walletconnect/window-getters" "1.0.0" - "@walletconnect/window-metadata" "1.0.0" - detect-browser "5.2.0" - -"@walletconnect/client@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/client/-/client-1.8.0.tgz#6f46b5499c7c861c651ff1ebe5da5b66225ca696" - integrity sha512-svyBQ14NHx6Cs2j4TpkQaBI/2AF4+LXz64FojTjMtV4VMMhl81jSO1vNeg+yYhQzvjcGH/GpSwixjyCW0xFBOQ== - dependencies: - "@walletconnect/core" "^1.8.0" - "@walletconnect/iso-crypto" "^1.8.0" - "@walletconnect/types" "^1.8.0" - "@walletconnect/utils" "^1.8.0" - -"@walletconnect/core@2.9.2": - version "2.9.2" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.9.2.tgz#c46734ca63771b28fd77606fd521930b7ecfc5e1" - integrity sha512-VARMPAx8sIgodeyngDHbealP3B621PQqjqKsByFUTOep8ZI1/R/20zU+cmq6j9RCrL+kLKZcrZqeVzs8Z7OlqQ== +"@walletconnect/core@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.10.2.tgz#a1bf6e3e87b33f9df795ce0970d8ddd400fdc8a3" + integrity sha512-JQz/xp3SLEpTeRQctdck2ugSBVEpMxoSE+lFi2voJkZop1hv6P+uqr6E4PzjFluAjeAnKlT1xvra0aFWjPWVcw== dependencies: "@walletconnect/heartbeat" "1.2.1" "@walletconnect/jsonrpc-provider" "1.0.13" @@ -6897,42 +6846,12 @@ "@walletconnect/relay-auth" "^1.0.4" "@walletconnect/safe-json" "^1.0.2" "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.9.2" - "@walletconnect/utils" "2.9.2" + "@walletconnect/types" "2.10.2" + "@walletconnect/utils" "2.10.2" events "^3.3.0" lodash.isequal "4.5.0" uint8arrays "^3.1.0" -"@walletconnect/core@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-1.8.0.tgz#6b2748b90c999d9d6a70e52e26a8d5e8bfeaa81e" - integrity sha512-aFTHvEEbXcZ8XdWBw6rpQDte41Rxwnuk3SgTD8/iKGSRTni50gI9S3YEzMj05jozSiOBxQci4pJDMVhIUMtarw== - dependencies: - "@walletconnect/socket-transport" "^1.8.0" - "@walletconnect/types" "^1.8.0" - "@walletconnect/utils" "^1.8.0" - -"@walletconnect/crypto@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@walletconnect/crypto/-/crypto-1.0.3.tgz#7b8dd4d7e2884fe3543c7c07aea425eef5ef9dd4" - integrity sha512-+2jdORD7XQs76I2Odgr3wwrtyuLUXD/kprNVsjWRhhhdO9Mt6WqVzOPu0/t7OHSmgal8k7SoBQzUc5hu/8zL/g== - dependencies: - "@walletconnect/encoding" "^1.0.2" - "@walletconnect/environment" "^1.0.1" - "@walletconnect/randombytes" "^1.0.3" - aes-js "^3.1.2" - hash.js "^1.1.7" - tslib "1.14.1" - -"@walletconnect/encoding@^1.0.1", "@walletconnect/encoding@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@walletconnect/encoding/-/encoding-1.0.2.tgz#cb3942ad038d6a6bf01158f66773062dd25724da" - integrity sha512-CrwSBrjqJ7rpGQcTL3kU+Ief+Bcuu9PH6JLOb+wM6NITX1GTxR/MfNwnQfhLKK6xpRAyj2/nM04OOH6wS8Imag== - dependencies: - is-typedarray "1.0.0" - tslib "1.14.1" - typedarray-to-buffer "3.1.5" - "@walletconnect/environment@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@walletconnect/environment/-/environment-1.0.1.tgz#1d7f82f0009ab821a2ba5ad5e5a7b8ae3b214cd7" @@ -6940,33 +6859,19 @@ dependencies: tslib "1.14.1" -"@walletconnect/ethereum-provider@^1.7.8": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-1.8.0.tgz#ed1dbf9cecc3b818758a060d2f9017c50bde1d32" - integrity sha512-Nq9m+oo5P0F+njsROHw9KMWdoc/8iGHYzQdkjJN/1C7DtsqFRg5k5a3hd9rzCLpbPsOC1q8Z5lRs6JQgDvPm6Q== - dependencies: - "@walletconnect/client" "^1.8.0" - "@walletconnect/jsonrpc-http-connection" "^1.0.2" - "@walletconnect/jsonrpc-provider" "^1.0.5" - "@walletconnect/signer-connection" "^1.8.0" - "@walletconnect/types" "^1.8.0" - "@walletconnect/utils" "^1.8.0" - eip1193-provider "1.0.1" - eventemitter3 "4.0.7" - -"@walletconnect/ethereum-provider@^2.8.6": - version "2.9.2" - resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.9.2.tgz#fb3a6fca279bb4e98e75baa2fb9730545d41bb99" - integrity sha512-eO1dkhZffV1g7vpG19XUJTw09M/bwGUwwhy1mJ3AOPbOSbMPvwiCuRz2Kbtm1g9B0Jv15Dl+TvJ9vTgYF8zoZg== +"@walletconnect/ethereum-provider@^2.10.1", "@walletconnect/ethereum-provider@^2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.10.2.tgz#d5aca538fbcbbf7dd771bceb2430de30f06411de" + integrity sha512-QMYFZ6+rVq2CJLdIPdKK0j1Qm66UA27oQU5V2SrL8EVwl7wFfm0Bq7fnL+qAWeDpn612dNeNErpk/ROa1zWlWg== dependencies: "@walletconnect/jsonrpc-http-connection" "^1.0.7" "@walletconnect/jsonrpc-provider" "^1.0.13" "@walletconnect/jsonrpc-types" "^1.0.3" "@walletconnect/jsonrpc-utils" "^1.0.8" - "@walletconnect/sign-client" "2.9.2" - "@walletconnect/types" "2.9.2" - "@walletconnect/universal-provider" "2.9.2" - "@walletconnect/utils" "2.9.2" + "@walletconnect/sign-client" "2.10.2" + "@walletconnect/types" "2.10.2" + "@walletconnect/universal-provider" "2.10.2" + "@walletconnect/utils" "2.10.2" events "^3.3.0" "@walletconnect/events@^1.0.1": @@ -6986,16 +6891,7 @@ "@walletconnect/time" "^1.0.2" tslib "1.14.1" -"@walletconnect/iso-crypto@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/iso-crypto/-/iso-crypto-1.8.0.tgz#44ddf337c4f02837c062dbe33fa7ab36789df451" - integrity sha512-pWy19KCyitpfXb70hA73r9FcvklS+FvO9QUIttp3c2mfW8frxgYeRXfxLRCIQTkaYueRKvdqPjbyhPLam508XQ== - dependencies: - "@walletconnect/crypto" "^1.0.2" - "@walletconnect/types" "^1.8.0" - "@walletconnect/utils" "^1.8.0" - -"@walletconnect/jsonrpc-http-connection@^1.0.2", "@walletconnect/jsonrpc-http-connection@^1.0.7": +"@walletconnect/jsonrpc-http-connection@^1.0.7": version "1.0.7" resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.7.tgz#a6973569b8854c22da707a759d241e4f5c2d5a98" integrity sha512-qlfh8fCfu8LOM9JRR9KE0s0wxP6ZG9/Jom8M0qsoIQeKF3Ni0FyV4V1qy/cc7nfI46SLQLSl4tgWSfLiE1swyQ== @@ -7005,7 +6901,7 @@ cross-fetch "^3.1.4" tslib "1.14.1" -"@walletconnect/jsonrpc-provider@1.0.13", "@walletconnect/jsonrpc-provider@^1.0.13", "@walletconnect/jsonrpc-provider@^1.0.5": +"@walletconnect/jsonrpc-provider@1.0.13", "@walletconnect/jsonrpc-provider@^1.0.13": version "1.0.13" resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.13.tgz#9a74da648d015e1fffc745f0c7d629457f53648b" integrity sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g== @@ -7014,7 +6910,7 @@ "@walletconnect/safe-json" "^1.0.2" tslib "1.14.1" -"@walletconnect/jsonrpc-types@1.0.3", "@walletconnect/jsonrpc-types@^1.0.1", "@walletconnect/jsonrpc-types@^1.0.2", "@walletconnect/jsonrpc-types@^1.0.3": +"@walletconnect/jsonrpc-types@1.0.3", "@walletconnect/jsonrpc-types@^1.0.2", "@walletconnect/jsonrpc-types@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.3.tgz#65e3b77046f1a7fa8347ae02bc1b841abe6f290c" integrity sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw== @@ -7022,7 +6918,7 @@ keyvaluestorage-interface "^1.0.0" tslib "1.14.1" -"@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.3", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.7", "@walletconnect/jsonrpc-utils@^1.0.8": +"@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.7", "@walletconnect/jsonrpc-utils@^1.0.8": version "1.0.8" resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz#82d0cc6a5d6ff0ecc277cb35f71402c91ad48d72" integrity sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw== @@ -7058,57 +6954,30 @@ pino "7.11.0" tslib "1.14.1" -"@walletconnect/mobile-registry@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@walletconnect/mobile-registry/-/mobile-registry-1.4.0.tgz#502cf8ab87330841d794819081e748ebdef7aee5" - integrity sha512-ZtKRio4uCZ1JUF7LIdecmZt7FOLnX72RPSY7aUVu7mj7CSfxDwUn6gBuK6WGtH+NZCldBqDl5DenI5fFSvkKYw== - -"@walletconnect/modal-core@2.6.1": - version "2.6.1" - resolved "https://registry.yarnpkg.com/@walletconnect/modal-core/-/modal-core-2.6.1.tgz#bc76055d0b644a2d4b98024324825c108a700905" - integrity sha512-f2hYlJ5pwzGvjyaZ6BoGR5uiMgXzWXt6w6ktt1N8lmY6PiYp8whZgqx2hTxVWwVlsGnaIfh6UHp1hGnANx0eTQ== +"@walletconnect/modal-core@2.6.2": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@walletconnect/modal-core/-/modal-core-2.6.2.tgz#d73e45d96668764e0c8668ea07a45bb8b81119e9" + integrity sha512-cv8ibvdOJQv2B+nyxP9IIFdxvQznMz8OOr/oR/AaUZym4hjXNL/l1a2UlSQBXrVjo3xxbouMxLb3kBsHoYP2CA== dependencies: - valtio "1.11.0" + valtio "1.11.2" -"@walletconnect/modal-ui@2.6.1": - version "2.6.1" - resolved "https://registry.yarnpkg.com/@walletconnect/modal-ui/-/modal-ui-2.6.1.tgz#200c54c8dfe3c71321abb2724e18bb357dfd6371" - integrity sha512-RFUOwDAMijSK8B7W3+KoLKaa1l+KEUG0LCrtHqaB0H0cLnhEGdLR+kdTdygw+W8+yYZbkM5tXBm7MlFbcuyitA== +"@walletconnect/modal-ui@2.6.2": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@walletconnect/modal-ui/-/modal-ui-2.6.2.tgz#fa57c087c57b7f76aaae93deab0f84bb68b59cf9" + integrity sha512-rbdstM1HPGvr7jprQkyPggX7rP4XiCG85ZA+zWBEX0dVQg8PpAgRUqpeub4xQKDgY7pY/xLRXSiCVdWGqvG2HA== dependencies: - "@walletconnect/modal-core" "2.6.1" - lit "2.7.6" + "@walletconnect/modal-core" "2.6.2" + lit "2.8.0" motion "10.16.2" qrcode "1.5.3" -"@walletconnect/modal@^2.5.9": - version "2.6.1" - resolved "https://registry.yarnpkg.com/@walletconnect/modal/-/modal-2.6.1.tgz#066fdbfcff83b58c8a9da66ab4af0eb93e3626de" - integrity sha512-G84tSzdPKAFk1zimgV7JzIUFT5olZUVtI3GcOk77OeLYjlMfnDT23RVRHm5EyCrjkptnvpD0wQScXePOFd2Xcw== - dependencies: - "@walletconnect/modal-core" "2.6.1" - "@walletconnect/modal-ui" "2.6.1" - -"@walletconnect/qrcode-modal@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/qrcode-modal/-/qrcode-modal-1.8.0.tgz#ddd6f5c9b7ee52c16adf9aacec2a3eac4994caea" - integrity sha512-BueaFefaAi8mawE45eUtztg3ZFbsAH4DDXh1UNwdUlsvFMjqcYzLUG0xZvDd6z2eOpbgDg2N3bl6gF0KONj1dg== +"@walletconnect/modal@^2.6.2": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@walletconnect/modal/-/modal-2.6.2.tgz#4b534a836f5039eeb3268b80be7217a94dd12651" + integrity sha512-eFopgKi8AjKf/0U4SemvcYw9zlLpx9njVN8sf6DAkowC2Md0gPU/UNEbH1Wwj407pEKnEds98pKWib1NN1ACoA== dependencies: - "@walletconnect/browser-utils" "^1.8.0" - "@walletconnect/mobile-registry" "^1.4.0" - "@walletconnect/types" "^1.8.0" - copy-to-clipboard "^3.3.1" - preact "10.4.1" - qrcode "1.4.4" - -"@walletconnect/randombytes@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@walletconnect/randombytes/-/randombytes-1.0.3.tgz#e795e4918367fd1e6a2215e075e64ab93e23985b" - integrity sha512-35lpzxcHFbTN3ABefC9W+uBpNZl1GC4Wpx0ed30gibfO/y9oLdy1NznbV96HARQKSBV9J9M/rrtIvf6a23jfYw== - dependencies: - "@walletconnect/encoding" "^1.0.2" - "@walletconnect/environment" "^1.0.1" - randombytes "^2.1.0" - tslib "1.14.1" + "@walletconnect/modal-core" "2.6.2" + "@walletconnect/modal-ui" "2.6.2" "@walletconnect/relay-api@^1.0.9": version "1.0.9" @@ -7130,11 +6999,6 @@ tslib "1.14.1" uint8arrays "^3.0.0" -"@walletconnect/safe-json@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.0.tgz#12eeb11d43795199c045fafde97e3c91646683b2" - integrity sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg== - "@walletconnect/safe-json@^1.0.1", "@walletconnect/safe-json@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.2.tgz#7237e5ca48046e4476154e503c6d3c914126fa77" @@ -7142,42 +7006,21 @@ dependencies: tslib "1.14.1" -"@walletconnect/sign-client@2.9.2": - version "2.9.2" - resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.9.2.tgz#ff4c81c082c2078878367d07f24bcb20b1f7ab9e" - integrity sha512-anRwnXKlR08lYllFMEarS01hp1gr6Q9XUgvacr749hoaC/AwGVlxYFdM8+MyYr3ozlA+2i599kjbK/mAebqdXg== +"@walletconnect/sign-client@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.10.2.tgz#33300a9cfe42487473f66b73c99535f6b26f8c54" + integrity sha512-vviSLV3f92I0bReX+OLr1HmbH0uIzYEQQFd1MzIfDk9PkfFT/LLAHhUnDaIAMkIdippqDcJia+5QEtT4JihL3Q== dependencies: - "@walletconnect/core" "2.9.2" + "@walletconnect/core" "2.10.2" "@walletconnect/events" "^1.0.1" "@walletconnect/heartbeat" "1.2.1" "@walletconnect/jsonrpc-utils" "1.0.8" "@walletconnect/logger" "^2.0.1" "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.9.2" - "@walletconnect/utils" "2.9.2" + "@walletconnect/types" "2.10.2" + "@walletconnect/utils" "2.10.2" events "^3.3.0" -"@walletconnect/signer-connection@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/signer-connection/-/signer-connection-1.8.0.tgz#6cdf490df770e504cc1a550bdb5bac7696b130bc" - integrity sha512-+YAaTAP52MWZJ2wWnqKClKCPlPHBo6reURFe0cWidLADh9mi/kPWGALZ5AENK22zpem1bbKV466rF5Rzvu0ehA== - dependencies: - "@walletconnect/client" "^1.8.0" - "@walletconnect/jsonrpc-types" "^1.0.1" - "@walletconnect/jsonrpc-utils" "^1.0.3" - "@walletconnect/qrcode-modal" "^1.8.0" - "@walletconnect/types" "^1.8.0" - eventemitter3 "4.0.7" - -"@walletconnect/socket-transport@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/socket-transport/-/socket-transport-1.8.0.tgz#9a1128a249628a0be11a0979b522fe82b44afa1b" - integrity sha512-5DyIyWrzHXTcVp0Vd93zJ5XMW61iDM6bcWT4p8DTRfFsOtW46JquruMhxOLeCOieM4D73kcr3U7WtyR4JUsGuQ== - dependencies: - "@walletconnect/types" "^1.8.0" - "@walletconnect/utils" "^1.8.0" - ws "7.5.3" - "@walletconnect/time@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@walletconnect/time/-/time-1.0.2.tgz#6c5888b835750ecb4299d28eecc5e72c6d336523" @@ -7185,10 +7028,10 @@ dependencies: tslib "1.14.1" -"@walletconnect/types@2.9.2": - version "2.9.2" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.9.2.tgz#d5fd5a61dc0f41cbdca59d1885b85207ac7bf8c5" - integrity sha512-7Rdn30amnJEEal4hk83cdwHUuxI1SWQ+K7fFFHBMqkuHLGi3tpMY6kpyfDxnUScYEZXqgRps4Jo5qQgnRqVM7A== +"@walletconnect/types@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.10.2.tgz#68e433a29ec2cf42d79d8b50c77bd5c1d91db721" + integrity sha512-luNV+07Wdla4STi9AejseCQY31tzWKQ5a7C3zZZaRK/di+rFaAAb7YW04OP4klE7tw/mJRGPTlekZElmHxO8kQ== dependencies: "@walletconnect/events" "^1.0.1" "@walletconnect/heartbeat" "1.2.1" @@ -7197,30 +7040,25 @@ "@walletconnect/logger" "^2.0.1" events "^3.3.0" -"@walletconnect/types@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.8.0.tgz#3f5e85b2d6b149337f727ab8a71b8471d8d9a195" - integrity sha512-Cn+3I0V0vT9ghMuzh1KzZvCkiAxTq+1TR2eSqw5E5AVWfmCtECFkVZBP6uUJZ8YjwLqXheI+rnjqPy7sVM4Fyg== - -"@walletconnect/universal-provider@2.9.2": - version "2.9.2" - resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.9.2.tgz#40e54e98bc48b1f2f5f77eb5b7f05462093a8506" - integrity sha512-JmaolkO8D31UdRaQCHwlr8uIFUI5BYhBzqYFt54Mc6gbIa1tijGOmdyr6YhhFO70LPmS6gHIjljwOuEllmlrxw== +"@walletconnect/universal-provider@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.10.2.tgz#85c8da39f65da8fe33f65f62689e703607b5ddc5" + integrity sha512-wFgI0LbQ3D56sgaUMsgOHCM5m8WLxiC71BGuCKQfApgsbNMVKugYVy2zWHyUyi8sqTQHI+uSaVpDev4UHq9LEw== dependencies: "@walletconnect/jsonrpc-http-connection" "^1.0.7" "@walletconnect/jsonrpc-provider" "1.0.13" "@walletconnect/jsonrpc-types" "^1.0.2" "@walletconnect/jsonrpc-utils" "^1.0.7" "@walletconnect/logger" "^2.0.1" - "@walletconnect/sign-client" "2.9.2" - "@walletconnect/types" "2.9.2" - "@walletconnect/utils" "2.9.2" + "@walletconnect/sign-client" "2.10.2" + "@walletconnect/types" "2.10.2" + "@walletconnect/utils" "2.10.2" events "^3.3.0" -"@walletconnect/utils@2.9.2": - version "2.9.2" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.9.2.tgz#035bdb859ee81a4bcc6420f56114cc5ec3e30afb" - integrity sha512-D44hwXET/8JhhIjqljY6qxSu7xXnlPrf63UN/Qfl98vDjWlYVcDl2+JIQRxD9GPastw0S8XZXdRq59XDXLuZBg== +"@walletconnect/utils@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.10.2.tgz#1f2c6a2f1bb95bcc4517b1e94aa7164c9286eb46" + integrity sha512-syxXRpc2yhSknMu3IfiBGobxOY7fLfLTJuw+ppKaeO6WUdZpIit3wfuGOcc0Ms3ZPFCrGfyGOoZsCvgdXtptRg== dependencies: "@stablelib/chacha20poly1305" "1.0.1" "@stablelib/hkdf" "1.0.1" @@ -7230,45 +7068,20 @@ "@walletconnect/relay-api" "^1.0.9" "@walletconnect/safe-json" "^1.0.2" "@walletconnect/time" "^1.0.2" - "@walletconnect/types" "2.9.2" + "@walletconnect/types" "2.10.2" "@walletconnect/window-getters" "^1.0.1" "@walletconnect/window-metadata" "^1.0.1" detect-browser "5.3.0" query-string "7.1.3" uint8arrays "^3.1.0" -"@walletconnect/utils@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-1.8.0.tgz#2591a197c1fa7429941fe428876088fda6632060" - integrity sha512-zExzp8Mj1YiAIBfKNm5u622oNw44WOESzo6hj+Q3apSMIb0Jph9X3GDIdbZmvVZsNPxWDL7uodKgZcCInZv2vA== - dependencies: - "@walletconnect/browser-utils" "^1.8.0" - "@walletconnect/encoding" "^1.0.1" - "@walletconnect/jsonrpc-utils" "^1.0.3" - "@walletconnect/types" "^1.8.0" - bn.js "4.11.8" - js-sha3 "0.8.0" - query-string "6.13.5" - -"@walletconnect/window-getters@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.0.tgz#1053224f77e725dfd611c83931b5f6c98c32bfc8" - integrity sha512-xB0SQsLaleIYIkSsl43vm8EwETpBzJ2gnzk7e0wMF3ktqiTGS6TFHxcprMl5R44KKh4tCcHCJwolMCaDSwtAaA== - -"@walletconnect/window-getters@^1.0.0", "@walletconnect/window-getters@^1.0.1": +"@walletconnect/window-getters@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.1.tgz#f36d1c72558a7f6b87ecc4451fc8bd44f63cbbdc" integrity sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q== dependencies: tslib "1.14.1" -"@walletconnect/window-metadata@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.0.tgz#93b1cc685e6b9b202f29c26be550fde97800c4e5" - integrity sha512-9eFvmJxIKCC3YWOL97SgRkKhlyGXkrHwamfechmqszbypFspaSk+t2jQXAEU7YClHF6Qjw5eYOmy1//zFi9/GA== - dependencies: - "@walletconnect/window-getters" "^1.0.0" - "@walletconnect/window-metadata@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz#2124f75447b7e989e4e4e1581d55d25bc75f7be5" @@ -7277,105 +7090,96 @@ "@walletconnect/window-getters" "^1.0.1" tslib "1.14.1" -"@web3-react/coinbase-wallet@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@web3-react/coinbase-wallet/-/coinbase-wallet-8.2.0.tgz#038bb9e915834046320621aa49db5ba79130e488" - integrity sha512-SFPrsRbyw1gECyKJmE/TAB3iMhHAqh9DTa8X2FKPMgPyNPVPcha4+G0SuWy55rysh0MO6TJbj9pofX3HvXaYpw== +"@web3-react/coinbase-wallet@^8.2.3": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@web3-react/coinbase-wallet/-/coinbase-wallet-8.2.3.tgz#08d9ae9c9d15313a58f0bc33d970c73b0aaf813a" + integrity sha512-hYrOwv0RzhwQuI87GBv9ZHAblgrFg7YomnObOyuH2tPZT8+cQAtgP4D293TDQhW9SR1NXxzoS0tbTECWd4yUAQ== dependencies: - "@web3-react/types" "^8.2.0" + "@web3-react/types" "^8.2.3" -"@web3-react/core@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@web3-react/core/-/core-8.2.0.tgz#95fb615bb283be520e6f61b5e48cfb0047943808" - integrity sha512-r7dmK2E8Jrpvm/DF93hGMB+8lECHSI3Oo0NrHbhxkisK6in6rdgAXeYFhZtM48LBAm9py6fQvLzjCM6Qx9q0oQ== +"@web3-react/core@^8.2.3": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@web3-react/core/-/core-8.2.3.tgz#142899e74401bfd3a481a1b9578b2fd8f9dfde81" + integrity sha512-0ezmRKhqQpoa9ct2/3erg60zBXfC/f/liYR1mfSGKtIroRkLnPARigZSV6pI+fi8bhfGJ0RKtFWyTCCWZzdq1w== dependencies: - "@web3-react/store" "^8.2.0" - "@web3-react/types" "^8.2.0" - zustand "^4.3.5" + "@web3-react/store" "^8.2.3" + "@web3-react/types" "^8.2.3" + zustand "4.4.0" optionalDependencies: "@ethersproject/providers" "^5" -"@web3-react/eip1193@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@web3-react/eip1193/-/eip1193-8.2.0.tgz#a7953769f9d0bec54472aceb01f72c889458378f" - integrity sha512-Ugbt+FisHO8aLD5o5B4AZdtgSVpjrbmtC5MgHrOEBw+IwFqr20EJreh052u8ExI2OrPjARIVOkNcp50Xxs7oUw== +"@web3-react/eip1193@^8.2.3": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@web3-react/eip1193/-/eip1193-8.2.3.tgz#d09d5a5ea98719010eb7dd845631acb1f15c51e5" + integrity sha512-PdL8PCv3zgQrnowRlBK7PIO8G7v/nc31PYgarACo8mX+l5Y4+l7+ma/kpkULXp5yLtc4qlQYlCalmXpcbtl2FA== dependencies: - "@web3-react/types" "^8.2.0" + "@web3-react/types" "^8.2.3" eventemitter3 "^4.0.7" -"@web3-react/empty@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@web3-react/empty/-/empty-8.2.0.tgz#dac248ab22867700b5be716cd5a3f8f95308e8c5" - integrity sha512-U8BIF56lW1GHXFz9cPAJnlmKM8VcsjpXr+LXNXGS+9mr5AEjNcjbn9T9EnQf4hY4YXUPHAnjsVcZoUfw3q6u7Q== +"@web3-react/empty@^8.2.3": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@web3-react/empty/-/empty-8.2.3.tgz#70a0b07d7918a1f10c6dc4001b9fefc2f72face8" + integrity sha512-Uopeac2XgyJLmK8EawNmG1kferlSvklKgWzbianygriC3C3+6yHvflUBmHzYfcpZDq5gotP4JJr2bmhGAocQ5w== dependencies: - "@web3-react/types" "^8.2.0" + "@web3-react/types" "^8.2.3" -"@web3-react/gnosis-safe@^8.2.0": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@web3-react/gnosis-safe/-/gnosis-safe-8.2.1.tgz#c38601b2bd8c1a30691f9562693bc6e1b199e113" - integrity sha512-e4m6IphnnR3ENUnIL63GTN3uZGMdsb2V1uomJrbGtgcnZm/yM3/cea0f9J07+eF7zM6rIdad9NSbeivZQiiyOQ== +"@web3-react/gnosis-safe@^8.2.4": + version "8.2.4" + resolved "https://registry.yarnpkg.com/@web3-react/gnosis-safe/-/gnosis-safe-8.2.4.tgz#1f595a64bd26506a2e537b8a6734b5bf243d4e36" + integrity sha512-4M0CFludHJXtLsKJlKBIeMZcdTO60e6psYhYm2GLy76do9K9JJvBE8U4YVFBHLpk7sWpySsrCuYcaVZyzZ/xtA== dependencies: "@safe-global/safe-apps-provider" "^0.17.1" "@safe-global/safe-apps-sdk" "^8.0.0" - "@web3-react/types" "^8.2.0" + "@web3-react/types" "^8.2.3" -"@web3-react/metamask@^8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@web3-react/metamask/-/metamask-8.2.1.tgz#7ffac16e2a55ff8f1195e2831a9f9f99fa0bfba9" - integrity sha512-JysxkAImIygkD95Bimrj7HwcTq79tq4ZSlphZt24LBMrEVY5K8k+e5mCAuJuDZ7Fu+aBxqpS0lgPjaBGKdNu/A== +"@web3-react/metamask@^8.2.4": + version "8.2.4" + resolved "https://registry.yarnpkg.com/@web3-react/metamask/-/metamask-8.2.4.tgz#26438222c4b17964c011ea359058ba6feb6a2330" + integrity sha512-4yoqDgvcB0QKUGSk00/fUipA3z5rOXcQYAwE0CABPa5lbTRAIm5i8F0Gj8UW7QO0pQus4UtjX0+JxWdclB7UrA== dependencies: "@metamask/detect-provider" "^1.2.0" - "@web3-react/types" "^8.2.0" + "@web3-react/types" "^8.2.3" -"@web3-react/network@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@web3-react/network/-/network-8.2.0.tgz#225ae9e135711e8c64ab3123570abaa5b82b8145" - integrity sha512-3OcJwuaot8A+VTSoCe17MZv/K/TNVw7DjtYoS7lBRS/CmzYIwP53Tosea4MkliOuXiUUKj7Ge1D2FpWohq6pHw== +"@web3-react/network@^8.2.3": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@web3-react/network/-/network-8.2.3.tgz#edc8268877006780321fed7e632ebd86ef057eb8" + integrity sha512-OAlXo3aNhldANmHt/N88SuLrWihVQizJf0cNy1cqnbNIAg87292PnAqCZrj3Pwaq/s8hoSgapc87zl1KFJeTjA== dependencies: "@ethersproject/providers" "^5" - "@web3-react/types" "^8.2.0" + "@web3-react/types" "^8.2.3" -"@web3-react/store@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@web3-react/store/-/store-8.2.0.tgz#4260c7d1fca3c8e0358f32ed8909a5d8dba69a80" - integrity sha512-cG8nb+tBeRUJu+98ko6YZuAWmoipGMEbR3bhineCNd4x2mXv3GbWSPtE17GeWVshZgDbZu2/Du0okTx+22VWCg== +"@web3-react/store@^8.2.3": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@web3-react/store/-/store-8.2.3.tgz#64a0ddaf49f85c120e07f5089dd4d7df9346f881" + integrity sha512-qUJQ5pDsYYDra+/+glq2BmIS43HYAiEZ22sLLVh6E75WiZKRNOOqUxBDPe33KTIn718DLt51j+wd2FT+oT/kJQ== dependencies: "@ethersproject/address" "^5" - "@web3-react/types" "^8.2.0" - zustand "^4.3.5" + "@web3-react/types" "^8.2.3" + zustand "4.4.0" -"@web3-react/types@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@web3-react/types/-/types-8.2.0.tgz#195464ebb94cb417e6dc3c16951573f9b6b3832a" - integrity sha512-TBYTFlqJZaEpVbuAAKRJFX5PZc3lI1TqDZzY94zwCrCh4GBepwwK7+PxmRAppMFuNa5x0vFX/ghLEC44e6TCFg== +"@web3-react/types@^8.2.3": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@web3-react/types/-/types-8.2.3.tgz#e2ac1eaaa7f96b518a5535fee048bf73470f5c21" + integrity sha512-kSG90QkN+n7IOtp10nQ44oS8J7jzfH9EmqnruwBpCGybh1FM/ohyRvUKWYZNfNE4wsjTSpKsINR0/VdDsZMHyg== dependencies: - zustand "^4.3.5" + zustand "4.4.0" -"@web3-react/url@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@web3-react/url/-/url-8.2.0.tgz#5df80f213bf6b6f382aa842ae37ad0703d413a37" - integrity sha512-dt1i8AgZso6y0sX67JSZ1DzsU511iFu4Gcxksbw/yJPlFybsHco+Fcg94WLjWj4ec26kVRUBySUVCyXrYlg0kQ== +"@web3-react/url@^8.2.3": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@web3-react/url/-/url-8.2.3.tgz#20de44f6e653575f0d522c3e905ab00bf1e6a918" + integrity sha512-gOcs8uEbD+BKMvw2VhTWnD8Ls3aOmbebLwASu7daWYuM2eB8hS8AoqsEAbV1NnliNpY7ztd+L1Vi5CckiIhXcw== dependencies: "@ethersproject/providers" "^5" - "@web3-react/types" "^8.2.0" - -"@web3-react/walletconnect-v2@^8.3.7": - version "8.3.7" - resolved "https://registry.yarnpkg.com/@web3-react/walletconnect-v2/-/walletconnect-v2-8.3.7.tgz#272ff3674eeb9a8eae2ae06a133993a6ff01669f" - integrity sha512-iaD6Uqhfdkk50n8S+ADJBttgivdMNuR+mti+v98WAUCO3Spnw5i47B2fs+qCQwJIwmD5qCis0zZzlZMwBOriGg== - dependencies: - "@walletconnect/ethereum-provider" "^2.8.6" - "@walletconnect/modal" "^2.5.9" - "@web3-react/types" "^8.2.0" - eventemitter3 "^4.0.7" + "@web3-react/types" "^8.2.3" -"@web3-react/walletconnect@^8.2.0": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@web3-react/walletconnect/-/walletconnect-8.2.0.tgz#e4e325132f04f03a07a19cd193b4b97bfe6a9914" - integrity sha512-Yl1C0beRnwohtFZ9c6xz6mOci2MqoES2hYKhJI4X7qKqcmQJC6TOeLjlYfzjdUTUvP8IDf0A7flYZVeBUvL/fg== +"@web3-react/walletconnect-v2@^8.5.1": + version "8.5.1" + resolved "https://registry.yarnpkg.com/@web3-react/walletconnect-v2/-/walletconnect-v2-8.5.1.tgz#bc7d43b53bb30ec524e0cc36e20e1f279bf18818" + integrity sha512-K6RjdllFpEftTDQw39fRfuVcBLNCWXDxx5oZiWDc7D2RW071C0m1WridOeUiELmCXykyDCrIjd2zAVwV4GGueA== dependencies: - "@walletconnect/ethereum-provider" "^1.7.8" - "@web3-react/types" "^8.2.0" + "@walletconnect/ethereum-provider" "^2.10.1" + "@walletconnect/modal" "^2.6.2" + "@web3-react/types" "^8.2.3" eventemitter3 "^4.0.7" "@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": @@ -7639,11 +7443,6 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== -aes-js@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== - agent-base@6, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -7736,11 +7535,6 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -8102,13 +7896,6 @@ axios@^0.19.2: dependencies: follow-redirects "1.5.10" -axios@^0.21.0: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - axios@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" @@ -8580,11 +8367,6 @@ bn.js@4.11.6: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@4.11.8: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== - bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.12.0: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -8857,19 +8639,6 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" @@ -8880,12 +8649,7 @@ buffer-equal@0.0.1: resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" integrity sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA== -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== - -buffer-from@^1.0.0, buffer-from@^1.1.1: +buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== @@ -9390,15 +9154,6 @@ clipboardy@^2.3.0: execa "^1.0.0" is-wsl "^2.1.1" -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - cliui@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" @@ -9764,7 +9519,7 @@ cookie@^0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -copy-to-clipboard@^3.2.0, copy-to-clipboard@^3.3.1: +copy-to-clipboard@^3.2.0: version "3.3.3" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== @@ -10800,11 +10555,6 @@ destroy@1.2.0: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== -detect-browser@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.2.0.tgz#c9cd5afa96a6a19fda0bbe9e9be48a6b6e1e9c97" - integrity sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA== - detect-browser@5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" @@ -11135,13 +10885,6 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -eip1193-provider@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/eip1193-provider/-/eip1193-provider-1.0.1.tgz#420d29cf4f6c443e3f32e718fb16fafb250637c3" - integrity sha512-kSuqwQ26d7CzuS/t3yRXo2Su2cVH0QfvyKbr2H7Be7O5YDyIq4hQGCNTo5wRdP07bt+E2R/8nPCzey4ojBHf7g== - dependencies: - "@json-rpc-tools/provider" "^1.5.5" - ejs@^3.1.6, ejs@^3.1.7: version "3.1.9" resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.9.tgz#03c9e8777fe12686a9effcef22303ca3d8eeb361" @@ -11189,11 +10932,6 @@ emittery@^0.8.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -12148,7 +11886,7 @@ eventemitter3@4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== -eventemitter3@4.0.7, eventemitter3@^4.0.0, eventemitter3@^4.0.7: +eventemitter3@^4.0.0, eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== @@ -12679,7 +12417,7 @@ follow-redirects@1.5.10: dependencies: debug "=3.1.0" -follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.15.0: +follow-redirects@^1.0.0, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== @@ -14618,7 +14356,7 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.3, is-typed-array@^1.1.9: dependencies: which-typed-array "^1.1.11" -is-typedarray@1.0.0, is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== @@ -14660,7 +14398,7 @@ is-yarn-global@^0.3.0: resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== -isarray@^2.0.1, isarray@^2.0.5: +isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== @@ -16342,14 +16080,21 @@ lit-html@^2.7.0: dependencies: "@types/trusted-types" "^2.0.2" -lit@2.7.6: - version "2.7.6" - resolved "https://registry.yarnpkg.com/lit/-/lit-2.7.6.tgz#810007b876ed43e0c70124de91831921598b1665" - integrity sha512-1amFHA7t4VaaDe+vdQejSVBklwtH9svGoG6/dZi9JhxtJBBlqY5D1RV7iLUYY0trCqQc4NfhYYZilZiVHt7Hxg== +lit-html@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-2.8.0.tgz#96456a4bb4ee717b9a7d2f94562a16509d39bffa" + integrity sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q== + dependencies: + "@types/trusted-types" "^2.0.2" + +lit@2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/lit/-/lit-2.8.0.tgz#4d838ae03059bf9cafa06e5c61d8acc0081e974e" + integrity sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA== dependencies: "@lit/reactive-element" "^1.6.0" lit-element "^3.3.0" - lit-html "^2.7.0" + lit-html "^2.8.0" load-bmfont@^1.3.1: version "1.4.1" @@ -18503,7 +18248,7 @@ pkg-up@^4.0.0: dependencies: find-up "^6.2.0" -pngjs@^3.0.0, pngjs@^3.3.0, pngjs@^3.3.3: +pngjs@^3.0.0, pngjs@^3.3.3: version "3.4.0" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== @@ -19096,11 +18841,6 @@ postcss@^8.3.5, postcss@^8.4.21, postcss@^8.4.23, postcss@^8.4.26, postcss@^8.4. picocolors "^1.0.0" source-map-js "^1.0.2" -preact@10.4.1: - version "10.4.1" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.1.tgz#9b3ba020547673a231c6cf16f0fbaef0e8863431" - integrity sha512-WKrRpCSwL2t3tpOOGhf2WfTpcmbpxaWtDbdJdKdjd0aEiTkvOmS4NBkG6kzlaAHI9AkQ3iVqbFWM3Ei7mZ4o1Q== - preact@^10.5.9: version "10.16.0" resolved "https://registry.yarnpkg.com/preact/-/preact-10.16.0.tgz#68a06d70b191b8a313ea722d61e09c6b2a79a37e" @@ -19366,19 +19106,6 @@ q@^1.1.2, q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== -qrcode@1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83" - integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q== - dependencies: - buffer "^5.4.3" - buffer-alloc "^1.2.0" - buffer-from "^1.1.1" - dijkstrajs "^1.0.1" - isarray "^2.0.1" - pngjs "^3.3.0" - yargs "^13.2.4" - qrcode@1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170" @@ -19415,15 +19142,6 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== -query-string@6.13.5: - version "6.13.5" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.5.tgz#99e95e2fb7021db90a6f373f990c0c814b3812d8" - integrity sha512-svk3xg9qHR39P3JlHuD7g3nRnyay5mHbrPctEBDUxUkHRifPHXJDhBUycdCC0NBjXoDf44Gb+IsOZL1Uwn8M/Q== - dependencies: - decode-uri-component "^0.2.0" - split-on-first "^1.0.0" - strict-uri-encode "^2.0.0" - query-string@7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" @@ -21398,15 +21116,6 @@ string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -21494,13 +21203,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -22491,7 +22193,7 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typedarray-to-buffer@3.1.5, typedarray-to-buffer@^3.1.5: +typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== @@ -22917,10 +22619,10 @@ validator@^13.7.0: resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855" integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA== -valtio@1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/valtio/-/valtio-1.11.0.tgz#c029dcd17a0f99d2fbec933721fe64cfd32a31ed" - integrity sha512-65Yd0yU5qs86b5lN1eu/nzcTgQ9/6YnD6iO+DDaDbQLn1Zv2w12Gwk43WkPlUBxk5wL/6cD5YMFf7kj6HZ1Kpg== +valtio@1.11.2: + version "1.11.2" + resolved "https://registry.yarnpkg.com/valtio/-/valtio-1.11.2.tgz#b8049c02dfe65620635d23ebae9121a741bb6530" + integrity sha512-1XfIxnUXzyswPAPXo1P3Pdx2mq/pIqZICkWN60Hby0d9Iqb+MEIpqgYVlbflvHdrp2YR/q3jyKWRPJJ100yxaw== dependencies: proxy-compare "2.5.1" use-sync-external-store "1.2.0" @@ -24073,15 +23775,6 @@ wrap-ansi@^4.0.0: string-width "^2.1.1" strip-ansi "^4.0.0" -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -24128,12 +23821,7 @@ ws@7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== -ws@7.5.3: - version "7.5.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" - integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== - -ws@7.5.9, ws@^7.2.0, ws@^7.4.0, ws@^7.4.5, ws@^7.4.6, ws@^7.5.1: +ws@7.5.9, ws@^7.2.0, ws@^7.4.5, ws@^7.4.6, ws@^7.5.1: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== @@ -24282,14 +23970,6 @@ yargs-parser@^10.0.0: dependencies: camelcase "^4.1.0" -yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^18.1.2, yargs-parser@^18.1.3: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" @@ -24303,22 +23983,6 @@ yargs-parser@^20.2.2, yargs-parser@^20.2.3, yargs-parser@^20.2.9: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs@^13.2.4: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - yargs@^15.3.1, yargs@^15.4.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" @@ -24396,9 +24060,9 @@ z-schema@~5.0.2: optionalDependencies: commander "^10.0.0" -zustand@^4.3.5: - version "4.3.9" - resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.9.tgz#a7d4332bbd75dfd25c6848180b3df1407217f2ad" - integrity sha512-Tat5r8jOMG1Vcsj8uldMyqYKC5IZvQif8zetmLHs9WoZlntTHmIoNM8TpLRY31ExncuUvUOXehd0kvahkuHjDw== +zustand@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.4.0.tgz#13b3e8ca959dd53d536034440aec382ff91b65c3" + integrity sha512-2dq6wq4dSxbiPTamGar0NlIG/av0wpyWZJGeQYtUOLegIUvhM2Bf86ekPlmgpUtS5uR7HyetSiktYrGsdsyZgQ== dependencies: use-sync-external-store "1.2.0" From dede0d0431511ad1b1ed0548f6d42f881b0f95e0 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Mon, 16 Oct 2023 16:54:49 +0600 Subject: [PATCH 36/36] fix(eth-flow): update refund info for expired orders (#3222) * fix(eth-flow): update refund info for expired orders * chore: update comment * chore: fix ExpiredOrdersUpdater conditions * chore: fix namings --- .../updaters/orders/ExpiredOrdersUpdater.ts | 21 ++++++++----------- .../EthFlow/EthFlowStepper/index.cosmos.tsx | 10 +++++++-- libs/common-const/src/common.ts | 1 - 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/apps/cowswap-frontend/src/common/updaters/orders/ExpiredOrdersUpdater.ts b/apps/cowswap-frontend/src/common/updaters/orders/ExpiredOrdersUpdater.ts index 850cfd7201..006c88b659 100644 --- a/apps/cowswap-frontend/src/common/updaters/orders/ExpiredOrdersUpdater.ts +++ b/apps/cowswap-frontend/src/common/updaters/orders/ExpiredOrdersUpdater.ts @@ -1,6 +1,6 @@ import { useEffect, useCallback, useRef } from 'react' -import { EXPIRED_ORDERS_PENDING_TIME } from '@cowprotocol/common-const' +import { NATIVE_CURRENCY_BUY_ADDRESS } from '@cowprotocol/common-const' import { SupportedChainId as ChainId } from '@cowprotocol/cow-sdk' import { useWalletInfo } from '@cowprotocol/wallet' @@ -24,7 +24,6 @@ export function ExpiredOrdersUpdater(): null { const updateOrders = useCallback( async (chainId: ChainId, account: string) => { const lowerCaseAccount = account.toLowerCase() - const now = Date.now() if (isUpdating.current) { return @@ -33,26 +32,24 @@ export function ExpiredOrdersUpdater(): null { try { isUpdating.current = true - // Filter orders: + // Filter expired orders: + // - Only eth-flow orders // - Owned by the current connected account - // - Created in the last 5 min, no further // - Not yet refunded - const pending = expiredRef.current.filter(({ owner, creationTime: creationTimeString, refundHash }) => { - const creationTime = new Date(creationTimeString).getTime() + const orderWithoutRefund = expiredRef.current.filter(({ owner, refundHash, sellToken }) => { + const isEthFlowOrder = sellToken === NATIVE_CURRENCY_BUY_ADDRESS - return ( - owner.toLowerCase() === lowerCaseAccount && now - creationTime < EXPIRED_ORDERS_PENDING_TIME && !refundHash - ) + return isEthFlowOrder && owner.toLowerCase() === lowerCaseAccount && !refundHash }) - if (pending.length === 0) { + if (orderWithoutRefund.length === 0) { // console.debug(`[CancelledOrdersUpdater] No orders are being expired`) return } else { - console.debug(`[ExpiredOrdersUpdater] Checking ${pending.length} recently expired orders...`) + console.debug(`[ExpiredOrdersUpdater] Checking ${orderWithoutRefund.length} recently expired orders...`) } - const ordersPromises = pending.map(({ id }) => getOrder(chainId, id)) + const ordersPromises = orderWithoutRefund.map(({ id }) => getOrder(chainId, id)) const resolvedPromises = await Promise.allSettled(ordersPromises) diff --git a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.cosmos.tsx b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.cosmos.tsx index 1fd39c2845..022dcc648e 100644 --- a/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.cosmos.tsx +++ b/apps/cowswap-frontend/src/modules/swap/pure/EthFlow/EthFlowStepper/index.cosmos.tsx @@ -1,6 +1,7 @@ import 'inter-ui' // TODO: We need to do a cosmos wrapper with the global styles! Will reiterate to remove this line import { useSelect } from 'react-cosmos/client' +import styled from 'styled-components/macro' import { EthFlowStepper, EthFlowStepperProps, SmartOrderStatus } from '.' @@ -376,6 +377,11 @@ const STEPS_BY_DESCRIPTION = STEPS.reduce<{ [description: string]: EthFlowSteppe return acc }, {}) +const Wrapper = styled.div` + width: 80%; + margin: 20px auto; +` + function Fixture() { const [stepDescription] = useSelect('steps', { options: STEPS.map((step) => step.description), @@ -383,13 +389,13 @@ function Fixture() { const props = STEPS_BY_DESCRIPTION[stepDescription] return ( - <> +

Params

{JSON.stringify(props, null, 2)}
- +
) } diff --git a/libs/common-const/src/common.ts b/libs/common-const/src/common.ts index 4488559c9f..093a601cac 100644 --- a/libs/common-const/src/common.ts +++ b/libs/common-const/src/common.ts @@ -99,7 +99,6 @@ export const NATIVE_CURRENCY_BUY_TOKEN: { [chainId in ChainId | number]: Token } export const INPUT_OUTPUT_EXPLANATION = 'Only executed swaps incur fees.' export const PENDING_ORDERS_BUFFER = ms`60s` // 60s export const CANCELLED_ORDERS_PENDING_TIME = ms`5min` // 5min -export const EXPIRED_ORDERS_PENDING_TIME = ms`15min` // 15min export const PRICE_API_TIMEOUT_MS = ms`10s` // 10s export const GP_ORDER_UPDATE_INTERVAL = ms`30s` // 30s export const MINIMUM_ORDER_VALID_TO_TIME_SECONDS = 120