@rango-dev/widget-embedded 0.1.10-next.80 → 0.1.10-next.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/components/AppRouter.d.ts.map +1 -1
  2. package/dist/components/AppRoutes.d.ts.map +1 -1
  3. package/dist/components/ChangeSlippageButton.d.ts +2 -0
  4. package/dist/components/ChangeSlippageButton.d.ts.map +1 -0
  5. package/dist/components/ConfirmSwapErrors.d.ts +3 -0
  6. package/dist/components/ConfirmSwapErrors.d.ts.map +1 -0
  7. package/dist/components/ConfirmSwapWarnings.d.ts +3 -0
  8. package/dist/components/ConfirmSwapWarnings.d.ts.map +1 -0
  9. package/dist/components/Layout.d.ts.map +1 -1
  10. package/dist/components/UpdateUrl.d.ts.map +1 -1
  11. package/dist/components/warnings/BalanceWarnings.d.ts +6 -0
  12. package/dist/components/warnings/BalanceWarnings.d.ts.map +1 -0
  13. package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts +6 -0
  14. package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts.map +1 -0
  15. package/dist/components/warnings/HighSlippageWarning.d.ts +6 -0
  16. package/dist/components/warnings/HighSlippageWarning.d.ts.map +1 -0
  17. package/dist/components/warnings/MinRequiredSlippage.d.ts +6 -0
  18. package/dist/components/warnings/MinRequiredSlippage.d.ts.map +1 -0
  19. package/dist/constants/swapSettings.d.ts +6 -0
  20. package/dist/constants/swapSettings.d.ts.map +1 -0
  21. package/dist/hooks/useNavigateBack.d.ts +4 -0
  22. package/dist/hooks/useNavigateBack.d.ts.map +1 -0
  23. package/dist/pages/ConfirmSwapPage.d.ts.map +1 -1
  24. package/dist/pages/ConfirmWalletsPage.d.ts +0 -5
  25. package/dist/pages/ConfirmWalletsPage.d.ts.map +1 -1
  26. package/dist/pages/HistoryPage.d.ts.map +1 -1
  27. package/dist/pages/Home.d.ts.map +1 -1
  28. package/dist/pages/LiquiditySourcesPage.d.ts.map +1 -1
  29. package/dist/pages/SelectChainPage.d.ts.map +1 -1
  30. package/dist/pages/SelectTokenPage.d.ts.map +1 -1
  31. package/dist/pages/SettingsPage.d.ts.map +1 -1
  32. package/dist/pages/SwapDetailsPage.d.ts.map +1 -1
  33. package/dist/pages/WalletsPage.d.ts.map +1 -1
  34. package/dist/store/bestRoute.d.ts +1 -0
  35. package/dist/store/bestRoute.d.ts.map +1 -1
  36. package/dist/store/confirmSwap.d.ts +35 -0
  37. package/dist/store/confirmSwap.d.ts.map +1 -0
  38. package/dist/store/settings.d.ts.map +1 -1
  39. package/dist/store/ui.d.ts +2 -0
  40. package/dist/store/ui.d.ts.map +1 -0
  41. package/dist/store/wallets.d.ts.map +1 -1
  42. package/dist/types/index.d.ts +2 -0
  43. package/dist/types/index.d.ts.map +1 -0
  44. package/dist/types/swap.d.ts +11 -0
  45. package/dist/types/swap.d.ts.map +1 -0
  46. package/dist/utils/common.d.ts +1 -0
  47. package/dist/utils/common.d.ts.map +1 -1
  48. package/dist/utils/numbers.d.ts +5 -0
  49. package/dist/utils/numbers.d.ts.map +1 -1
  50. package/dist/utils/routing.d.ts +5 -7
  51. package/dist/utils/routing.d.ts.map +1 -1
  52. package/dist/utils/swap.d.ts +31 -3
  53. package/dist/utils/swap.d.ts.map +1 -1
  54. package/dist/utils/wallets.d.ts +2 -3
  55. package/dist/utils/wallets.d.ts.map +1 -1
  56. package/dist/widget-embedded.cjs.development.js +1814 -1327
  57. package/dist/widget-embedded.cjs.development.js.map +1 -1
  58. package/dist/widget-embedded.cjs.production.min.js +1814 -1327
  59. package/dist/widget-embedded.cjs.production.min.js.map +1 -1
  60. package/dist/widget-embedded.esm.js +1818 -1331
  61. package/dist/widget-embedded.esm.js.map +1 -1
  62. package/package.json +1 -1
  63. package/src/components/AppRouter.tsx +38 -3
  64. package/src/components/AppRoutes.tsx +8 -2
  65. package/src/components/ChangeSlippageButton.tsx +23 -0
  66. package/src/components/ConfirmSwapErrors.tsx +38 -0
  67. package/src/components/ConfirmSwapWarnings.tsx +38 -0
  68. package/src/components/Layout.tsx +22 -6
  69. package/src/components/UpdateUrl.tsx +100 -18
  70. package/src/components/warnings/BalanceWarnings.tsx +16 -0
  71. package/src/components/warnings/ConfirmSwapExtraMessages.tsx +14 -0
  72. package/src/components/warnings/HighSlippageWarning.tsx +21 -0
  73. package/src/components/warnings/MinRequiredSlippage.tsx +18 -0
  74. package/src/constants/navigationRoutes.ts +2 -2
  75. package/src/constants/swapSettings.ts +9 -0
  76. package/src/hooks/useNavigateBack.ts +37 -0
  77. package/src/pages/ConfirmSwapPage.tsx +30 -8
  78. package/src/pages/ConfirmWalletsPage.tsx +30 -17
  79. package/src/pages/HistoryPage.tsx +4 -4
  80. package/src/pages/Home.tsx +79 -36
  81. package/src/pages/LiquiditySourcesPage.tsx +11 -8
  82. package/src/pages/SelectChainPage.tsx +9 -28
  83. package/src/pages/SelectTokenPage.tsx +38 -27
  84. package/src/pages/SettingsPage.tsx +26 -11
  85. package/src/pages/SwapDetailsPage.tsx +9 -3
  86. package/src/pages/WalletsPage.tsx +37 -22
  87. package/src/store/bestRoute.ts +147 -28
  88. package/src/store/confirmSwap.ts +327 -0
  89. package/src/store/settings.ts +44 -32
  90. package/src/store/ui.ts +15 -0
  91. package/src/store/wallets.ts +93 -80
  92. package/src/swapBox.tsx +5 -5
  93. package/src/types/index.ts +1 -0
  94. package/src/types/swap.ts +13 -0
  95. package/src/utils/common.ts +4 -0
  96. package/src/utils/numbers.ts +17 -0
  97. package/src/utils/routing.ts +28 -77
  98. package/src/utils/swap.ts +445 -67
  99. package/src/utils/wallets.ts +4 -19
  100. package/dist/hooks/useBestRoute.d.ts +0 -8
  101. package/dist/hooks/useBestRoute.d.ts.map +0 -1
  102. package/dist/hooks/useConfirmSwap.d.ts +0 -2
  103. package/dist/hooks/useConfirmSwap.d.ts.map +0 -1
  104. package/src/hooks/useBestRoute.ts +0 -70
  105. package/src/hooks/useConfirmSwap.ts +0 -268
@@ -1,11 +1,14 @@
1
1
  import { BestRouteResponse, BlockchainMeta } from 'rango-sdk';
2
2
  import { Token } from 'rango-sdk/lib';
3
3
  import { create } from 'zustand';
4
- import { immer } from 'zustand/middleware/immer';
5
4
  import BigNumber from 'bignumber.js';
6
5
  import { ZERO } from '../constants/numbers';
7
6
  import { getBestRouteToTokenUsdPrice } from '../utils/routing';
8
7
  import createSelectors from './selectors';
8
+ import { subscribeWithSelector } from 'zustand/middleware';
9
+ import { httpService } from '../services/httpService';
10
+ import { useSettingsStore } from './settings';
11
+ import { createBestRouteRequestBody } from '../utils/swap';
9
12
 
10
13
  const getUsdValue = (token: Token | null, amount: string) =>
11
14
  new BigNumber(amount || ZERO).multipliedBy(token?.usdPrice || 0);
@@ -19,6 +22,8 @@ interface RouteState {
19
22
  outputUsdValue: BigNumber;
20
23
  fromToken: Token | null;
21
24
  toToken: Token | null;
25
+ loading: boolean;
26
+ error: string;
22
27
  setFromChain: (chain: BlockchainMeta | null) => void;
23
28
  setToChain: (chian: BlockchainMeta | null) => void;
24
29
  setFromToken: (token: Token | null) => void;
@@ -30,7 +35,7 @@ interface RouteState {
30
35
 
31
36
  export const useBestRouteStore = createSelectors(
32
37
  create<RouteState>()(
33
- immer((set) => ({
38
+ subscribeWithSelector((set) => ({
34
39
  fromChain: null,
35
40
  fromToken: null,
36
41
  inputAmount: '',
@@ -40,43 +45,157 @@ export const useBestRouteStore = createSelectors(
40
45
  toChain: null,
41
46
  toToken: null,
42
47
  bestRoute: null,
48
+ loading: false,
49
+ error: '',
43
50
  setBestRoute: (bestRoute) =>
44
51
  set((state) => {
45
- state.bestRoute = bestRoute;
52
+ let outputAmount: BigNumber | null = null;
53
+ let outputUsdValue: BigNumber = ZERO;
46
54
  if (!!bestRoute) {
47
- const outputAmount = !!bestRoute.result?.outputAmount
55
+ outputAmount = !!bestRoute.result?.outputAmount
48
56
  ? new BigNumber(bestRoute.result?.outputAmount)
49
57
  : null;
50
- state.outputAmount = outputAmount;
51
- state.outputUsdValue = new BigNumber(outputAmount || ZERO).multipliedBy(
52
- getBestRouteToTokenUsdPrice(bestRoute) || state.toToken?.usdPrice || 0,
58
+ outputUsdValue = new BigNumber(outputAmount || ZERO).multipliedBy(
59
+ getBestRouteToTokenUsdPrice(bestRoute) ||
60
+ state.toToken?.usdPrice ||
61
+ 0
53
62
  );
54
63
  }
64
+ return {
65
+ bestRoute,
66
+ ...(!!bestRoute && {
67
+ outputAmount,
68
+ outputUsdValue,
69
+ }),
70
+ };
55
71
  }),
56
72
  setFromChain: (chain) =>
57
- set((state) => {
58
- state.fromChain = chain;
59
- }),
73
+ set(() => ({
74
+ fromChain: chain,
75
+ })),
60
76
  setFromToken: (token) =>
61
- set((state) => {
62
- state.fromToken = token;
63
- if (!!state.inputAmount)
64
- state.inputUsdValue = getUsdValue(state.fromToken!, state.inputAmount);
65
- }),
77
+ set((state) => ({
78
+ fromToken: token,
79
+ ...(!!state.inputAmount && {
80
+ inputUsdValue: getUsdValue(token, state.inputAmount),
81
+ }),
82
+ })),
66
83
  setToChain: (chain) =>
67
- set((state) => {
68
- state.toChain = chain;
69
- }),
84
+ set(() => ({
85
+ toChain: chain,
86
+ })),
70
87
  setToToken: (token) =>
71
- set((state) => {
72
- state.toToken = token;
73
- }),
88
+ set(() => ({
89
+ toToken: token,
90
+ })),
74
91
  setInputAmount: (amount) =>
75
- set((state) => {
76
- state.inputAmount = amount;
77
- if (!!state.fromToken)
78
- state.inputUsdValue = getUsdValue(state.fromToken, state.inputAmount);
79
- }),
80
- })),
81
- ),
92
+ set((state) => ({
93
+ inputAmount: amount,
94
+ ...(!!state.fromToken && {
95
+ inputUsdValue: getUsdValue(state.fromToken, amount),
96
+ }),
97
+ })),
98
+ }))
99
+ )
100
+ );
101
+
102
+ const bestRoute = (
103
+ bestRouteStore: typeof useBestRouteStore,
104
+ settingsStore: typeof useSettingsStore
105
+ ) => {
106
+ let abortController: AbortController | null = null;
107
+ const fetchBestRoute = () => {
108
+ const { fromToken, toToken, inputAmount } = bestRouteStore.getState();
109
+ const { slippage, customSlippage, disabledLiquiditySources } =
110
+ settingsStore.getState();
111
+ if (!fromToken || !toToken || !inputAmount) return;
112
+ abortController?.abort();
113
+ abortController = new AbortController();
114
+ const userSlippage = customSlippage | slippage;
115
+ const requestBody = createBestRouteRequestBody(
116
+ fromToken,
117
+ toToken,
118
+ inputAmount,
119
+ [],
120
+ [],
121
+ disabledLiquiditySources,
122
+ userSlippage,
123
+ false
124
+ );
125
+ bestRouteStore.setState({ loading: true, bestRoute: null });
126
+ httpService
127
+ .getBestRoute(requestBody, {
128
+ signal: abortController.signal,
129
+ })
130
+ .then((res) => {
131
+ const { setBestRoute } = bestRouteStore.getState();
132
+ setBestRoute(res);
133
+ bestRouteStore.setState({ loading: false });
134
+ abortController = null;
135
+ })
136
+ .catch((error) => {
137
+ if (error.code === 'ERR_CANCELED') return;
138
+ bestRouteStore.setState({
139
+ error: error.message,
140
+ loading: false,
141
+ });
142
+ });
143
+ };
144
+
145
+ useBestRouteStore.subscribe(
146
+ (state) => ({
147
+ fromChain: state.fromChain,
148
+ fromToken: state.fromToken,
149
+ toChain: state.toChain,
150
+ toToken: state.toToken,
151
+ inputAmount: state.inputAmount,
152
+ }),
153
+
154
+ fetchBestRoute.bind(null),
155
+ {
156
+ equalityFn: (prevState, state) => {
157
+ if (
158
+ prevState.fromChain?.name !== state.fromChain?.name ||
159
+ prevState.toChain?.name !== state.toChain?.name ||
160
+ prevState.fromToken?.symbol !== state.fromToken?.symbol ||
161
+ prevState.toToken?.symbol !== state.toToken?.symbol ||
162
+ prevState.fromToken?.blockchain !== state.fromToken?.blockchain ||
163
+ prevState.toToken?.blockchain !== state.toToken?.blockchain ||
164
+ prevState.fromToken?.address !== state.fromToken?.address ||
165
+ prevState.toToken?.address !== state.toToken?.address ||
166
+ prevState.inputAmount !== state.inputAmount
167
+ )
168
+ return false;
169
+ else return true;
170
+ },
171
+ }
172
+ );
173
+
174
+ useSettingsStore.subscribe(
175
+ (state) => ({
176
+ slippage: state.slippage,
177
+ customSlippage: state.customSlippage,
178
+ disabledLiquiditySources: state.disabledLiquiditySources,
179
+ }),
180
+ fetchBestRoute.bind(null),
181
+ {
182
+ equalityFn: (prevState, state) => {
183
+ if (
184
+ prevState.slippage !== state.slippage ||
185
+ prevState.customSlippage !== state.customSlippage ||
186
+ prevState.disabledLiquiditySources.length !==
187
+ state.disabledLiquiditySources.length
188
+ )
189
+ return false;
190
+ else return true;
191
+ },
192
+ }
193
+ );
194
+
195
+ return { fetchBestRoute };
196
+ };
197
+
198
+ export const { fetchBestRoute } = bestRoute(
199
+ useBestRouteStore,
200
+ useSettingsStore
82
201
  );
@@ -0,0 +1,327 @@
1
+ import BigNumber from 'bignumber.js';
2
+ import { create } from 'zustand';
3
+ import { shallow } from 'zustand/shallow';
4
+ import { subscribeWithSelector } from 'zustand/middleware';
5
+ import { httpService } from '../services/httpService';
6
+ import { PendingSwapSettings } from '../types';
7
+ import { numberToString } from '../utils/numbers';
8
+ import {
9
+ isRouteChanged,
10
+ isNumberOfSwapsChanged,
11
+ isRouteSwappersUpdated,
12
+ isRouteInternalCoinsUpdated,
13
+ } from '../utils/routing';
14
+ import {
15
+ createBestRouteRequestBody,
16
+ getOutputRatio,
17
+ outputRatioHasWarning,
18
+ isOutputAmountChangedALot,
19
+ getRouteOutputAmount,
20
+ getPercentageChange,
21
+ getBalanceWarnings,
22
+ getMinRequiredSlippage,
23
+ hasProperSlippage,
24
+ calculatePendingSwap,
25
+ getWalletsForNewSwap,
26
+ } from '../utils/swap';
27
+ import { useBestRouteStore } from './bestRoute';
28
+ import { useMetaStore } from './meta';
29
+ import createSelectors from './selectors';
30
+ import { useSettingsStore } from './settings';
31
+ import { useWalletsStore } from './wallets';
32
+
33
+ interface ConfirmSwapState {
34
+ loading: boolean;
35
+ errors: ConfirmSwapError[];
36
+ warnings: ConfirmSwapWarnings[];
37
+ proceedAnyway: boolean;
38
+ }
39
+
40
+ export const useConfirmSwapStore = createSelectors(
41
+ create<ConfirmSwapState>()(
42
+ subscribeWithSelector(() => ({
43
+ loading: false,
44
+ errors: [],
45
+ warnings: [],
46
+ proceedAnyway: false,
47
+ }))
48
+ )
49
+ );
50
+
51
+ export enum ConfirmSwapErrorTypes {
52
+ NO_ROUTE,
53
+ ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS,
54
+ REQUEST_FAILED,
55
+ INSUFFICIENT_SLIPPAGE,
56
+ }
57
+
58
+ export type ConfirmSwapError =
59
+ | {
60
+ type: ConfirmSwapErrorTypes.REQUEST_FAILED;
61
+ status?: number;
62
+ }
63
+ | {
64
+ type: ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE;
65
+ minRequiredSlippage: number;
66
+ }
67
+ | {
68
+ type: Exclude<
69
+ ConfirmSwapErrorTypes,
70
+ | ConfirmSwapErrorTypes.REQUEST_FAILED
71
+ | ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE
72
+ >;
73
+ };
74
+
75
+ export type ConfirmSwapWarnings =
76
+ | {
77
+ type: ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED;
78
+ newOutputAmount: string;
79
+ percentageChange: string;
80
+ }
81
+ | { type: ConfirmSwapWarningTypes.INSUFFICIENT_BALANCE; messages: string[] }
82
+ | {
83
+ type: Exclude<
84
+ ConfirmSwapWarningTypes,
85
+ | ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED
86
+ | ConfirmSwapWarningTypes.INSUFFICIENT_BALANCE
87
+ >;
88
+ };
89
+
90
+ export enum ConfirmSwapWarningTypes {
91
+ ROUTE_UPDATED,
92
+ ROUTE_SWAPPERS_UPDATED,
93
+ ROUTE_COINS_UPDATED,
94
+ ROUTE_AND_OUTPUT_AMOUNT_UPDATED,
95
+ INSUFFICIENT_BALANCE,
96
+ }
97
+
98
+ export const confirmSwap = () => {
99
+ const {
100
+ fromToken,
101
+ toToken,
102
+ inputAmount,
103
+ bestRoute: initialRoute,
104
+ inputUsdValue,
105
+ setBestRoute,
106
+ } = useBestRouteStore.getState();
107
+ const { accounts, selectedWallets } = useWalletsStore.getState();
108
+ const { proceedAnyway } = useConfirmSwapStore.getState();
109
+ const { disabledLiquiditySources, slippage, customSlippage } =
110
+ useSettingsStore.getState();
111
+ const { meta } = useMetaStore.getState();
112
+
113
+ const userSlippage = customSlippage || slippage;
114
+
115
+ if (!fromToken || !toToken || !inputAmount || !initialRoute) return;
116
+
117
+ if (proceedAnyway!) {
118
+ const swapSettings: PendingSwapSettings = {
119
+ slippage: userSlippage.toString(),
120
+ disabledSwappersGroups: disabledLiquiditySources,
121
+ };
122
+
123
+ const newSwap = calculatePendingSwap(
124
+ inputAmount.toString(),
125
+ initialRoute,
126
+ getWalletsForNewSwap(selectedWallets),
127
+ swapSettings,
128
+ false,
129
+ meta
130
+ );
131
+
132
+ console.log('new swap:', newSwap);
133
+
134
+ return useConfirmSwapStore.setState({
135
+ errors: [],
136
+ warnings: [],
137
+ proceedAnyway: false,
138
+ });
139
+ }
140
+
141
+ let abortController: AbortController | null = new AbortController();
142
+
143
+ useConfirmSwapStore.setState({ loading: true });
144
+
145
+ const requestBody = createBestRouteRequestBody(
146
+ fromToken,
147
+ toToken,
148
+ inputAmount,
149
+ accounts,
150
+ selectedWallets,
151
+ disabledLiquiditySources,
152
+ userSlippage,
153
+ true
154
+ );
155
+ const unsubscribeFromBestRouteStore = useBestRouteStore.subscribe(
156
+ (state) => state.bestRoute,
157
+ () => {
158
+ abortController.abort();
159
+ },
160
+ { equalityFn: shallow }
161
+ );
162
+ const unsubscribeFromWalletsStore = useWalletsStore.subscribe(
163
+ (state) => state.selectedWallets,
164
+ () => {
165
+ abortController?.abort();
166
+ },
167
+ {
168
+ equalityFn: (prevState, state) => {
169
+ const selectedWalletsChanged = !state.every(
170
+ (wallet) =>
171
+ !!prevState.find(
172
+ (prevWallet) =>
173
+ wallet.address === prevWallet.address &&
174
+ wallet.chain === prevWallet.chain
175
+ )
176
+ );
177
+
178
+ if (selectedWalletsChanged) return false;
179
+ else return true;
180
+ },
181
+ }
182
+ );
183
+
184
+ httpService
185
+ .getBestRoute(requestBody, { signal: abortController.signal })
186
+ .then((confiremedRoute) => {
187
+ useConfirmSwapStore.setState({ loading: false });
188
+
189
+ if (
190
+ !confiremedRoute.result ||
191
+ !new BigNumber(confiremedRoute.requestAmount).isEqualTo(
192
+ new BigNumber(inputAmount || '-1')
193
+ )
194
+ )
195
+ return useConfirmSwapStore.setState((prevState) => ({
196
+ errors: prevState.errors.concat({
197
+ type: ConfirmSwapErrorTypes.NO_ROUTE,
198
+ }),
199
+ }));
200
+
201
+ const confirmSwap: Partial<ConfirmSwapState> = {
202
+ loading: false,
203
+ errors: [],
204
+ warnings: [],
205
+ proceedAnyway,
206
+ };
207
+
208
+ const routeChanged = isRouteChanged(initialRoute, confiremedRoute!);
209
+
210
+ if (routeChanged) {
211
+ setBestRoute(confiremedRoute);
212
+ const newRouteOutputUsdValue = new BigNumber(
213
+ confiremedRoute.result?.outputAmount || '0'
214
+ ).multipliedBy(toToken.usdPrice || 0);
215
+
216
+ const outputRatio = getOutputRatio(
217
+ inputUsdValue,
218
+ newRouteOutputUsdValue
219
+ );
220
+ const highValueLoss = outputRatioHasWarning(inputUsdValue, outputRatio);
221
+
222
+ if (isNumberOfSwapsChanged(initialRoute, confiremedRoute))
223
+ confirmSwap.warnings.push({
224
+ type: ConfirmSwapWarningTypes.ROUTE_UPDATED,
225
+ });
226
+ else if (isRouteSwappersUpdated(initialRoute, confiremedRoute))
227
+ confirmSwap.warnings.push({
228
+ type: ConfirmSwapWarningTypes.ROUTE_SWAPPERS_UPDATED,
229
+ });
230
+ else isRouteInternalCoinsUpdated(initialRoute, confiremedRoute);
231
+ confirmSwap.warnings.push({
232
+ type: ConfirmSwapWarningTypes.ROUTE_COINS_UPDATED,
233
+ });
234
+ if (highValueLoss)
235
+ confirmSwap.errors.push({
236
+ type: ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS,
237
+ });
238
+ else if (isOutputAmountChangedALot(initialRoute, confiremedRoute))
239
+ confirmSwap.warnings.push({
240
+ type: ConfirmSwapWarningTypes.ROUTE_AND_OUTPUT_AMOUNT_UPDATED,
241
+ newOutputAmount: numberToString(
242
+ getRouteOutputAmount(confiremedRoute)
243
+ ),
244
+ percentageChange: numberToString(
245
+ getPercentageChange(
246
+ getRouteOutputAmount(initialRoute),
247
+ getRouteOutputAmount(confiremedRoute)
248
+ ),
249
+ null,
250
+ 2
251
+ ),
252
+ });
253
+ }
254
+
255
+ const balanceWarnings = getBalanceWarnings(
256
+ confiremedRoute,
257
+ selectedWallets
258
+ );
259
+ const enoughBalance = balanceWarnings.length === 0;
260
+
261
+ if (!enoughBalance)
262
+ confirmSwap.warnings.push({
263
+ type: ConfirmSwapWarningTypes.INSUFFICIENT_BALANCE,
264
+ messages: balanceWarnings,
265
+ });
266
+
267
+ const minRequiredSlippage = getMinRequiredSlippage(initialRoute);
268
+
269
+ if (!hasProperSlippage(userSlippage.toString(), minRequiredSlippage))
270
+ confirmSwap.errors.push({
271
+ type: ConfirmSwapErrorTypes.INSUFFICIENT_SLIPPAGE,
272
+ minRequiredSlippage,
273
+ });
274
+
275
+ const noErrors = confirmSwap.errors.length === 0;
276
+ const noWarnings = confirmSwap.warnings.length === 0;
277
+
278
+ if (
279
+ (noErrors || (!noErrors && proceedAnyway)) &&
280
+ (noWarnings || (!noWarnings && proceedAnyway))
281
+ ) {
282
+ const swapSettings: PendingSwapSettings = {
283
+ slippage: userSlippage.toString(),
284
+ disabledSwappersGroups: disabledLiquiditySources,
285
+ };
286
+
287
+ const newSwap = calculatePendingSwap(
288
+ inputAmount.toString(),
289
+ initialRoute,
290
+ getWalletsForNewSwap(selectedWallets),
291
+ swapSettings,
292
+ false,
293
+ meta
294
+ );
295
+
296
+ console.log('new swap:', newSwap);
297
+ } else if (!proceedAnyway) confirmSwap.proceedAnyway = true;
298
+
299
+ abortController = null;
300
+ useConfirmSwapStore.setState(confirmSwap);
301
+ unsubscribeFromBestRouteStore();
302
+ unsubscribeFromWalletsStore();
303
+ })
304
+ .catch((error) => {
305
+ abortController = null;
306
+ if (error.code === 'ERR_CANCELED') {
307
+ useConfirmSwapStore.setState({
308
+ errors: [],
309
+ warnings: [],
310
+ loading: false,
311
+ proceedAnyway: false,
312
+ });
313
+ unsubscribeFromBestRouteStore();
314
+ unsubscribeFromWalletsStore();
315
+ }
316
+
317
+ const status = error.response?.status;
318
+
319
+ useConfirmSwapStore.setState((prevState) => ({
320
+ loading: false,
321
+ errors: prevState.errors.concat({
322
+ type: ConfirmSwapErrorTypes.REQUEST_FAILED,
323
+ status,
324
+ }),
325
+ }));
326
+ });
327
+ };
@@ -1,6 +1,7 @@
1
1
  import { create } from 'zustand';
2
- import { persist } from 'zustand/middleware';
3
- import { immer } from 'zustand/middleware/immer';
2
+ import { persist, subscribeWithSelector } from 'zustand/middleware';
3
+ import { DEFAULT_SLIPPAGE } from '../constants/swapSettings';
4
+ import { removeDuplicateFrom } from '../utils/common';
4
5
  import { useMetaStore } from './meta';
5
6
  import createSelectors from './selectors';
6
7
 
@@ -9,12 +10,12 @@ type Theme = 'auto' | 'dark' | 'light';
9
10
  interface Settings {
10
11
  slippage: number;
11
12
  customSlippage: number | null;
12
- infinitApprove: boolean;
13
+ infiniteApprove: boolean;
13
14
  disabledLiquiditySources: string[];
14
15
  theme: Theme;
15
16
  setSlippage: (slippage: number) => void;
16
17
  setCustomSlippage: (customSlippage: number | null) => void;
17
- toggleInfinitApprove: () => void;
18
+ toggleInfiniteApprove: () => void;
18
19
  toggleLiquiditySource: (name: string) => void;
19
20
  setTheme: (theme: Theme) => void;
20
21
  toggleAllLiquiditySources: () => void;
@@ -23,50 +24,61 @@ interface Settings {
23
24
  export const useSettingsStore = createSelectors(
24
25
  create<Settings>()(
25
26
  persist(
26
- immer((set) => ({
27
- slippage: 1,
27
+ subscribeWithSelector((set) => ({
28
+ slippage: DEFAULT_SLIPPAGE,
28
29
  customSlippage: null,
29
- infinitApprove: false,
30
+ infiniteApprove: false,
30
31
  disabledLiquiditySources: [],
31
32
  theme: 'auto',
32
33
  setSlippage: (slippage) =>
33
- set((state) => {
34
- state.slippage = slippage;
35
- }),
36
- setCustomSlippage: (customSlippage) => {
37
- return set((state) => {
38
- state.customSlippage = customSlippage;
39
- });
40
- },
34
+ set(() => ({
35
+ slippage: slippage,
36
+ })),
37
+ setCustomSlippage: (customSlippage) =>
38
+ set(() => ({
39
+ customSlippage: customSlippage,
40
+ })),
41
41
  toggleAllLiquiditySources: () =>
42
42
  set((state) => {
43
43
  const { swappers } = useMetaStore.getState().meta;
44
+ const swappersGroup = removeDuplicateFrom(
45
+ swappers.map((swapper) => swapper.swapperGroup)
46
+ );
44
47
 
45
- if (swappers.length - state.disabledLiquiditySources.length === 0)
46
- state.disabledLiquiditySources = [];
48
+ if (swappersGroup.length === state.disabledLiquiditySources.length)
49
+ return { disabledLiquiditySources: [] };
47
50
  else {
48
- const allSwappers = swappers.map((swapper) => swapper.swapperGroup);
49
- state.disabledLiquiditySources = allSwappers;
51
+ return {
52
+ disabledLiquiditySources: swappersGroup,
53
+ };
50
54
  }
51
55
  }),
52
- toggleInfinitApprove: () =>
53
- set((state) => {
54
- state.infinitApprove = !state.infinitApprove;
55
- }),
56
+ toggleInfiniteApprove: () =>
57
+ set((state) => ({
58
+ infiniteApprove: !state.infiniteApprove,
59
+ })),
56
60
  toggleLiquiditySource: (name) =>
57
61
  set((state) => {
58
- state.disabledLiquiditySources = state.disabledLiquiditySources.includes(name)
59
- ? state.disabledLiquiditySources.filter((liquiditySource) => liquiditySource != name)
60
- : state.disabledLiquiditySources.concat(name);
62
+ if (state.disabledLiquiditySources.includes(name))
63
+ return {
64
+ disabledLiquiditySources: state.disabledLiquiditySources.filter(
65
+ (liquiditySource) => liquiditySource != name
66
+ ),
67
+ };
68
+ else
69
+ return {
70
+ disabledLiquiditySources:
71
+ state.disabledLiquiditySources.concat(name),
72
+ };
61
73
  }),
62
74
  setTheme: (theme) =>
63
- set((state) => {
64
- state.theme = theme;
65
- }),
75
+ set(() => ({
76
+ theme,
77
+ })),
66
78
  })),
67
79
  {
68
80
  name: 'user-settings',
69
- },
70
- ),
71
- ),
81
+ }
82
+ )
83
+ )
72
84
  );
@@ -0,0 +1,15 @@
1
+ import { create } from 'zustand';
2
+ import createSelectors from './selectors';
3
+
4
+ interface UiState {
5
+ connectWalletsButtonDisabled: boolean;
6
+ toggleConnectWalletsButton: () => void;
7
+ }
8
+
9
+ export const useUiStore = createSelectors(
10
+ create<UiState>()((set) => ({
11
+ connectWalletsButtonDisabled: false,
12
+ toggleConnectWalletsButton: () =>
13
+ set((state) => ({ connectWalletsButtonDisabled: !state.connectWalletsButtonDisabled })),
14
+ })),
15
+ );