@rango-dev/widget-embedded 0.48.0 → 0.48.1-next.0

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 (59) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/containers/Inputs/Inputs.d.ts.map +1 -1
  3. package/dist/containers/Refuel/Refuel.d.ts +5 -0
  4. package/dist/containers/Refuel/Refuel.d.ts.map +1 -0
  5. package/dist/containers/Refuel/Refuel.types.d.ts +5 -0
  6. package/dist/containers/Refuel/Refuel.types.d.ts.map +1 -0
  7. package/dist/containers/Refuel/index.d.ts +2 -0
  8. package/dist/containers/Refuel/index.d.ts.map +1 -0
  9. package/dist/containers/WidgetProvider/WidgetProvider.d.ts.map +1 -1
  10. package/dist/hooks/useBootstrap/useBootstrap.d.ts.map +1 -1
  11. package/dist/hooks/useConfirmSwap/useConfirmSwap.d.ts.map +1 -1
  12. package/dist/hooks/useSwapMode.d.ts +11 -0
  13. package/dist/hooks/useSwapMode.d.ts.map +1 -0
  14. package/dist/index.d.ts +3 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -2
  17. package/dist/index.js.map +4 -4
  18. package/dist/pages/HistoryPage.d.ts.map +1 -1
  19. package/dist/pages/Home.d.ts.map +1 -1
  20. package/dist/pages/SelectBlockchainPage.d.ts.map +1 -1
  21. package/dist/store/quote.d.ts +119 -4
  22. package/dist/store/quote.d.ts.map +1 -1
  23. package/dist/store/slices/data.d.ts +1 -0
  24. package/dist/store/slices/data.d.ts.map +1 -1
  25. package/dist/widget-embedded.build.json +1 -1
  26. package/package.json +3 -3
  27. package/src/components/BlockchainsSection/BlockchainsSection.tsx +2 -2
  28. package/src/components/ConfirmWalletsModal/ConfirmWalletsModal.tsx +1 -1
  29. package/src/components/CustomDestination/CustomDestination.tsx +1 -1
  30. package/src/components/Quotes/Quotes.tsx +1 -1
  31. package/src/components/Quotes/SelectStrategy.tsx +1 -1
  32. package/src/components/SameTokensWarning/SameTokensWarning.tsx +1 -1
  33. package/src/components/SwapDetails/SwapDetails.tsx +1 -1
  34. package/src/components/SwitchFromAndTo/SwitchFromAndTo.tsx +1 -1
  35. package/src/components/TokenList/TokenList.tsx +1 -1
  36. package/src/containers/Inputs/Inputs.tsx +5 -2
  37. package/src/containers/QuoteInfo/QuoteInfo.tsx +1 -1
  38. package/src/containers/Refuel/Refuel.tsx +25 -0
  39. package/src/containers/Refuel/Refuel.types.ts +5 -0
  40. package/src/containers/Refuel/index.ts +1 -0
  41. package/src/containers/WidgetInfo/WidgetInfo.tsx +2 -2
  42. package/src/containers/WidgetProvider/WidgetProvider.tsx +6 -0
  43. package/src/hooks/useBootstrap/useBootstrap.ts +6 -7
  44. package/src/hooks/useConfirmSwap/useConfirmSwap.ts +12 -9
  45. package/src/hooks/useSwapInput.ts +1 -1
  46. package/src/hooks/useSwapMode.ts +20 -0
  47. package/src/hooks/useSyncStoresWithConfig.ts +1 -1
  48. package/src/hooks/useSyncUrlAndStore/useSyncUrlAndStore.ts +1 -1
  49. package/src/hooks/useUpdateQuoteInputs/useUpdateQuoteInputs.ts +1 -1
  50. package/src/index.ts +4 -0
  51. package/src/pages/ConfirmSwapPage.tsx +1 -1
  52. package/src/pages/CustomTokensPage.tsx +1 -1
  53. package/src/pages/HistoryPage.tsx +51 -4
  54. package/src/pages/Home.tsx +19 -9
  55. package/src/pages/Routes.tsx +1 -1
  56. package/src/pages/SelectBlockchainPage.tsx +29 -15
  57. package/src/pages/SelectSwapItemPage/SelectSwapItemsPage.tsx +1 -1
  58. package/src/store/quote.ts +282 -253
  59. package/src/store/slices/data.ts +9 -0
@@ -1,3 +1,5 @@
1
+ import type { BlockchainMeta } from 'rango-types';
2
+
1
3
  import { i18n } from '@lingui/core';
2
4
  import {
3
5
  Divider,
@@ -11,6 +13,7 @@ import { BlockchainList } from '../components/BlockchainList';
11
13
  import { Layout, PageContainer } from '../components/Layout';
12
14
  import { SearchInput } from '../components/SearchInput';
13
15
  import { useNavigateBack } from '../hooks/useNavigateBack';
16
+ import { useSwapMode } from '../hooks/useSwapMode';
14
17
  import { useAppStore } from '../store/AppStore';
15
18
  import { useQuoteStore } from '../store/quote';
16
19
 
@@ -24,10 +27,12 @@ export function SelectBlockchainPage(props: PropTypes) {
24
27
  const navigateBack = useNavigateBack();
25
28
  const [searchedFor, setSearchedFor] = useState<string>('');
26
29
  const [blockchainCategory, setBlockchainCategory] = useState<string>('ALL');
27
- const setToBlockchain = useQuoteStore.use.setToBlockchain();
28
- const setFromBlockchain = useQuoteStore.use.setFromBlockchain();
29
- const { fetchStatus } = useAppStore();
30
+ const setToBlockchain = useQuoteStore().use.setToBlockchain();
31
+ const setFromBlockchain = useQuoteStore().use.setFromBlockchain();
32
+ const setToToken = useQuoteStore().use.setToToken();
33
+ const { fetchStatus, findNativeToken } = useAppStore();
30
34
  const navigate = useNavigate();
35
+ const { swapMode } = useSwapMode();
31
36
 
32
37
  const blockchains = useAppStore().blockchains({
33
38
  type,
@@ -36,6 +41,26 @@ export function SelectBlockchainPage(props: PropTypes) {
36
41
 
37
42
  const showCategory = !props.hideCategory && activeCategoriesCount !== 1;
38
43
 
44
+ const handleBlockchainChange = (blockchain: BlockchainMeta) => {
45
+ if (type === 'custom-token') {
46
+ navigate(`..?blockchain=${blockchain.name}`, { replace: true });
47
+ } else {
48
+ if (type === 'source') {
49
+ setFromBlockchain(blockchain);
50
+ } else {
51
+ if (swapMode === 'swap') {
52
+ setToBlockchain(blockchain);
53
+ } else {
54
+ const blockchainNativeToken = findNativeToken(blockchain);
55
+ if (blockchainNativeToken) {
56
+ setToToken({ token: blockchainNativeToken, meta: { blockchains } });
57
+ }
58
+ }
59
+ }
60
+ navigateBack();
61
+ }
62
+ };
63
+
39
64
  return (
40
65
  <Layout
41
66
  header={{
@@ -72,18 +97,7 @@ export function SelectBlockchainPage(props: PropTypes) {
72
97
  showTitle={type !== 'custom-token'}
73
98
  searchedFor={searchedFor}
74
99
  blockchainCategory={blockchainCategory}
75
- onChange={(blockchain) => {
76
- if (type === 'custom-token') {
77
- navigate(`..?blockchain=${blockchain.name}`, { replace: true });
78
- } else {
79
- if (type === 'source') {
80
- setFromBlockchain(blockchain);
81
- } else {
82
- setToBlockchain(blockchain);
83
- }
84
- navigateBack();
85
- }
86
- }}
100
+ onChange={handleBlockchainChange}
87
101
  />
88
102
  </PageContainer>
89
103
  </Layout>
@@ -35,7 +35,7 @@ export function SelectSwapItemsPage(props: PropTypes) {
35
35
  setToToken,
36
36
  setFromBlockchain,
37
37
  setToBlockchain,
38
- } = useQuoteStore();
38
+ } = useQuoteStore()();
39
39
  const { getBalanceFor } = useAppStore();
40
40
  const {
41
41
  fetch,
@@ -6,12 +6,14 @@ import type {
6
6
  PreferenceType,
7
7
  Token,
8
8
  } from 'rango-sdk';
9
+ import type { StateCreator } from 'zustand';
9
10
 
10
11
  import BigNumber from 'bignumber.js';
11
12
  import { create } from 'zustand';
12
13
  import { subscribeWithSelector } from 'zustand/middleware';
13
14
 
14
15
  import { ZERO } from '../constants/numbers';
16
+ import { useSwapMode } from '../hooks/useSwapMode';
15
17
  import { eventEmitter } from '../services/eventEmitter';
16
18
  import {
17
19
  type QuoteError,
@@ -95,7 +97,7 @@ export interface QuoteState {
95
97
  sanitizeInputAmount: (amount: string) => void;
96
98
  setSelectedQuote: (quote: SelectedQuote | null) => void;
97
99
  retry: (retryQuote: RetryQuote) => void;
98
- switchFromAndTo: () => void;
100
+ switchFromAndTo: (options?: { toToken?: Token }) => void;
99
101
  setQuoteWalletConfirmed: (flag: boolean) => void;
100
102
  setSelectedWallets: (wallets: Wallet[]) => void;
101
103
  setCustomDestination: (address: string | null) => void;
@@ -103,276 +105,303 @@ export interface QuoteState {
103
105
  setQuoteWarningsConfirmed: (flag: boolean) => void;
104
106
  }
105
107
 
106
- export const useQuoteStore = createSelectors(
107
- create<QuoteState>()(
108
- subscribeWithSelector((set) => ({
109
- fromBlockchain: null,
110
- fromToken: null,
111
- inputAmount: '',
108
+ const initializer: StateCreator<
109
+ QuoteState,
110
+ [['zustand/subscribeWithSelector', never]],
111
+ []
112
+ > = (
113
+ set: (
114
+ partial:
115
+ | QuoteState
116
+ | Partial<QuoteState>
117
+ | ((state: QuoteState) => QuoteState | Partial<QuoteState>),
118
+ replace?: boolean | undefined
119
+ ) => void
120
+ ) => ({
121
+ fromBlockchain: null,
122
+ fromToken: null,
123
+ inputAmount: '',
124
+ outputAmount: null,
125
+ inputUsdValue: new BigNumber(0),
126
+ outputUsdValue: new BigNumber(0),
127
+ toBlockchain: null,
128
+ toToken: null,
129
+ refetchQuote: true,
130
+ sortStrategy: 'SMART',
131
+ selectedQuote: null,
132
+ quotes: null,
133
+ error: null,
134
+ warning: null,
135
+ quoteWalletsConfirmed: false,
136
+ selectedWallets: [],
137
+ customDestination: null,
138
+ quoteWarningsConfirmed: false,
139
+ updateQuotePartialState: (key, value) =>
140
+ set((state) => ({
141
+ ...state,
142
+ [key]: value,
143
+ })),
144
+ setSelectedQuote: (quote) =>
145
+ set((state) => {
146
+ let outputAmount: BigNumber | null = null;
147
+ let outputUsdValue: BigNumber = ZERO;
148
+
149
+ let inputUsdValue = state.inputUsdValue;
150
+ if (!isPositiveNumber(state.inputAmount)) {
151
+ return {};
152
+ }
153
+ if (!!quote) {
154
+ outputAmount = !!quote?.outputAmount
155
+ ? new BigNumber(quote?.outputAmount)
156
+ : null;
157
+ inputUsdValue = getUsdInputFrom(quote) ?? ZERO;
158
+ outputUsdValue = getUsdOutputFrom(quote) ?? ZERO;
159
+ }
160
+ return {
161
+ selectedQuote: quote,
162
+ ...(!!quote && {
163
+ outputAmount,
164
+ outputUsdValue,
165
+ inputUsdValue,
166
+ }),
167
+ };
168
+ }),
169
+ resetAlerts: () =>
170
+ set(() => ({
171
+ error: null,
172
+ warning: null,
173
+ })),
174
+ resetQuote: () =>
175
+ set(() => ({
176
+ selectedQuote: null,
112
177
  outputAmount: null,
113
- inputUsdValue: new BigNumber(0),
114
178
  outputUsdValue: new BigNumber(0),
115
- toBlockchain: null,
116
- toToken: null,
117
- refetchQuote: true,
118
- sortStrategy: 'SMART',
119
- selectedQuote: null,
120
179
  quotes: null,
180
+ refetchQuote: true,
121
181
  error: null,
122
182
  warning: null,
123
- quoteWalletsConfirmed: false,
124
- selectedWallets: [],
125
- customDestination: null,
126
- quoteWarningsConfirmed: false,
127
- updateQuotePartialState: (key, value) =>
128
- set((state) => ({
129
- ...state,
130
- [key]: value,
131
- })),
132
- setSelectedQuote: (quote) =>
133
- set((state) => {
134
- let outputAmount: BigNumber | null = null;
135
- let outputUsdValue: BigNumber = ZERO;
183
+ })),
184
+ setFromBlockchain: (chain) => {
185
+ set((state) => {
186
+ if (state.fromBlockchain?.name === chain?.name) {
187
+ return {};
188
+ }
136
189
 
137
- let inputUsdValue = state.inputUsdValue;
138
- if (!isPositiveNumber(state.inputAmount)) {
139
- return {};
140
- }
141
- if (!!quote) {
142
- outputAmount = !!quote?.outputAmount
143
- ? new BigNumber(quote?.outputAmount)
144
- : null;
145
- inputUsdValue = getUsdInputFrom(quote) ?? ZERO;
146
- outputUsdValue = getUsdOutputFrom(quote) ?? ZERO;
147
- }
148
- return {
149
- selectedQuote: quote,
150
- ...(!!quote && {
151
- outputAmount,
152
- outputUsdValue,
153
- inputUsdValue,
154
- }),
155
- };
156
- }),
157
- resetAlerts: () =>
158
- set(() => ({
159
- error: null,
160
- warning: null,
161
- })),
162
- resetQuote: () =>
163
- set(() => ({
190
+ return {
191
+ fromBlockchain: chain,
192
+ inputUsdValue: new BigNumber(0),
193
+ ...(state.fromToken && {
164
194
  selectedQuote: null,
195
+ fromToken: null,
165
196
  outputAmount: null,
166
197
  outputUsdValue: new BigNumber(0),
167
- quotes: null,
168
- refetchQuote: true,
169
- error: null,
170
- warning: null,
171
- })),
172
- setFromBlockchain: (chain) => {
173
- set((state) => {
174
- if (state.fromBlockchain?.name === chain?.name) {
175
- return {};
176
- }
177
-
178
- return {
179
- fromBlockchain: chain,
180
- inputUsdValue: new BigNumber(0),
181
- ...(state.fromToken && {
182
- selectedQuote: null,
183
- fromToken: null,
184
- outputAmount: null,
185
- outputUsdValue: new BigNumber(0),
186
- }),
187
- };
188
- });
189
- },
190
- setFromToken: (params) => {
191
- return set((state) => ({
192
- fromToken: params.token,
193
- ...(params.token && {
194
- fromBlockchain:
195
- params.meta.blockchains.find(
196
- (blockchain) => blockchain.name === params.token.blockchain
197
- ) ?? null,
198
- }),
199
- ...(!!state.inputAmount && {
200
- inputUsdValue: getUsdValue(params.token, state.inputAmount),
201
- }),
202
- }));
203
- },
204
- setToBlockchain: (chain) => {
205
- set((state) => {
206
- if (state.toBlockchain?.name === chain?.name) {
207
- return {};
208
- }
209
-
210
- return {
211
- toBlockchain: chain,
212
- ...(state.toToken && {
213
- selectedQuote: null,
214
- toToken: null,
215
- outputAmount: null,
216
- outputUsdValue: new BigNumber(0),
217
- }),
218
- };
219
- });
220
- },
221
- setToToken: (params) => {
222
- return set(() => ({
223
- toToken: params.token,
224
- ...(params.token && {
225
- toBlockchain:
226
- params.meta.blockchains.find(
227
- (blockchain) => blockchain.name === params.token.blockchain
228
- ) ?? null,
229
- }),
230
- }));
231
- },
232
- sanitizeInputAmount: (amount) => {
233
- const sanitized = sanitizeInputAmount(amount);
234
-
235
- set(() => ({
236
- inputAmount: sanitized,
237
- }));
238
- },
239
- setInputAmount: (amount) => {
240
- let sanitized = amount;
241
- if (!isZeroValue(amount)) {
242
- // sanitize once a meaningful digit is entered (e.g. "00001" → "1")
243
- sanitized = removeLeadingZeros(sanitized);
244
- sanitized = ensureLeadingZeroForDecimal(sanitized);
245
- }
246
- set((state) => ({
247
- inputAmount: sanitized,
248
- ...(!sanitized && {
249
- outputAmount: null,
250
- outputUsdValue: new BigNumber(0),
251
- selectedQuote: null,
252
- }),
253
- ...(!!state.fromToken && {
254
- inputUsdValue: getUsdValue(state.fromToken, sanitized),
255
- }),
256
- }));
257
- },
258
- retry: (retryQuote) => {
259
- const {
260
- fromBlockchain,
261
- fromToken,
262
- toBlockchain,
263
- toToken,
264
- inputAmount,
265
- } = retryQuote;
198
+ }),
199
+ };
200
+ });
201
+ },
202
+ setFromToken: (params) => {
203
+ return set((state) => ({
204
+ fromToken: params.token,
205
+ ...(params.token && {
206
+ fromBlockchain:
207
+ params.meta.blockchains.find(
208
+ (blockchain) => blockchain.name === params.token.blockchain
209
+ ) ?? null,
210
+ }),
211
+ ...(!!state.inputAmount && {
212
+ inputUsdValue: getUsdValue(params.token, state.inputAmount),
213
+ }),
214
+ }));
215
+ },
216
+ setToBlockchain: (chain) => {
217
+ set((state) => {
218
+ if (state.toBlockchain?.name === chain?.name) {
219
+ return {};
220
+ }
266
221
 
267
- set({
268
- fromBlockchain,
269
- fromToken,
270
- inputAmount,
271
- outputAmount: null,
272
- inputUsdValue: getUsdValue(fromToken ?? null, inputAmount),
273
- outputUsdValue: new BigNumber(0),
274
- toBlockchain,
275
- toToken,
276
- selectedQuote: null,
277
- });
278
- },
279
- switchFromAndTo: () =>
280
- set((state) => ({
281
- fromBlockchain: state.toBlockchain,
282
- fromToken: state.toToken,
283
- toBlockchain: state.fromBlockchain,
284
- toToken: state.fromToken,
285
- inputAmount: state.outputAmount?.toString() || '',
286
- inputUsdValue: state.toToken
287
- ? getUsdValue(state.toToken, state.outputAmount?.toString() || '')
288
- : new BigNumber(0),
289
- })),
290
- resetFromBlockchain: () =>
291
- set(() => ({
292
- fromToken: null,
293
- fromBlockchain: null,
294
- outputUsdValue: new BigNumber(0),
295
- inputUsdValue: new BigNumber(0),
296
- inputAmount: '',
297
- outputAmount: null,
222
+ return {
223
+ toBlockchain: chain,
224
+ ...(state.toToken && {
298
225
  selectedQuote: null,
299
- })),
300
- resetToBlockchain: () =>
301
- set(() => ({
302
226
  toToken: null,
303
- toBlockchain: null,
304
227
  outputAmount: null,
305
228
  outputUsdValue: new BigNumber(0),
306
- selectedQuote: null,
307
- })),
308
- setQuoteWalletConfirmed: (flag) =>
309
- set({
310
- quoteWalletsConfirmed: flag,
311
- }),
312
- setSelectedWallets: (wallets) => set({ selectedWallets: wallets }),
313
- setCustomDestination: (address) => set({ customDestination: address }),
314
- resetQuoteWallets: () =>
315
- set({
316
- quoteWalletsConfirmed: false,
317
- selectedWallets: [],
318
- customDestination: null,
319
229
  }),
320
- setQuoteWarningsConfirmed: (flag) =>
321
- set({ quoteWarningsConfirmed: flag }),
322
- }))
323
- )
324
- );
230
+ };
231
+ });
232
+ },
233
+ setToToken: (params) => {
234
+ return set(() => ({
235
+ toToken: params.token,
236
+ ...(params.token && {
237
+ toBlockchain:
238
+ params.meta.blockchains.find(
239
+ (blockchain) => blockchain.name === params.token.blockchain
240
+ ) ?? null,
241
+ }),
242
+ }));
243
+ },
244
+ sanitizeInputAmount: (amount) => {
245
+ const sanitized = sanitizeInputAmount(amount);
325
246
 
326
- export const unsubscribeQuoteStore = useQuoteStore.subscribe(
327
- (selectedState, previousSelectedState) => {
328
- if (
329
- selectedState.fromBlockchain !== previousSelectedState.fromBlockchain ||
330
- selectedState.fromToken !== previousSelectedState.fromToken ||
331
- selectedState.toBlockchain !== previousSelectedState.toBlockchain ||
332
- selectedState.toToken !== previousSelectedState.toToken ||
333
- selectedState.inputAmount !== previousSelectedState.inputAmount
334
- ) {
335
- // useEffect hook can not be used in Zustand subscribe
336
- eventEmitter.emit(WidgetEvents.QuoteEvent, {
337
- type: QuoteEventTypes.QUOTE_INPUT_UPDATE,
338
- payload: {
339
- fromBlockchain: selectedState.fromBlockchain?.name,
340
- toBlockchain: selectedState.toBlockchain?.name,
341
- fromToken: selectedState.fromToken
342
- ? {
343
- symbol: selectedState.fromToken.symbol,
344
- name: selectedState.fromToken.name,
345
- address: selectedState.fromToken.address,
346
- }
347
- : undefined,
348
- toToken: selectedState.toToken
349
- ? {
350
- symbol: selectedState.toToken.symbol,
351
- name: selectedState.toToken.name,
352
- address: selectedState.toToken.address,
353
- }
354
- : undefined,
355
- requestAmount: selectedState.inputAmount,
356
- },
357
- });
247
+ set(() => ({
248
+ inputAmount: sanitized,
249
+ }));
250
+ },
251
+ setInputAmount: (amount) => {
252
+ let sanitized = amount;
253
+ if (!isZeroValue(amount)) {
254
+ // sanitize once a meaningful digit is entered (e.g. "00001" → "1")
255
+ sanitized = removeLeadingZeros(sanitized);
256
+ sanitized = ensureLeadingZeroForDecimal(sanitized);
358
257
  }
258
+ set((state) => ({
259
+ inputAmount: sanitized,
260
+ ...(!sanitized && {
261
+ outputAmount: null,
262
+ outputUsdValue: new BigNumber(0),
263
+ selectedQuote: null,
264
+ }),
265
+ ...(!!state.fromToken && {
266
+ inputUsdValue: getUsdValue(state.fromToken, sanitized),
267
+ }),
268
+ }));
269
+ },
270
+ retry: (retryQuote) => {
271
+ const { fromBlockchain, fromToken, toBlockchain, toToken, inputAmount } =
272
+ retryQuote;
359
273
 
360
- if (
361
- selectedState.selectedQuote?.requestId !==
362
- previousSelectedState.selectedQuote?.requestId
363
- ) {
364
- eventEmitter.emit(WidgetEvents.QuoteEvent, {
365
- type: QuoteEventTypes.QUOTE_OUTPUT_UPDATE,
366
- payload: selectedState.selectedQuote
274
+ set({
275
+ fromBlockchain,
276
+ fromToken,
277
+ inputAmount,
278
+ outputAmount: null,
279
+ inputUsdValue: getUsdValue(fromToken ?? null, inputAmount),
280
+ outputUsdValue: new BigNumber(0),
281
+ toBlockchain,
282
+ toToken,
283
+ selectedQuote: null,
284
+ });
285
+ },
286
+ switchFromAndTo: () =>
287
+ set((state) => ({
288
+ fromBlockchain: state.toBlockchain,
289
+ fromToken: state.toToken,
290
+ toBlockchain: state.fromBlockchain,
291
+ toToken: state.fromToken,
292
+ inputAmount: state.outputAmount?.toString() || '',
293
+ inputUsdValue: state.toToken
294
+ ? getUsdValue(state.toToken, state.outputAmount?.toString() || '')
295
+ : new BigNumber(0),
296
+ })),
297
+ resetFromBlockchain: () =>
298
+ set(() => ({
299
+ fromToken: null,
300
+ fromBlockchain: null,
301
+ outputUsdValue: new BigNumber(0),
302
+ inputUsdValue: new BigNumber(0),
303
+ inputAmount: '',
304
+ outputAmount: null,
305
+ selectedQuote: null,
306
+ })),
307
+ resetToBlockchain: () =>
308
+ set(() => ({
309
+ toToken: null,
310
+ toBlockchain: null,
311
+ outputAmount: null,
312
+ outputUsdValue: new BigNumber(0),
313
+ selectedQuote: null,
314
+ })),
315
+ setQuoteWalletConfirmed: (flag) =>
316
+ set({
317
+ quoteWalletsConfirmed: flag,
318
+ }),
319
+ setSelectedWallets: (wallets) => set({ selectedWallets: wallets }),
320
+ setCustomDestination: (address) => set({ customDestination: address }),
321
+ resetQuoteWallets: () =>
322
+ set({
323
+ quoteWalletsConfirmed: false,
324
+ selectedWallets: [],
325
+ customDestination: null,
326
+ }),
327
+ setQuoteWarningsConfirmed: (flag) => set({ quoteWarningsConfirmed: flag }),
328
+ });
329
+
330
+ const createSwapQuoteSelectors = create<QuoteState>()(
331
+ subscribeWithSelector(initializer)
332
+ );
333
+ const createRefuelQuoteSelectors = create<QuoteState>()(
334
+ subscribeWithSelector(initializer)
335
+ );
336
+
337
+ export const useSwapQuoteStore = createSelectors(createSwapQuoteSelectors);
338
+ export const useRefuelQuoteStore = createSelectors(createRefuelQuoteSelectors);
339
+
340
+ export function useQuoteStore() {
341
+ const { swapMode } = useSwapMode();
342
+ return createSelectors(
343
+ swapMode === 'refuel'
344
+ ? createRefuelQuoteSelectors
345
+ : createSwapQuoteSelectors
346
+ );
347
+ }
348
+
349
+ const subscribeCallback = (
350
+ selectedState: QuoteState,
351
+ previousSelectedState: QuoteState
352
+ ) => {
353
+ if (
354
+ selectedState.fromBlockchain !== previousSelectedState.fromBlockchain ||
355
+ selectedState.fromToken !== previousSelectedState.fromToken ||
356
+ selectedState.toBlockchain !== previousSelectedState.toBlockchain ||
357
+ selectedState.toToken !== previousSelectedState.toToken ||
358
+ selectedState.inputAmount !== previousSelectedState.inputAmount
359
+ ) {
360
+ // useEffect hook can not be used in Zustand subscribe
361
+ eventEmitter.emit(WidgetEvents.QuoteEvent, {
362
+ type: QuoteEventTypes.QUOTE_INPUT_UPDATE,
363
+ payload: {
364
+ fromBlockchain: selectedState.fromBlockchain?.name,
365
+ toBlockchain: selectedState.toBlockchain?.name,
366
+ fromToken: selectedState.fromToken
367
367
  ? {
368
- requestAmount: selectedState.selectedQuote.requestAmount,
369
- swaps: selectedState.selectedQuote.swaps,
370
- outputAmount: selectedState.selectedQuote.outputAmount,
371
- resultType: selectedState.selectedQuote.resultType,
372
- tags: selectedState.selectedQuote.tags,
368
+ symbol: selectedState.fromToken.symbol,
369
+ name: selectedState.fromToken.name,
370
+ address: selectedState.fromToken.address,
373
371
  }
374
- : null,
375
- });
376
- }
372
+ : undefined,
373
+ toToken: selectedState.toToken
374
+ ? {
375
+ symbol: selectedState.toToken.symbol,
376
+ name: selectedState.toToken.name,
377
+ address: selectedState.toToken.address,
378
+ }
379
+ : undefined,
380
+ requestAmount: selectedState.inputAmount,
381
+ },
382
+ });
377
383
  }
378
- );
384
+
385
+ if (
386
+ selectedState.selectedQuote?.requestId !==
387
+ previousSelectedState.selectedQuote?.requestId
388
+ ) {
389
+ eventEmitter.emit(WidgetEvents.QuoteEvent, {
390
+ type: QuoteEventTypes.QUOTE_OUTPUT_UPDATE,
391
+ payload: selectedState.selectedQuote
392
+ ? {
393
+ requestAmount: selectedState.selectedQuote.requestAmount,
394
+ swaps: selectedState.selectedQuote.swaps,
395
+ outputAmount: selectedState.selectedQuote.outputAmount,
396
+ resultType: selectedState.selectedQuote.resultType,
397
+ tags: selectedState.selectedQuote.tags,
398
+ }
399
+ : null,
400
+ });
401
+ }
402
+ };
403
+
404
+ export const unsubscribeSwapQuoteStore =
405
+ useSwapQuoteStore.subscribe(subscribeCallback);
406
+ export const unsubscribeRefuelQuoteStore =
407
+ useRefuelQuoteStore.subscribe(subscribeCallback);
@@ -56,6 +56,7 @@ export interface DataSlice {
56
56
  swappers: () => SwapperMeta[];
57
57
  isTokenPinned: (token: Token, type: 'source' | 'destination') => boolean;
58
58
  findToken: FindToken;
59
+ findNativeToken: (blockchain: BlockchainMeta) => Token | undefined;
59
60
  fetch: () => Promise<void>;
60
61
  }
61
62
 
@@ -275,6 +276,14 @@ export const createDataSlice: StateCreator<
275
276
  }
276
277
  return token;
277
278
  },
279
+ findNativeToken: (blockchain: BlockchainMeta) => {
280
+ const feeAsset = blockchain.feeAssets[0];
281
+ return get().findToken({
282
+ blockchain: blockchain.name,
283
+ address: feeAsset.address,
284
+ symbol: feeAsset.symbol,
285
+ });
286
+ },
278
287
  isTokenPinned: (token, type) => {
279
288
  const pinnedTokens =
280
289
  type === 'source'