@rango-dev/widget-embedded 0.21.1-next.0 → 0.21.1-next.10

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 (138) hide show
  1. package/dist/components/ConfirmWalletsModal/ConfirmWallets.styles.d.ts +1 -1
  2. package/dist/components/ConfirmWalletsModal/ConfirmWalletsModal.d.ts.map +1 -1
  3. package/dist/components/ConfirmWalletsModal/WalletList.d.ts.map +1 -1
  4. package/dist/components/CustomCollapsible/CustomCollapsible.d.ts.map +1 -1
  5. package/dist/components/HeaderButtons/HomeButtons.d.ts.map +1 -1
  6. package/dist/components/HistoryGroupedList/HistoryGroupedList.d.ts +4 -0
  7. package/dist/components/HistoryGroupedList/HistoryGroupedList.d.ts.map +1 -0
  8. package/dist/components/HistoryGroupedList/HistoryGroupedList.helpers.d.ts +2 -0
  9. package/dist/components/HistoryGroupedList/HistoryGroupedList.helpers.d.ts.map +1 -0
  10. package/dist/components/{SwapsGroup/SwapsGroup.styles.d.ts → HistoryGroupedList/HistoryGroupedList.styles.d.ts} +162 -1
  11. package/dist/components/HistoryGroupedList/HistoryGroupedList.styles.d.ts.map +1 -0
  12. package/dist/components/{SwapsGroup/SwapsGroup.types.d.ts → HistoryGroupedList/HistoryGroupedList.types.d.ts} +5 -4
  13. package/dist/components/HistoryGroupedList/HistoryGroupedList.types.d.ts.map +1 -0
  14. package/dist/components/HistoryGroupedList/index.d.ts +2 -0
  15. package/dist/components/HistoryGroupedList/index.d.ts.map +1 -0
  16. package/dist/components/Layout/Layout.d.ts.map +1 -1
  17. package/dist/components/Layout/Layout.styles.d.ts.map +1 -1
  18. package/dist/components/Layout/Layout.types.d.ts +0 -1
  19. package/dist/components/Layout/Layout.types.d.ts.map +1 -1
  20. package/dist/components/NotificationContent/NotificationContent.d.ts.map +1 -1
  21. package/dist/components/NotificationContent/NotificationContent.styles.d.ts.map +1 -1
  22. package/dist/components/Quote/Quote.d.ts.map +1 -1
  23. package/dist/components/Quote/QuoteCostDetails.d.ts.map +1 -1
  24. package/dist/components/QuoteWarningsAndErrors/HighValueLossWarningModal.d.ts.map +1 -1
  25. package/dist/components/QuoteWarningsAndErrors/SlippageWariningModal.d.ts.map +1 -1
  26. package/dist/components/QuoteWarningsAndErrors/UnknownPriceWarningModal.d.ts.map +1 -1
  27. package/dist/components/SwapDetailsModal/SwapDetailsCompleteModal.d.ts.map +1 -1
  28. package/dist/components/SwapDetailsModal/SwapDetailsModal.WalletState.d.ts.map +1 -1
  29. package/dist/components/SwapDetailsModal/SwapDetailsModal.d.ts.map +1 -1
  30. package/dist/components/TokenList/TokenList.d.ts.map +1 -1
  31. package/dist/components/WalletModal/WalletModal.d.ts.map +1 -1
  32. package/dist/components/common/ActivateTabModal/ActivateTabModal.d.ts.map +1 -1
  33. package/dist/components/common/WatermarkedModal/WatermarkedModal.d.ts +5 -0
  34. package/dist/components/common/WatermarkedModal/WatermarkedModal.d.ts.map +1 -0
  35. package/dist/components/common/WatermarkedModal/index.d.ts +2 -0
  36. package/dist/components/common/WatermarkedModal/index.d.ts.map +1 -0
  37. package/dist/constants/index.d.ts +7 -1
  38. package/dist/constants/index.d.ts.map +1 -1
  39. package/dist/constants/searchParams.d.ts +2 -1
  40. package/dist/constants/searchParams.d.ts.map +1 -1
  41. package/dist/containers/App/App.d.ts.map +1 -1
  42. package/dist/hooks/useFetchApiConfig.d.ts +7 -0
  43. package/dist/hooks/useFetchApiConfig.d.ts.map +1 -0
  44. package/dist/hooks/useIframe/index.d.ts +2 -0
  45. package/dist/hooks/useIframe/index.d.ts.map +1 -0
  46. package/dist/hooks/useIframe/useIframe.d.ts +9 -0
  47. package/dist/hooks/useIframe/useIframe.d.ts.map +1 -0
  48. package/dist/hooks/useIframe/useIframe.helpers.d.ts +2 -0
  49. package/dist/hooks/useIframe/useIframe.helpers.d.ts.map +1 -0
  50. package/dist/hooks/useIframe/useIframe.types.d.ts +10 -0
  51. package/dist/hooks/useIframe/useIframe.types.d.ts.map +1 -0
  52. package/dist/hooks/useSyncUrlAndStore/useSyncUrlAndStore.d.ts.map +1 -1
  53. package/dist/hooks/useWalletList.d.ts +1 -0
  54. package/dist/hooks/useWalletList.d.ts.map +1 -1
  55. package/dist/index.d.ts +2 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +2 -2
  58. package/dist/index.js.map +4 -4
  59. package/dist/pages/Home.d.ts.map +1 -1
  60. package/dist/pages/WalletsPage.d.ts.map +1 -1
  61. package/dist/store/slices/config.d.ts +8 -0
  62. package/dist/store/slices/config.d.ts.map +1 -1
  63. package/dist/store/ui.d.ts +5 -0
  64. package/dist/store/ui.d.ts.map +1 -1
  65. package/dist/types/config.d.ts +1 -0
  66. package/dist/types/config.d.ts.map +1 -1
  67. package/dist/types/notification.d.ts +4 -4
  68. package/dist/types/notification.d.ts.map +1 -1
  69. package/dist/utils/common.d.ts.map +1 -1
  70. package/dist/utils/date.d.ts +1 -1
  71. package/dist/utils/date.d.ts.map +1 -1
  72. package/dist/utils/wallets.d.ts +2 -1
  73. package/dist/utils/wallets.d.ts.map +1 -1
  74. package/package.json +2 -2
  75. package/readme.md +1 -0
  76. package/src/components/ConfirmWalletsModal/ConfirmWalletsModal.tsx +9 -7
  77. package/src/components/ConfirmWalletsModal/WalletList.tsx +35 -27
  78. package/src/components/CustomCollapsible/CustomCollapsible.tsx +1 -10
  79. package/src/components/HeaderButtons/HomeButtons.tsx +2 -1
  80. package/src/components/HistoryGroupedList/HistoryGroupedList.helpers.ts +17 -0
  81. package/src/components/{SwapsGroup/SwapsGroup.styles.ts → HistoryGroupedList/HistoryGroupedList.styles.ts} +9 -0
  82. package/src/components/HistoryGroupedList/HistoryGroupedList.tsx +162 -0
  83. package/src/components/{SwapsGroup/SwapsGroup.types.ts → HistoryGroupedList/HistoryGroupedList.types.ts} +4 -3
  84. package/src/components/HistoryGroupedList/index.ts +1 -0
  85. package/src/components/Layout/Layout.styles.ts +12 -6
  86. package/src/components/Layout/Layout.tsx +47 -22
  87. package/src/components/Layout/Layout.types.ts +0 -1
  88. package/src/components/NotificationContent/NotificationContent.styles.ts +1 -0
  89. package/src/components/NotificationContent/NotificationContent.tsx +13 -22
  90. package/src/components/NotificationContent/NotificationNotFound.tsx +1 -1
  91. package/src/components/Quote/Quote.tsx +2 -12
  92. package/src/components/Quote/QuoteCostDetails.tsx +3 -3
  93. package/src/components/QuoteWarningsAndErrors/HighValueLossWarningModal.tsx +4 -3
  94. package/src/components/QuoteWarningsAndErrors/SlippageWariningModal.tsx +5 -3
  95. package/src/components/QuoteWarningsAndErrors/UnknownPriceWarningModal.tsx +4 -4
  96. package/src/components/SwapDetailsModal/SwapDetailsCompleteModal.tsx +7 -5
  97. package/src/components/SwapDetailsModal/SwapDetailsModal.WalletState.tsx +29 -3
  98. package/src/components/SwapDetailsModal/SwapDetailsModal.tsx +7 -5
  99. package/src/components/TokenList/TokenList.tsx +4 -24
  100. package/src/components/WalletModal/WalletModal.tsx +8 -5
  101. package/src/components/common/ActivateTabModal/ActivateTabModal.tsx +9 -3
  102. package/src/components/common/WatermarkedModal/WatermarkedModal.tsx +18 -0
  103. package/src/components/common/WatermarkedModal/index.ts +1 -0
  104. package/src/constants/index.ts +7 -1
  105. package/src/constants/searchParams.ts +2 -0
  106. package/src/containers/App/App.tsx +3 -1
  107. package/src/hooks/useFetchApiConfig.ts +33 -0
  108. package/src/hooks/useIframe/index.ts +1 -0
  109. package/src/hooks/useIframe/useIframe.helpers.ts +3 -0
  110. package/src/hooks/useIframe/useIframe.ts +55 -0
  111. package/src/hooks/useIframe/useIframe.types.ts +13 -0
  112. package/src/hooks/useSwapInput.ts +2 -2
  113. package/src/hooks/useSyncStoresWithConfig.ts +3 -3
  114. package/src/hooks/useSyncUrlAndStore/useSyncUrlAndStore.ts +11 -1
  115. package/src/hooks/useWalletList.ts +20 -4
  116. package/src/index.ts +2 -0
  117. package/src/pages/HistoryPage.tsx +6 -6
  118. package/src/pages/Home.tsx +2 -3
  119. package/src/pages/WalletsPage.tsx +24 -18
  120. package/src/store/notification.ts +4 -4
  121. package/src/store/slices/config.ts +29 -1
  122. package/src/store/slices/data.ts +2 -2
  123. package/src/store/ui.ts +8 -0
  124. package/src/types/config.ts +1 -0
  125. package/src/types/notification.ts +4 -4
  126. package/src/utils/common.ts +2 -2
  127. package/src/utils/configs.ts +3 -3
  128. package/src/utils/date.ts +9 -2
  129. package/src/utils/meta.ts +2 -2
  130. package/src/utils/wallets.ts +5 -1
  131. package/dist/components/SwapsGroup/SwapsGroup.d.ts +0 -4
  132. package/dist/components/SwapsGroup/SwapsGroup.d.ts.map +0 -1
  133. package/dist/components/SwapsGroup/SwapsGroup.styles.d.ts.map +0 -1
  134. package/dist/components/SwapsGroup/SwapsGroup.types.d.ts.map +0 -1
  135. package/dist/components/SwapsGroup/index.d.ts +0 -2
  136. package/dist/components/SwapsGroup/index.d.ts.map +0 -1
  137. package/src/components/SwapsGroup/SwapsGroup.tsx +0 -141
  138. package/src/components/SwapsGroup/index.ts +0 -1
@@ -1,9 +1,10 @@
1
1
  import type { PropTypes } from './WalletModal.types';
2
2
 
3
- import { Divider, Modal } from '@rango-dev/ui';
3
+ import { Divider } from '@rango-dev/ui';
4
4
  import React from 'react';
5
5
 
6
- import { RANGO_SWAP_BOX_ID } from '../../constants';
6
+ import { WIDGET_UI_ID } from '../../constants';
7
+ import { WatermarkedModal } from '../common/WatermarkedModal';
7
8
 
8
9
  import { ModalContent } from './WalletModalContent';
9
10
 
@@ -11,12 +12,14 @@ export function WalletModal(props: PropTypes) {
11
12
  const { open, onClose, ...otherProps } = props;
12
13
 
13
14
  return (
14
- <Modal
15
+ <WatermarkedModal
15
16
  open={open}
16
17
  onClose={onClose}
17
- container={document.getElementById(RANGO_SWAP_BOX_ID) || document.body}>
18
+ container={
19
+ document.getElementById(WIDGET_UI_ID.SWAP_BOX_ID) || document.body
20
+ }>
18
21
  <ModalContent {...otherProps} />
19
22
  <Divider direction="vertical" size={32} />
20
- </Modal>
23
+ </WatermarkedModal>
21
24
  );
22
25
  }
@@ -1,15 +1,21 @@
1
1
  import type { PropTypes } from './ActivateTabModal.types';
2
2
 
3
3
  import { i18n } from '@lingui/core';
4
- import { Button, Divider, MessageBox, Modal } from '@rango-dev/ui';
4
+ import { Button, Divider, MessageBox } from '@rango-dev/ui';
5
5
  import React from 'react';
6
6
 
7
7
  import { getContainer } from '../../../utils/common';
8
+ import { WatermarkedModal } from '../WatermarkedModal';
8
9
 
9
10
  export function ActivateTabModal(props: PropTypes) {
10
11
  const { open, onClose, onConfirm } = props;
12
+
11
13
  return (
12
- <Modal open={open} dismissible onClose={onClose} container={getContainer()}>
14
+ <WatermarkedModal
15
+ open={open}
16
+ dismissible
17
+ onClose={onClose}
18
+ container={getContainer()}>
13
19
  <MessageBox
14
20
  title={i18n.t('Activate current tab')}
15
21
  type="warning"
@@ -26,6 +32,6 @@ export function ActivateTabModal(props: PropTypes) {
26
32
  {i18n.t('Confirm')}
27
33
  </Button>
28
34
  </MessageBox>
29
- </Modal>
35
+ </WatermarkedModal>
30
36
  );
31
37
  }
@@ -0,0 +1,18 @@
1
+ import type { ModalPropTypes } from '@rango-dev/ui';
2
+ import type { PropsWithChildren } from 'react';
3
+
4
+ import { Modal } from '@rango-dev/ui';
5
+ import React from 'react';
6
+
7
+ import { useUiStore } from '../../../store/ui';
8
+
9
+ export function WatermarkedModal(props: PropsWithChildren<ModalPropTypes>) {
10
+ const { watermark } = useUiStore();
11
+
12
+ const hasWatermark = watermark === 'FULL';
13
+ return (
14
+ <Modal hasWatermark={hasWatermark} {...props}>
15
+ {props.children}
16
+ </Modal>
17
+ );
18
+ }
@@ -0,0 +1 @@
1
+ export { WatermarkedModal } from './WatermarkedModal';
@@ -1,4 +1,10 @@
1
+ import { UI_ID } from '@rango-dev/ui';
2
+
1
3
  export const RANGO_PUBLIC_API_KEY = 'c6381a79-2817-4602-83bf-6a641a409e32';
2
4
  export const DEFAULT_BASE_URL = 'https://api.rango.exchange';
3
- export const RANGO_SWAP_BOX_ID = 'rango-swap-box';
4
5
  export const SCANNER_BASE_URL = 'https://scan.rango.exchange';
6
+
7
+ export const WIDGET_UI_ID = {
8
+ SWAP_BOX_ID: 'rango-swap-box',
9
+ ...UI_ID,
10
+ };
@@ -5,4 +5,6 @@ export enum SearchParams {
5
5
  TO_TOKEN = 'toToken',
6
6
  FROM_AMOUNT = 'fromAmount',
7
7
  AUTO_CONNECT = 'autoConnect',
8
+ // iframe environments
9
+ CLIENT_URL = 'clientUrl',
8
10
  }
@@ -7,6 +7,7 @@ import { AppRouter } from '../../components/AppRouter';
7
7
  import { AppRoutes } from '../../components/AppRoutes';
8
8
  import { WidgetEvents } from '../../components/WidgetEvents';
9
9
  import { globalFont } from '../../globalStyles';
10
+ import { useFetchApiConfig } from '../../hooks/useFetchApiConfig';
10
11
  import { useLanguage } from '../../hooks/useLanguage';
11
12
  import { useTheme } from '../../hooks/useTheme';
12
13
  import { useAppStore } from '../../store/AppStore';
@@ -25,10 +26,11 @@ export function Main() {
25
26
  useState<string>('');
26
27
  const [disconnectedWallet, setDisconnectedWallet] = useState<WalletType>();
27
28
  const widgetContext = useContext(WidgetContext);
28
-
29
+ const { fetchApiConfig } = useFetchApiConfig();
29
30
  useEffect(() => {
30
31
  void useNotificationStore.persist.rehydrate();
31
32
  widgetContext.onConnectWallet(setLastConnectedWalletWithNetwork);
33
+ void fetchApiConfig().catch(console.log);
32
34
  }, []);
33
35
 
34
36
  return (
@@ -0,0 +1,33 @@
1
+ import { useUiStore } from '../store/ui';
2
+ import { getConfig } from '../utils/configs';
3
+
4
+ export type Watermark = 'NONE' | 'FULL';
5
+
6
+ type ConfigResponse = {
7
+ config: {
8
+ watermark: Watermark;
9
+ };
10
+ };
11
+
12
+ interface UseFetchApiConfig {
13
+ fetchApiConfig: () => Promise<void>;
14
+ }
15
+
16
+ export function useFetchApiConfig(): UseFetchApiConfig {
17
+ const { setWatermark } = useUiStore();
18
+
19
+ const fetchApiConfig: UseFetchApiConfig['fetchApiConfig'] = async () => {
20
+ const response = await fetch(
21
+ `${getConfig('BASE_URL')}/meta/dapp/config?apiKey=${getConfig('API_KEY')}`
22
+ );
23
+
24
+ if (!response.ok) {
25
+ throw new Error(`Request failed with status: ${response.status} `);
26
+ }
27
+
28
+ const data: ConfigResponse = await response.json();
29
+
30
+ setWatermark(data.config.watermark);
31
+ };
32
+ return { fetchApiConfig };
33
+ }
@@ -0,0 +1 @@
1
+ export { useIframe } from './useIframe';
@@ -0,0 +1,3 @@
1
+ export function isAppLoadedIntoIframe() {
2
+ return window.self !== window.top;
3
+ }
@@ -0,0 +1,55 @@
1
+ import type { Messages } from './useIframe.types';
2
+
3
+ import { useRef } from 'react';
4
+
5
+ import { useAppStore } from '../../store/AppStore';
6
+
7
+ import { isAppLoadedIntoIframe } from './useIframe.helpers';
8
+
9
+ interface UseIframe {
10
+ send: (message: Messages) => void;
11
+ connectHeightObserver: (element: HTMLElement) => void;
12
+ disconnectHeightObserver: () => void;
13
+ }
14
+
15
+ function useIframe(): UseIframe {
16
+ const heightObserver = useRef<ResizeObserver | null>(null);
17
+ const { iframe } = useAppStore();
18
+ const isMessagePassingAvailable = isAppLoadedIntoIframe() && iframe.clientUrl;
19
+
20
+ const send = (message: Messages) => {
21
+ if (isMessagePassingAvailable) {
22
+ window.top?.postMessage(message, iframe.clientUrl!);
23
+ }
24
+ };
25
+
26
+ const connectHeightObserver = (element: HTMLElement) => {
27
+ heightObserver.current = new ResizeObserver((entries) => {
28
+ for (const entry of entries) {
29
+ send({
30
+ type: 'widget_height',
31
+ data: {
32
+ height: entry.contentRect.height,
33
+ },
34
+ });
35
+ }
36
+ });
37
+
38
+ heightObserver.current.observe(element);
39
+ };
40
+
41
+ const disconnectHeightObserver = () => {
42
+ if (heightObserver.current) {
43
+ heightObserver.current.disconnect();
44
+ heightObserver.current = null;
45
+ }
46
+ };
47
+
48
+ return {
49
+ send,
50
+ connectHeightObserver,
51
+ disconnectHeightObserver,
52
+ };
53
+ }
54
+
55
+ export { useIframe };
@@ -0,0 +1,13 @@
1
+ type Message<T, D> = {
2
+ type: T;
3
+ data: D;
4
+ };
5
+ type WidgetHeightMessage = Message<
6
+ 'widget_height',
7
+ {
8
+ height: number;
9
+ }
10
+ >;
11
+
12
+ // Add new types of messages to this union.
13
+ export type Messages = WidgetHeightMessage;
@@ -11,7 +11,7 @@ import { isPositiveNumber } from '../utils/numbers';
11
11
  import { generateQuoteWarnings } from '../utils/quote';
12
12
  import { isFeatureEnabled } from '../utils/settings';
13
13
  import { createQuoteRequestBody } from '../utils/swap';
14
- import { tokensAreEqual } from '../utils/wallets';
14
+ import { areTokensEqual } from '../utils/wallets';
15
15
 
16
16
  import {
17
17
  handleQuoteErrors,
@@ -68,7 +68,7 @@ export function useSwapInput(): UseSwapInput {
68
68
  const tokensValueInvalid = !fromToken || !toToken;
69
69
  const shouldSkipRequest =
70
70
  tokensValueInvalid ||
71
- tokensAreEqual(fromToken, toToken) ||
71
+ areTokensEqual(fromToken, toToken) ||
72
72
  !isPositiveNumber(inputAmount);
73
73
 
74
74
  const resetState = (loading: boolean) => {
@@ -8,7 +8,7 @@ import {
8
8
  isBlockchainExcludedInConfig,
9
9
  isTokenExcludedInConfig,
10
10
  } from '../utils/configs';
11
- import { tokensAreEqual } from '../utils/wallets';
11
+ import { areTokensEqual } from '../utils/wallets';
12
12
 
13
13
  export function useSyncStoresWithConfig() {
14
14
  const {
@@ -50,7 +50,7 @@ export function useSyncStoresWithConfig() {
50
50
  (chain) => chain.name === config?.from?.blockchain
51
51
  );
52
52
  const token = tokens.find((t) =>
53
- tokensAreEqual(t, config?.from?.token || null)
53
+ areTokensEqual(t, config?.from?.token || null)
54
54
  );
55
55
 
56
56
  if (chain || (!chain && prevConfigFromBlockchain.current)) {
@@ -99,7 +99,7 @@ export function useSyncStoresWithConfig() {
99
99
  (chain) => chain.name === config?.to?.blockchain
100
100
  );
101
101
  const token = tokens.find((t) =>
102
- tokensAreEqual(t, config?.to?.token || null)
102
+ areTokensEqual(t, config?.to?.token || null)
103
103
  );
104
104
 
105
105
  if (chain || (!chain && prevConfigToBlockchain.current)) {
@@ -33,6 +33,7 @@ export function useSyncUrlAndStore() {
33
33
  const blockchains = useAppStore().blockchains();
34
34
  const tokens = useAppStore().tokens();
35
35
  const isInRouterContext = useInRouterContext();
36
+ const { updateIframe } = useAppStore();
36
37
 
37
38
  const getUrlSearchParams = () => {
38
39
  const fromAmount = searchParams.get(SearchParams.FROM_AMOUNT);
@@ -41,6 +42,7 @@ export function useSyncUrlAndStore() {
41
42
  const toBlockchain = searchParams.get(SearchParams.TO_BLOCKCHAIN);
42
43
  const toToken = searchParams.get(SearchParams.TO_TOKEN);
43
44
  const autoConnect = searchParams.get(SearchParams.AUTO_CONNECT);
45
+ const clientUrl = searchParams.get(SearchParams.CLIENT_URL);
44
46
 
45
47
  return {
46
48
  fromAmount,
@@ -49,6 +51,7 @@ export function useSyncUrlAndStore() {
49
51
  toBlockchain,
50
52
  toToken,
51
53
  autoConnect,
54
+ clientUrl,
52
55
  };
53
56
  };
54
57
 
@@ -64,7 +67,7 @@ export function useSyncUrlAndStore() {
64
67
  };
65
68
 
66
69
  useEffect(() => {
67
- const { autoConnect } = getUrlSearchParams();
70
+ const { autoConnect, clientUrl } = getUrlSearchParams();
68
71
  if (isInRouterContext && fetchMetaStatus === 'success') {
69
72
  updateUrlSearchParams({
70
73
  [SearchParams.FROM_BLOCKCHAIN]: fromBlockchain?.name,
@@ -73,6 +76,7 @@ export function useSyncUrlAndStore() {
73
76
  [SearchParams.TO_TOKEN]: tokenToSearchParam(toToken),
74
77
  [SearchParams.FROM_AMOUNT]: inputAmount,
75
78
  [SearchParams.AUTO_CONNECT]: autoConnect ?? undefined,
79
+ [SearchParams.CLIENT_URL]: clientUrl ?? undefined,
76
80
  });
77
81
  }
78
82
  }, [
@@ -132,4 +136,10 @@ export function useSyncUrlAndStore() {
132
136
  }
133
137
  }
134
138
  }, [fetchMetaStatus]);
139
+
140
+ // We run this only once, because if the app is embedded into an iframe, the data in url for iframe will not change.
141
+ useEffect(() => {
142
+ const { clientUrl } = getUrlSearchParams();
143
+ updateIframe('clientUrl', clientUrl || undefined);
144
+ }, []);
135
145
  }
@@ -9,12 +9,13 @@ import {
9
9
  type WalletType,
10
10
  WalletTypes,
11
11
  } from '@rango-dev/wallets-shared';
12
- import { useEffect, useState } from 'react';
12
+ import { useCallback, useEffect, useRef, useState } from 'react';
13
13
 
14
14
  import { useAppStore } from '../store/AppStore';
15
15
  import { useWalletsStore } from '../store/wallets';
16
16
  import { configWalletsToWalletName } from '../utils/providers';
17
17
  import {
18
+ hashWalletsState,
18
19
  isExperimentalChain,
19
20
  mapWalletTypesToWalletInfo,
20
21
  sortWalletsBasedOnConnectionState,
@@ -39,6 +40,7 @@ export function useWalletList(params: Params) {
39
40
  const { state, disconnect, getWalletInfo, connect } = useWallets();
40
41
  const { connectedWallets } = useWalletsStore();
41
42
  const blockchains = useAppStore().blockchains();
43
+ const componentWillUnmount = useRef(false);
42
44
 
43
45
  /** It can be what has been set by widget config or as a fallback we use all the supported wallets by our library */
44
46
  const listAvailableWalletTypes =
@@ -87,21 +89,34 @@ export function useWalletList(params: Params) {
87
89
  }
88
90
  };
89
91
 
90
- const disconnectConnectingWallets = () => {
92
+ const disconnectConnectingWallets = useCallback(() => {
91
93
  const connectingWallets =
92
94
  wallets?.filter((wallet) => wallet.state === WalletState.CONNECTING) ||
93
95
  [];
94
96
  for (const wallet of connectingWallets) {
95
97
  void disconnect(wallet.type);
96
98
  }
97
- };
99
+ }, [hashWalletsState(wallets)]);
98
100
 
101
+ /*
102
+ * The order of useEffects is crucial.
103
+ * 1- The first useEffect for componentWillUnmount sets its value to true
104
+ */
99
105
  useEffect(() => {
100
106
  return () => {
101
- disconnectConnectingWallets();
107
+ componentWillUnmount.current = true;
102
108
  };
103
109
  }, []);
104
110
 
111
+ // 2- The second useEffect checks if componentWillUnmount is true then it disconnects connecting wallets
112
+ useEffect(() => {
113
+ return () => {
114
+ if (componentWillUnmount.current) {
115
+ disconnectConnectingWallets();
116
+ }
117
+ };
118
+ }, [disconnectConnectingWallets]);
119
+
105
120
  /*
106
121
  * Atm, we only support default injected wallet for the EVM
107
122
  * so we show default wallet when there is no other evm wallet installed
@@ -141,5 +156,6 @@ export function useWalletList(params: Params) {
141
156
  ),
142
157
  error,
143
158
  handleClick,
159
+ disconnectConnectingWallets,
144
160
  };
145
161
  }
package/src/index.ts CHANGED
@@ -55,6 +55,7 @@ import {
55
55
  import { Networks, WalletTypes } from '@rango-dev/wallets-shared';
56
56
  import { PendingSwapNetworkStatus } from 'rango-types';
57
57
 
58
+ import { WIDGET_UI_ID as UI_ID } from './constants';
58
59
  import { WidgetWallets } from './containers/Wallets';
59
60
  import { Widget } from './containers/Widget';
60
61
  import { useWidget } from './containers/WidgetInfo';
@@ -105,6 +106,7 @@ export {
105
106
  StepEventType,
106
107
  StepExecutionEventStatus,
107
108
  StepExecutionBlockedEventStatus,
109
+ UI_ID,
108
110
  };
109
111
 
110
112
  // Internal type exports for Rango
@@ -6,15 +6,15 @@ import { Divider, NotFound, styled } from '@rango-dev/ui';
6
6
  import React, { useState } from 'react';
7
7
  import { useNavigate } from 'react-router-dom';
8
8
 
9
+ import { HistoryGroupedList } from '../components/HistoryGroupedList';
10
+ import { NotFoundContainer } from '../components/HistoryGroupedList/HistoryGroupedList.styles';
9
11
  import { Layout, PageContainer } from '../components/Layout';
10
12
  import { SearchInput } from '../components/SearchInput';
11
- import { SwapsGroup } from '../components/SwapsGroup';
12
- import { NotFoundContainer } from '../components/SwapsGroup/SwapsGroup.styles';
13
13
  import { groupSwapsByDate } from '../utils/date';
14
14
  import { containsText } from '../utils/numbers';
15
15
  import { getPendingSwaps } from '../utils/queue';
16
16
 
17
- const SwapsGroupContainer = styled('div', {
17
+ const HistoryGroupedListContainer = styled('div', {
18
18
  overflowY: 'visible',
19
19
  width: '100%',
20
20
  display: 'flex',
@@ -77,7 +77,7 @@ export function HistoryPage() {
77
77
  value={searchedFor}
78
78
  />
79
79
  <Divider size="16" />
80
- <SwapsGroupContainer>
80
+ <HistoryGroupedListContainer>
81
81
  {isEmpty && (
82
82
  <NotFoundContainer>
83
83
  <Divider size={32} />
@@ -90,14 +90,14 @@ export function HistoryPage() {
90
90
  </NotFoundContainer>
91
91
  )}
92
92
  {!isEmpty && (
93
- <SwapsGroup
93
+ <HistoryGroupedList
94
94
  list={filteredList}
95
95
  onSwapClick={navigate}
96
96
  groupBy={groupSwapsByDate}
97
97
  isLoading={loading}
98
98
  />
99
99
  )}
100
- </SwapsGroupContainer>
100
+ </HistoryGroupedListContainer>
101
101
  </PageContainer>
102
102
  </Layout>
103
103
  );
@@ -62,7 +62,7 @@ export function Home() {
62
62
  setQuoteWarningsConfirmed,
63
63
  } = useQuoteStore();
64
64
 
65
- const fetchMetaStatus = useAppStore().fetchStatus;
65
+ const { config, fetchStatus: fetchMetaStatus } = useAppStore();
66
66
 
67
67
  const { connectedWallets, getBalanceFor } = useWalletsStore();
68
68
  const { isActiveTab } = useUiStore();
@@ -125,7 +125,6 @@ export function Home() {
125
125
  return (
126
126
  <Layout
127
127
  height="auto"
128
- hasLogo
129
128
  footer={
130
129
  <Button
131
130
  type="primary"
@@ -152,7 +151,7 @@ export function Home() {
152
151
  navigate(navigationRoutes.wallets);
153
152
  },
154
153
  hasBackButton: false,
155
- title: i18n.t('Swap'),
154
+ title: config.title || i18n.t('Swap'),
156
155
  suffix: (
157
156
  <HomeButtons
158
157
  onClickRefresh={
@@ -35,23 +35,29 @@ export function WalletsPage() {
35
35
  let modalTimerId: ReturnType<typeof setTimeout> | null = null;
36
36
  const isActiveTab = useUiStore.use.isActiveTab();
37
37
 
38
- const { list, handleClick, error } = useWalletList({
39
- config,
40
- onBeforeConnect: (type) => {
41
- modalTimerId = setTimeout(() => {
42
- setOpenModal(true);
43
- setSelectedWalletType(type);
44
- }, TIME_TO_IGNORE_MODAL);
45
- },
46
- onConnect: () => {
47
- if (modalTimerId) {
48
- clearTimeout(modalTimerId);
49
- }
50
- setTimeout(() => {
51
- setOpenModal(false);
52
- }, TIME_TO_CLOSE_MODAL);
53
- },
54
- });
38
+ const { list, handleClick, error, disconnectConnectingWallets } =
39
+ useWalletList({
40
+ config,
41
+ onBeforeConnect: (type) => {
42
+ modalTimerId = setTimeout(() => {
43
+ setOpenModal(true);
44
+ setSelectedWalletType(type);
45
+ }, TIME_TO_IGNORE_MODAL);
46
+ },
47
+ onConnect: () => {
48
+ if (modalTimerId) {
49
+ clearTimeout(modalTimerId);
50
+ }
51
+ setTimeout(() => {
52
+ setOpenModal(false);
53
+ }, TIME_TO_CLOSE_MODAL);
54
+ },
55
+ });
56
+
57
+ const handleCloseWalletModal = () => {
58
+ disconnectConnectingWallets();
59
+ setOpenModal(false);
60
+ };
55
61
 
56
62
  const selectedWallet = list.find(
57
63
  (wallet) => wallet.type === selectedWalletType
@@ -87,7 +93,7 @@ export function WalletsPage() {
87
93
  })}
88
94
  <WalletModal
89
95
  open={!!openModal}
90
- onClose={() => setOpenModal(false)}
96
+ onClose={handleCloseWalletModal}
91
97
  image={selectedWalletImage}
92
98
  state={selectedWalletState}
93
99
  error={error}
@@ -34,13 +34,13 @@ export const useNotificationStore = createSelectors(
34
34
  route: {
35
35
  from: {
36
36
  blockchain: fromStep.fromBlockchain,
37
- tokenAddress: fromStep.fromSymbolAddress,
38
- tokenSymbol: fromStep.fromSymbol,
37
+ address: fromStep.fromSymbolAddress,
38
+ symbol: fromStep.fromSymbol,
39
39
  },
40
40
  to: {
41
41
  blockchain: toStep.toBlockchain,
42
- tokenSymbol: toStep.toSymbol,
43
- tokenAddress: toStep.toSymbolAddress,
42
+ address: toStep.toSymbolAddress,
43
+ symbol: toStep.toSymbol,
44
44
  },
45
45
  },
46
46
  };
@@ -3,15 +3,31 @@ import type { StateCreatorWithInitialData } from '../app';
3
3
 
4
4
  export const DEFAULT_CONFIG: WidgetConfig = {
5
5
  apiKey: '',
6
+ title: undefined,
6
7
  multiWallets: true,
7
8
  enableNewLiquiditySources: true,
8
9
  customDestination: true,
9
10
  };
10
11
 
12
+ interface IframeConfigs {
13
+ clientUrl?: string;
14
+ }
15
+
16
+ const DEFAULT_IFRAME_CONFIGS: IframeConfigs = {
17
+ clientUrl: undefined,
18
+ };
19
+
11
20
  export type ConfigSlice = {
21
+ // What user can set directly.
12
22
  config: WidgetConfig;
13
-
14
23
  updateConfig: (config: WidgetConfig) => void;
24
+
25
+ // What we are setting based on enviroments.
26
+ iframe: { clientUrl?: string };
27
+ updateIframe: <K extends keyof IframeConfigs>(
28
+ name: K,
29
+ value: IframeConfigs[K]
30
+ ) => void;
15
31
  };
16
32
 
17
33
  export const createConfigSlice: StateCreatorWithInitialData<
@@ -21,6 +37,7 @@ export const createConfigSlice: StateCreatorWithInitialData<
21
37
  > = (initialData, set, get) => {
22
38
  return {
23
39
  config: { ...DEFAULT_CONFIG, ...initialData },
40
+ iframe: DEFAULT_IFRAME_CONFIGS,
24
41
 
25
42
  // Actions
26
43
  updateConfig: (nextConfig: WidgetConfig) => {
@@ -33,5 +50,16 @@ export const createConfigSlice: StateCreatorWithInitialData<
33
50
  },
34
51
  });
35
52
  },
53
+
54
+ updateIframe: (name, value) => {
55
+ const currentIframeConfig = get().iframe;
56
+
57
+ set({
58
+ iframe: {
59
+ ...currentIframeConfig,
60
+ [name]: value,
61
+ },
62
+ });
63
+ },
36
64
  };
37
65
  };
@@ -8,7 +8,7 @@ import { httpService as sdk } from '../../services/httpService';
8
8
  import { containsText } from '../../utils/common';
9
9
  import { isTokenExcludedInConfig } from '../../utils/configs';
10
10
  import { sortLiquiditySourcesByGroupTitle } from '../../utils/settings';
11
- import { tokensAreEqual } from '../../utils/wallets';
11
+ import { areTokensEqual } from '../../utils/wallets';
12
12
 
13
13
  type BlockchainOptions = {
14
14
  type?: 'source' | 'destination';
@@ -163,7 +163,7 @@ export const createDataSlice: StateCreator<
163
163
  ? get().config.from?.pinnedTokens
164
164
  : get().config.to?.pinnedTokens;
165
165
  const pinned = !!pinnedTokens?.some((pinnedToken) =>
166
- tokensAreEqual(pinnedToken, token)
166
+ areTokensEqual(pinnedToken, token)
167
167
  );
168
168
  return pinned;
169
169
  },