@rango-dev/widget-embedded 0.30.1-next.1 → 0.30.1-next.11

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 (79) hide show
  1. package/dist/components/ConfirmWalletsModal/ConfirmWallets.styles.d.ts +1 -653
  2. package/dist/components/ConfirmWalletsModal/ConfirmWallets.styles.d.ts.map +1 -1
  3. package/dist/components/ConfirmWalletsModal/ConfirmWalletsModal.d.ts.map +1 -1
  4. package/dist/components/ConfirmWalletsModal/WalletList.d.ts.map +1 -1
  5. package/dist/components/CustomDestination/CustomDestination.d.ts +4 -0
  6. package/dist/components/CustomDestination/CustomDestination.d.ts.map +1 -0
  7. package/dist/components/CustomDestination/CustomDestination.styles.d.ts +495 -0
  8. package/dist/components/CustomDestination/CustomDestination.styles.d.ts.map +1 -0
  9. package/dist/components/CustomDestination/CustomDestination.types.d.ts +7 -0
  10. package/dist/components/CustomDestination/CustomDestination.types.d.ts.map +1 -0
  11. package/dist/components/Quote/Quote.styles.d.ts +3 -3
  12. package/dist/components/RefreshModal/RefreshModal.styles.d.ts +3 -3
  13. package/dist/components/SwapDetailsModal/SwapDetailsModal.WalletState.d.ts.map +1 -1
  14. package/dist/containers/Wallets/Wallets.d.ts.map +1 -1
  15. package/dist/hooks/usePrepareBlockchainList/usePrepareBlockchainList.helpers.d.ts +2 -2
  16. package/dist/hooks/useTheme.d.ts.map +1 -1
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +2 -2
  20. package/dist/index.js.map +4 -4
  21. package/dist/pages/Home.d.ts.map +1 -1
  22. package/dist/pages/WalletsPage.d.ts.map +1 -1
  23. package/dist/services/cacheService.d.ts +21 -0
  24. package/dist/services/cacheService.d.ts.map +1 -0
  25. package/dist/store/notification.d.ts.map +1 -1
  26. package/dist/store/slices/config.d.ts +2 -1
  27. package/dist/store/slices/config.d.ts.map +1 -1
  28. package/dist/store/slices/data.d.ts +2 -1
  29. package/dist/store/slices/data.d.ts.map +1 -1
  30. package/dist/store/utils/data.d.ts +20 -0
  31. package/dist/store/utils/data.d.ts.map +1 -0
  32. package/dist/store/utils/data.test.d.ts +2 -0
  33. package/dist/store/utils/data.test.d.ts.map +1 -0
  34. package/dist/store/utils/index.d.ts +2 -0
  35. package/dist/store/utils/index.d.ts.map +1 -0
  36. package/dist/test-utils/fixtures.d.ts +1 -0
  37. package/dist/test-utils/fixtures.d.ts.map +1 -1
  38. package/dist/types/config.d.ts +5 -0
  39. package/dist/types/config.d.ts.map +1 -1
  40. package/dist/types/event.d.ts +21 -15
  41. package/dist/types/event.d.ts.map +1 -1
  42. package/dist/types/notification.d.ts +1 -0
  43. package/dist/types/notification.d.ts.map +1 -1
  44. package/dist/types/wallets.d.ts +1 -1
  45. package/dist/types/wallets.d.ts.map +1 -1
  46. package/dist/utils/events.d.ts +8 -0
  47. package/dist/utils/events.d.ts.map +1 -0
  48. package/dist/utils/settings.d.ts +1 -1
  49. package/dist/utils/swap.d.ts +1 -1
  50. package/dist/utils/swap.d.ts.map +1 -1
  51. package/dist/widget-embedded.build.json +1 -1
  52. package/package.json +10 -10
  53. package/src/components/ConfirmWalletsModal/ConfirmWallets.styles.ts +1 -49
  54. package/src/components/ConfirmWalletsModal/ConfirmWalletsModal.tsx +59 -178
  55. package/src/components/ConfirmWalletsModal/WalletList.tsx +16 -4
  56. package/src/components/CustomDestination/CustomDestination.styles.ts +45 -0
  57. package/src/components/CustomDestination/CustomDestination.tsx +148 -0
  58. package/src/components/CustomDestination/CustomDestination.types.ts +7 -0
  59. package/src/components/SwapDetailsModal/SwapDetailsModal.WalletState.tsx +28 -13
  60. package/src/containers/Wallets/Wallets.tsx +7 -2
  61. package/src/hooks/useTheme.ts +11 -5
  62. package/src/index.ts +4 -0
  63. package/src/pages/Home.tsx +6 -3
  64. package/src/pages/WalletsPage.tsx +25 -11
  65. package/src/services/cacheService.ts +35 -0
  66. package/src/store/notification.ts +13 -1
  67. package/src/store/slices/config.ts +39 -1
  68. package/src/store/slices/data.test.ts +84 -0
  69. package/src/store/slices/data.ts +44 -24
  70. package/src/store/utils/data.test.ts +175 -0
  71. package/src/store/utils/data.ts +117 -0
  72. package/src/store/utils/index.ts +1 -0
  73. package/src/test-utils/fixtures.ts +14 -7
  74. package/src/types/config.ts +3 -1
  75. package/src/types/event.ts +32 -16
  76. package/src/types/notification.ts +1 -0
  77. package/src/types/wallets.ts +1 -1
  78. package/src/utils/events.ts +27 -0
  79. package/src/utils/swap.ts +4 -4
@@ -0,0 +1,175 @@
1
+ import type { Token } from 'rango-sdk';
2
+
3
+ import { describe, expect, test } from 'vitest';
4
+
5
+ import { createToken } from '../../test-utils/fixtures';
6
+ import { createTokenHash } from '../../utils/meta';
7
+
8
+ import { matchTokensFromConfigWithMeta } from './data'; // Adjust path as necessary
9
+
10
+ type MatchTokensFromConfigWithMetaParam = Parameters<
11
+ typeof matchTokensFromConfigWithMeta
12
+ >[0];
13
+
14
+ const BLOCKCHAIN_A = 'blockchainA';
15
+ const BLOCKCHAIN_B = 'blockchainB';
16
+ const BLOCKCHAIN_C = 'blockchainC';
17
+
18
+ const tokens: Token[] = [
19
+ { ...createToken(), blockchain: BLOCKCHAIN_A },
20
+ { ...createToken(), blockchain: BLOCKCHAIN_A },
21
+ { ...createToken(), blockchain: BLOCKCHAIN_B },
22
+ { ...createToken(), blockchain: BLOCKCHAIN_C },
23
+ ];
24
+
25
+ function createMetaForMockData(
26
+ tokens: Token[]
27
+ ): MatchTokensFromConfigWithMetaParam['meta'] {
28
+ const meta: MatchTokensFromConfigWithMetaParam['meta'] = {
29
+ tokensMapByTokenHash: new Map(),
30
+ tokensMapByBlockchainName: {},
31
+ };
32
+ tokens.forEach((token) => {
33
+ const tokenHash = createTokenHash(token);
34
+ meta.tokensMapByTokenHash.set(tokenHash, token);
35
+ if (!meta.tokensMapByBlockchainName[token.blockchain]) {
36
+ meta.tokensMapByBlockchainName[token.blockchain] = [];
37
+ }
38
+ meta.tokensMapByBlockchainName[token.blockchain].push(tokenHash);
39
+ });
40
+
41
+ return meta;
42
+ }
43
+
44
+ describe('matchTokensFromConfigWithMeta', () => {
45
+ test('should include tokens from config.tokens array that exist in meta', () => {
46
+ const mockData: MatchTokensFromConfigWithMetaParam = {
47
+ type: 'source',
48
+ meta: createMetaForMockData(tokens),
49
+ config: {
50
+ blockchains: undefined,
51
+ tokens: [tokens[0], tokens[1]],
52
+ },
53
+ };
54
+
55
+ const result = matchTokensFromConfigWithMeta(mockData);
56
+ expect(result).toEqual([tokens[0], tokens[1]]);
57
+ });
58
+
59
+ test('If config.blockchains is not defined or is empty, we should include all tokens from the meta for every blockchain that does not have tokens specified in the config, as well as tokens specified in the config that exist in the meta.', () => {
60
+ const mockData: MatchTokensFromConfigWithMetaParam = {
61
+ type: 'source',
62
+ meta: createMetaForMockData(tokens),
63
+ config: {
64
+ blockchains: undefined,
65
+ tokens: {
66
+ [BLOCKCHAIN_A]: { tokens: [tokens[0]], isExcluded: false },
67
+ },
68
+ },
69
+ };
70
+
71
+ const runTestWithConfig = (config: {
72
+ blockchains: MatchTokensFromConfigWithMetaParam['config']['blockchains'];
73
+ }) => {
74
+ mockData.config.blockchains = config.blockchains;
75
+ const result = matchTokensFromConfigWithMeta(mockData);
76
+ /**
77
+ * In this case, the result might differ from what was expected.
78
+ * To pass the test, we reordered the expected result.
79
+ * Changing the order of tokens does not impact the overall behavior of our app,
80
+ * as we have a comprehensive sorting logic applied to tokens within the data slice.
81
+ */
82
+ // eslint-disable-next-line @typescript-eslint/no-magic-numbers
83
+ expect(result).toEqual([tokens[2], tokens[3], tokens[0]]);
84
+ };
85
+
86
+ runTestWithConfig({ blockchains: undefined });
87
+ runTestWithConfig({ blockchains: [] });
88
+ });
89
+
90
+ test('should include tokens from config.tokens object that exist in meta', () => {
91
+ const mockData: MatchTokensFromConfigWithMetaParam = {
92
+ type: 'source',
93
+ meta: createMetaForMockData(tokens),
94
+ config: {
95
+ blockchains: [BLOCKCHAIN_A, BLOCKCHAIN_B],
96
+ tokens: {
97
+ [BLOCKCHAIN_A]: { tokens: [tokens[0]], isExcluded: false },
98
+ [BLOCKCHAIN_B]: { tokens: [tokens[2]], isExcluded: false },
99
+ },
100
+ },
101
+ };
102
+
103
+ const result = matchTokensFromConfigWithMeta(mockData);
104
+ expect(result).toEqual([tokens[0], tokens[2]]);
105
+ });
106
+
107
+ test('should not include tokens from config.tokens whose blockchain does not exist in config.blockchains', () => {
108
+ const mockData: MatchTokensFromConfigWithMetaParam = {
109
+ type: 'source',
110
+ meta: createMetaForMockData(tokens),
111
+ config: {
112
+ blockchains: [BLOCKCHAIN_A],
113
+ tokens: {
114
+ [BLOCKCHAIN_B]: { tokens: [tokens[2]], isExcluded: false },
115
+ },
116
+ },
117
+ };
118
+
119
+ const result = matchTokensFromConfigWithMeta(mockData);
120
+ expect(result).toEqual([tokens[0], tokens[1]]);
121
+ });
122
+
123
+ test('should include all tokens from a blockchain if that blockchain does not have any tokens in config.tokens', () => {
124
+ const mockData: MatchTokensFromConfigWithMetaParam = {
125
+ type: 'source',
126
+ meta: createMetaForMockData(tokens),
127
+ config: {
128
+ blockchains: [BLOCKCHAIN_A],
129
+ tokens: {},
130
+ },
131
+ };
132
+
133
+ const result = matchTokensFromConfigWithMeta(mockData);
134
+ expect(result).toEqual([tokens[0], tokens[1]]);
135
+ });
136
+
137
+ test('should include all tokens from config.blockchains that exist in the meta, except tokens excluded in config.token', () => {
138
+ const mockData: MatchTokensFromConfigWithMetaParam = {
139
+ type: 'source',
140
+ meta: createMetaForMockData(tokens),
141
+ config: {
142
+ blockchains: [BLOCKCHAIN_A],
143
+ tokens: {
144
+ [BLOCKCHAIN_A]: { tokens: [tokens[0]], isExcluded: true },
145
+ },
146
+ },
147
+ };
148
+
149
+ const result = matchTokensFromConfigWithMeta(mockData);
150
+ expect(result).toEqual([tokens[1]]);
151
+ });
152
+
153
+ test('should include all tokens from the meta when config parameters are empty values', () => {
154
+ const mockData: MatchTokensFromConfigWithMetaParam = {
155
+ type: 'source',
156
+ meta: createMetaForMockData(tokens),
157
+ config: {
158
+ blockchains: [],
159
+ tokens: {},
160
+ },
161
+ };
162
+
163
+ const runTestWithConfig = (
164
+ config: MatchTokensFromConfigWithMetaParam['config']
165
+ ) => {
166
+ mockData.config = config;
167
+ const result = matchTokensFromConfigWithMeta(mockData);
168
+ expect(result).toEqual(tokens);
169
+ };
170
+
171
+ runTestWithConfig({ blockchains: [], tokens: {} });
172
+ runTestWithConfig({ blockchains: undefined, tokens: undefined });
173
+ runTestWithConfig({ blockchains: [], tokens: [] });
174
+ });
175
+ });
@@ -0,0 +1,117 @@
1
+ import type { BlockchainAndTokenConfig, TokenHash } from '../../types';
2
+ import type { DataSlice } from '../slices/data';
3
+ import type { Asset, Token } from 'rango-sdk';
4
+
5
+ import { createTokenHash } from '../../utils/meta';
6
+
7
+ /**
8
+ * This function retrieves tokens and blockchains from the widget configuration and combines them with token data from the meta response to determine which tokens should be displayed in the widget.
9
+ * To optimize performance, the function minimizes unnecessary iterations over the meta tokens.
10
+ * The result of this function should be cached and recalculated whenever the widget configuration changes.
11
+ */
12
+ export function matchTokensFromConfigWithMeta(params: {
13
+ type: 'source' | 'destination';
14
+ config: {
15
+ blockchains: BlockchainAndTokenConfig['blockchains'];
16
+ tokens: BlockchainAndTokenConfig['tokens'];
17
+ };
18
+ meta: {
19
+ tokensMapByTokenHash: DataSlice['_tokensMapByTokenHash'];
20
+ tokensMapByBlockchainName: DataSlice['_tokensMapByBlockchainName'];
21
+ };
22
+ }): Token[] {
23
+ const { config, meta } = params;
24
+ const result: Record<TokenHash, Token> = {};
25
+ const configTokens = config.tokens;
26
+
27
+ // Helper function to add tokens to result
28
+ const addTokens = (tokens: (Asset | TokenHash)[]) => {
29
+ tokens.forEach((item) => {
30
+ if (typeof item !== 'string') {
31
+ item = createTokenHash(item);
32
+ }
33
+ const tokenFromMeta = meta.tokensMapByTokenHash.get(item);
34
+ if (tokenFromMeta) {
35
+ result[item] = tokenFromMeta;
36
+ }
37
+ });
38
+ };
39
+
40
+ /**
41
+ * We support two types of configurations for passing tokens in the widget config.
42
+ * We check the type of configuration and calculate the result based on that.
43
+ */
44
+ if (Array.isArray(configTokens)) {
45
+ /**
46
+ * If "config.tokens" is an array,
47
+ * we iterate through it and include any token that exists in the meta data in the result.
48
+ */
49
+ if (configTokens.length > 0) {
50
+ addTokens(configTokens);
51
+ return Object.values(result);
52
+ }
53
+ return Array.from(meta.tokensMapByTokenHash.values());
54
+ }
55
+
56
+ /**
57
+ * From this point onward,
58
+ * the function handles the other type of widget configuration.
59
+ */
60
+ if (!configTokens) {
61
+ return Array.from(meta.tokensMapByTokenHash.values());
62
+ }
63
+
64
+ let configBlockchains: string[];
65
+
66
+ if (config.blockchains?.length) {
67
+ configBlockchains = config.blockchains;
68
+ } else {
69
+ /**
70
+ * If config.blockchains does not exist,
71
+ * we include all tokens from every blockchain in the meta data that are not specified in the tokens from the config.
72
+ */
73
+ configBlockchains = Object.keys(configTokens);
74
+ const configBlockchainsSet = new Set(configBlockchains);
75
+
76
+ Object.keys(meta.tokensMapByBlockchainName).forEach((blockchain) => {
77
+ if (!configBlockchainsSet.has(blockchain)) {
78
+ addTokens(meta.tokensMapByBlockchainName[blockchain]);
79
+ }
80
+ });
81
+ }
82
+ //We iterate over each blockchain and retrieve the related tokens for each one from the configuration.
83
+ configBlockchains.forEach((blockchain) => {
84
+ const targetTokensForBlockchain = configTokens[blockchain];
85
+ /**
86
+ * If no tokens exist for a blockchain,
87
+ * we include all tokens for that blockchain from the meta response.
88
+ */
89
+ if (
90
+ !targetTokensForBlockchain &&
91
+ meta.tokensMapByBlockchainName?.[blockchain]
92
+ ) {
93
+ addTokens(meta.tokensMapByBlockchainName[blockchain]);
94
+ return;
95
+ }
96
+
97
+ if (targetTokensForBlockchain) {
98
+ if (targetTokensForBlockchain.isExcluded) {
99
+ /**
100
+ * If tokens are excluded,
101
+ * we first include all tokens from the meta for that blockchain,
102
+ * then remove the excluded tokens from the result.
103
+ */
104
+ addTokens(meta.tokensMapByBlockchainName[blockchain]);
105
+ targetTokensForBlockchain.tokens.forEach((token) => {
106
+ const tokenHash = createTokenHash(token);
107
+ delete result[tokenHash];
108
+ });
109
+ } else {
110
+ //We retrieve the corresponding token from the meta and include it in the result.
111
+ addTokens(targetTokensForBlockchain.tokens);
112
+ }
113
+ }
114
+ });
115
+
116
+ return Object.values(result);
117
+ }
@@ -0,0 +1 @@
1
+ export * from './data';
@@ -1,5 +1,5 @@
1
1
  import type { AppStoreState } from '../store/app';
2
- import type { TokenHash, WidgetConfig } from '../types';
2
+ import type { Blockchain, TokenHash, WidgetConfig } from '../types';
3
3
  import type { BlockchainMeta, EvmBlockchainMeta, Token } from 'rango-sdk';
4
4
 
5
5
  import { faker } from '@faker-js/faker';
@@ -231,13 +231,20 @@ export function createInitialAppStore() {
231
231
  blockchains: blockchains.map((b) => b.name),
232
232
  });
233
233
 
234
+ const tokensMapByTokenHash: Map<TokenHash, Token> = new Map();
235
+ const tokensMapByBlockchainName: Record<Blockchain, TokenHash[]> = {};
236
+ tokens.forEach((token) => {
237
+ const tokenHash = createTokenHash(token);
238
+ if (!tokensMapByBlockchainName[token.blockchain]) {
239
+ tokensMapByBlockchainName[token.blockchain] = [];
240
+ }
241
+ tokensMapByTokenHash.set(tokenHash, token);
242
+ tokensMapByBlockchainName[token.blockchain].push(tokenHash);
243
+ });
244
+
234
245
  return {
235
- _tokensMapByTokenHash: new Map<TokenHash, Token>(
236
- tokens.map((token) => {
237
- const tokenHash = createTokenHash(token);
238
- return [tokenHash, token];
239
- })
240
- ),
246
+ _tokensMapByTokenHash: tokensMapByTokenHash,
247
+ _tokensMapByBlockchainName: tokensMapByBlockchainName,
241
248
  _blockchainsMapByName: new Map<string, BlockchainMeta>(
242
249
  blockchains.map((meta) => [meta.name, meta])
243
250
  ),
@@ -179,6 +179,8 @@ export type TrezorManifest = {
179
179
  * @property {boolean} customDestination - A boolean value indicating whether the user can input a custom
180
180
  * address for the transaction. If set to true, the widget will allow the user to input a custom
181
181
  * address for the destination.
182
+ * @property {{[blockchain: string]: string }} defaultCustomDestinations - The `defaultCustomDestinations` property is a map of supported `blockchain` names to an arbitrary blockchain address.
183
+ * You could use it to set a default custom destination for some blockchains. e.g. {'BSC': '0x2be.....c1','ETH': '0x2be.....c1'}
182
184
  * @property {string} language - The language property is an optional string that specifies the
183
185
  * default language in which the widget should be displayed. If not provided, the widget will default to the
184
186
  * language of the user's browser.
@@ -219,6 +221,7 @@ export type WidgetConfig = {
219
221
  wallets?: (WalletType | ProviderInterface)[];
220
222
  multiWallets?: boolean;
221
223
  customDestination?: boolean;
224
+ defaultCustomDestinations?: { [blockchain: string]: string };
222
225
  language?: Language;
223
226
  theme?: WidgetTheme;
224
227
  externalWallets?: boolean;
@@ -227,7 +230,6 @@ export type WidgetConfig = {
227
230
  variant?: WidgetVariant;
228
231
  enableCentralizedSwappers?: boolean;
229
232
  signers?: SignersConfig;
230
-
231
233
  // These are likely to change or remove at anytime. Please use with a caution.
232
234
  __UNSTABLE_OR_INTERNAL__?: {
233
235
  walletConnectListedDesktopWalletLink?: string;
@@ -7,6 +7,17 @@ import type {
7
7
 
8
8
  import { WidgetEvents as QueueManagerEvents } from '@rango-dev/queue-manager-rango-preset';
9
9
 
10
+ type EventData<
11
+ T extends QuoteEventTypes | WalletEventTypes | UiEventTypes,
12
+ U extends Record<string, unknown> | null
13
+ > = { type: T; payload: U };
14
+
15
+ export type PreventableEventPayload<
16
+ T extends Record<string, unknown> = Record<string, unknown>
17
+ > = {
18
+ preventDefault: () => void;
19
+ } & T;
20
+
10
21
  type Account = Wallet;
11
22
 
12
23
  export enum QuoteEventTypes {
@@ -19,6 +30,14 @@ export enum WalletEventTypes {
19
30
  DISCONNECT = 'disconnect',
20
31
  }
21
32
 
33
+ /**
34
+ * We use a prefix for interaction type and a name for defining the event name: INTERACTION_EVENT_NAME
35
+ * e.g. CLICK_X_BUTTON or NAVIGATE_WALLET_PAGE
36
+ */
37
+ export enum UiEventTypes {
38
+ CLICK_CONNECT_WALLET = 'clickConnectWallet',
39
+ }
40
+
22
41
  export type QuoteInputUpdateEventPayload = {
23
42
  fromBlockchain?: string;
24
43
  toBlockchain?: string;
@@ -41,31 +60,27 @@ export type DisconnectWalletEventPayload = {
41
60
  walletType: string;
42
61
  };
43
62
 
63
+ export type ClickConnectWalletPayload = PreventableEventPayload;
64
+
44
65
  export type QuoteEventData =
45
- | {
46
- type: QuoteEventTypes.QUOTE_INPUT_UPDATE;
47
- payload: QuoteInputUpdateEventPayload;
48
- }
49
- | {
50
- type: QuoteEventTypes.QUOTE_OUTPUT_UPDATE;
51
- payload: QuoteUpdateEventPayload;
52
- };
66
+ | EventData<QuoteEventTypes.QUOTE_INPUT_UPDATE, QuoteInputUpdateEventPayload>
67
+ | EventData<QuoteEventTypes.QUOTE_OUTPUT_UPDATE, QuoteUpdateEventPayload>;
53
68
 
54
69
  export type WalletEventData =
55
- | {
56
- type: WalletEventTypes.CONNECT;
57
- payload: ConnectWalletEventPayload;
58
- }
59
- | {
60
- type: WalletEventTypes.DISCONNECT;
61
- payload: DisconnectWalletEventPayload;
62
- };
70
+ | EventData<WalletEventTypes.CONNECT, ConnectWalletEventPayload>
71
+ | EventData<WalletEventTypes.DISCONNECT, DisconnectWalletEventPayload>;
72
+
73
+ export type UiEventData = EventData<
74
+ UiEventTypes.CLICK_CONNECT_WALLET,
75
+ ClickConnectWalletPayload
76
+ >;
63
77
 
64
78
  export enum WidgetEvents {
65
79
  RouteEvent = QueueManagerEvents.RouteEvent,
66
80
  StepEvent = QueueManagerEvents.StepEvent,
67
81
  QuoteEvent = 'quoteEvent',
68
82
  WalletEvent = 'walletEvent',
83
+ UiEvent = 'uiEvent',
69
84
  }
70
85
 
71
86
  export type Events = {
@@ -73,6 +88,7 @@ export type Events = {
73
88
  [WidgetEvents.StepEvent]: StepEventData;
74
89
  [WidgetEvents.QuoteEvent]: QuoteEventData;
75
90
  [WidgetEvents.WalletEvent]: WalletEventData;
91
+ [WidgetEvents.UiEvent]: UiEventData;
76
92
  };
77
93
 
78
94
  declare type EventHandler<T = unknown> = (event: T) => void;
@@ -6,6 +6,7 @@ import {
6
6
  } from '@rango-dev/queue-manager-rango-preset';
7
7
 
8
8
  type NotificationRoute = {
9
+ creationTime: number;
9
10
  from: {
10
11
  blockchain: Step['fromBlockchain'];
11
12
  symbol: Step['fromSymbol'];
@@ -13,7 +13,7 @@ export type Balance = {
13
13
  usdValue: string;
14
14
  };
15
15
 
16
- type Blockchain = string;
16
+ export type Blockchain = string;
17
17
  type TokenSymbol = string;
18
18
  type Address = string;
19
19
 
@@ -0,0 +1,27 @@
1
+ import { eventEmitter } from '../services/eventEmitter';
2
+ import { type UiEventData, WidgetEvents } from '../types';
3
+
4
+ type UiEvent = {
5
+ type: UiEventData['type'];
6
+ payload?: Omit<UiEventData['payload'], 'preventDefault'>;
7
+ };
8
+
9
+ export function emitPreventableEvent(event: UiEvent, action: () => void): void {
10
+ let defaultPrevented = false;
11
+
12
+ const extendedPayload = {
13
+ preventDefault() {
14
+ defaultPrevented = true;
15
+ },
16
+ ...(event.payload === undefined && { payload: event.payload }),
17
+ };
18
+
19
+ eventEmitter.emit(WidgetEvents.UiEvent, {
20
+ type: event.type,
21
+ payload: extendedPayload,
22
+ });
23
+
24
+ if (!defaultPrevented) {
25
+ action();
26
+ }
27
+ }
package/src/utils/swap.ts CHANGED
@@ -722,7 +722,7 @@ export function shouldRetrySwap(pendingSwap: PendingSwap) {
722
722
 
723
723
  export function isConfirmSwapDisabled(
724
724
  fetching: boolean,
725
- showCustomDestination: boolean,
725
+ isCustomDestinationOpen: boolean,
726
726
  customDestination: string | null,
727
727
  quote: SelectedQuote | null,
728
728
  selectedWallets: { walletType: string; chain: string }[],
@@ -752,9 +752,9 @@ export function isConfirmSwapDisabled(
752
752
  : false;
753
753
 
754
754
  return (
755
- (!showCustomDestination && !everyWalletSelected) ||
756
- (showCustomDestination && !customDestination) ||
757
- (showCustomDestination &&
755
+ (!isCustomDestinationOpen && !everyWalletSelected) ||
756
+ (isCustomDestinationOpen && !customDestination) ||
757
+ (isCustomDestinationOpen &&
758
758
  !!customDestination &&
759
759
  (!customDestinationIsValid || !everyRequiredWalletSelected))
760
760
  );