@rango-dev/widget-embedded 0.1.10-next.100

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 (204) hide show
  1. package/dist/App.d.ts +9 -0
  2. package/dist/App.d.ts.map +1 -0
  3. package/dist/QueueManager.d.ts +4 -0
  4. package/dist/QueueManager.d.ts.map +1 -0
  5. package/dist/components/AppRouter.d.ts +9 -0
  6. package/dist/components/AppRouter.d.ts.map +1 -0
  7. package/dist/components/AppRoutes.d.ts +8 -0
  8. package/dist/components/AppRoutes.d.ts.map +1 -0
  9. package/dist/components/BottomLogo.d.ts +3 -0
  10. package/dist/components/BottomLogo.d.ts.map +1 -0
  11. package/dist/components/ChangeSlippageButton.d.ts +3 -0
  12. package/dist/components/ChangeSlippageButton.d.ts.map +1 -0
  13. package/dist/components/ConfirmSwapErrors.d.ts +4 -0
  14. package/dist/components/ConfirmSwapErrors.d.ts.map +1 -0
  15. package/dist/components/ConfirmSwapWarnings.d.ts +4 -0
  16. package/dist/components/ConfirmSwapWarnings.d.ts.map +1 -0
  17. package/dist/components/Footer.d.ts +2 -0
  18. package/dist/components/Footer.d.ts.map +1 -0
  19. package/dist/components/Header.d.ts +10 -0
  20. package/dist/components/Header.d.ts.map +1 -0
  21. package/dist/components/HeaderButtons.d.ts +4 -0
  22. package/dist/components/HeaderButtons.d.ts.map +1 -0
  23. package/dist/components/Layout.d.ts +7 -0
  24. package/dist/components/Layout.d.ts.map +1 -0
  25. package/dist/components/RoutesOverview.d.ts +10 -0
  26. package/dist/components/RoutesOverview.d.ts.map +1 -0
  27. package/dist/components/SwitchFromAndTo.d.ts +4 -0
  28. package/dist/components/SwitchFromAndTo.d.ts.map +1 -0
  29. package/dist/components/TokenInfo.d.ts +18 -0
  30. package/dist/components/TokenInfo.d.ts.map +1 -0
  31. package/dist/components/TokenPreview.d.ts +20 -0
  32. package/dist/components/TokenPreview.d.ts.map +1 -0
  33. package/dist/components/UpdateUrl.d.ts +2 -0
  34. package/dist/components/UpdateUrl.d.ts.map +1 -0
  35. package/dist/components/warnings/BalanceWarnings.d.ts +7 -0
  36. package/dist/components/warnings/BalanceWarnings.d.ts.map +1 -0
  37. package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts +7 -0
  38. package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts.map +1 -0
  39. package/dist/components/warnings/HighSlippageWarning.d.ts +7 -0
  40. package/dist/components/warnings/HighSlippageWarning.d.ts.map +1 -0
  41. package/dist/components/warnings/MinRequiredSlippage.d.ts +7 -0
  42. package/dist/components/warnings/MinRequiredSlippage.d.ts.map +1 -0
  43. package/dist/constants/errors.d.ts +4 -0
  44. package/dist/constants/errors.d.ts.map +1 -0
  45. package/dist/constants/navigationRoutes.d.ts +15 -0
  46. package/dist/constants/navigationRoutes.d.ts.map +1 -0
  47. package/dist/constants/numbers.d.ts +3 -0
  48. package/dist/constants/numbers.d.ts.map +1 -0
  49. package/dist/constants/searchParams.d.ts +8 -0
  50. package/dist/constants/searchParams.d.ts.map +1 -0
  51. package/dist/constants/swapSettings.d.ts +6 -0
  52. package/dist/constants/swapSettings.d.ts.map +1 -0
  53. package/dist/globalStyles.d.ts +3 -0
  54. package/dist/globalStyles.d.ts.map +1 -0
  55. package/dist/hooks/useConfirmSwap.d.ts +11 -0
  56. package/dist/hooks/useConfirmSwap.d.ts.map +1 -0
  57. package/dist/hooks/useCopyToClipboard.d.ts +2 -0
  58. package/dist/hooks/useCopyToClipboard.d.ts.map +1 -0
  59. package/dist/hooks/useNavigateBack.d.ts +4 -0
  60. package/dist/hooks/useNavigateBack.d.ts.map +1 -0
  61. package/dist/hooks/usePrevious.d.ts +2 -0
  62. package/dist/hooks/usePrevious.d.ts.map +1 -0
  63. package/dist/hooks/useSelectLanguage.d.ts +5 -0
  64. package/dist/hooks/useSelectLanguage.d.ts.map +1 -0
  65. package/dist/hooks/useTheme.d.ts +8 -0
  66. package/dist/hooks/useTheme.d.ts.map +1 -0
  67. package/dist/i18n.d.ts +3 -0
  68. package/dist/i18n.d.ts.map +1 -0
  69. package/dist/index.d.ts +2 -0
  70. package/dist/index.d.ts.map +1 -0
  71. package/dist/index.js +8 -0
  72. package/dist/lib.d.ts +8 -0
  73. package/dist/lib.d.ts.map +1 -0
  74. package/dist/mockData/pendingSwap.d.ts +2 -0
  75. package/dist/mockData/pendingSwap.d.ts.map +1 -0
  76. package/dist/pages/ConfirmSwapPage.d.ts +3 -0
  77. package/dist/pages/ConfirmSwapPage.d.ts.map +1 -0
  78. package/dist/pages/ConfirmWalletsPage.d.ts +3 -0
  79. package/dist/pages/ConfirmWalletsPage.d.ts.map +1 -0
  80. package/dist/pages/HistoryPage.d.ts +3 -0
  81. package/dist/pages/HistoryPage.d.ts.map +1 -0
  82. package/dist/pages/Home.d.ts +9 -0
  83. package/dist/pages/Home.d.ts.map +1 -0
  84. package/dist/pages/LiquiditySourcesPage.d.ts +8 -0
  85. package/dist/pages/LiquiditySourcesPage.d.ts.map +1 -0
  86. package/dist/pages/SelectChainPage.d.ts +9 -0
  87. package/dist/pages/SelectChainPage.d.ts.map +1 -0
  88. package/dist/pages/SelectTokenPage.d.ts +15 -0
  89. package/dist/pages/SelectTokenPage.d.ts.map +1 -0
  90. package/dist/pages/SettingsPage.d.ts +8 -0
  91. package/dist/pages/SettingsPage.d.ts.map +1 -0
  92. package/dist/pages/SwapDetailsPage.d.ts +3 -0
  93. package/dist/pages/SwapDetailsPage.d.ts.map +1 -0
  94. package/dist/pages/WalletsPage.d.ts +9 -0
  95. package/dist/pages/WalletsPage.d.ts.map +1 -0
  96. package/dist/services/httpService.d.ts +3 -0
  97. package/dist/services/httpService.d.ts.map +1 -0
  98. package/dist/store/bestRoute.d.ts +28 -0
  99. package/dist/store/bestRoute.d.ts.map +1 -0
  100. package/dist/store/meta.d.ts +9 -0
  101. package/dist/store/meta.d.ts.map +1 -0
  102. package/dist/store/selectors.d.ts +11 -0
  103. package/dist/store/selectors.d.ts.map +1 -0
  104. package/dist/store/settings.d.ts +17 -0
  105. package/dist/store/settings.d.ts.map +1 -0
  106. package/dist/store/ui.d.ts +2 -0
  107. package/dist/store/ui.d.ts.map +1 -0
  108. package/dist/store/wallets.d.ts +28 -0
  109. package/dist/store/wallets.d.ts.map +1 -0
  110. package/dist/types/config.d.ts +40 -0
  111. package/dist/types/config.d.ts.map +1 -0
  112. package/dist/types/index.d.ts +4 -0
  113. package/dist/types/index.d.ts.map +1 -0
  114. package/dist/types/routing.d.ts +45 -0
  115. package/dist/types/routing.d.ts.map +1 -0
  116. package/dist/types/swap.d.ts +11 -0
  117. package/dist/types/swap.d.ts.map +1 -0
  118. package/dist/utils/common.d.ts +4 -0
  119. package/dist/utils/common.d.ts.map +1 -0
  120. package/dist/utils/numbers.d.ts +14 -0
  121. package/dist/utils/numbers.d.ts.map +1 -0
  122. package/dist/utils/queue.d.ts +4 -0
  123. package/dist/utils/queue.d.ts.map +1 -0
  124. package/dist/utils/routing.d.ts +18 -0
  125. package/dist/utils/routing.d.ts.map +1 -0
  126. package/dist/utils/swap.d.ts +45 -0
  127. package/dist/utils/swap.d.ts.map +1 -0
  128. package/dist/utils/wallets.d.ts +29 -0
  129. package/dist/utils/wallets.d.ts.map +1 -0
  130. package/dist/widget-embedded.cjs.development.js +3101 -0
  131. package/dist/widget-embedded.cjs.development.js.map +1 -0
  132. package/dist/widget-embedded.cjs.production.min.js +3101 -0
  133. package/dist/widget-embedded.cjs.production.min.js.map +1 -0
  134. package/dist/widget-embedded.esm.js +3092 -0
  135. package/dist/widget-embedded.esm.js.map +1 -0
  136. package/package.json +55 -0
  137. package/readme.md +2 -0
  138. package/src/App.tsx +91 -0
  139. package/src/QueueManager.tsx +94 -0
  140. package/src/app.css +27 -0
  141. package/src/components/AppRouter.tsx +60 -0
  142. package/src/components/AppRoutes.tsx +105 -0
  143. package/src/components/BottomLogo.tsx +47 -0
  144. package/src/components/ChangeSlippageButton.tsx +19 -0
  145. package/src/components/ConfirmSwapErrors.tsx +38 -0
  146. package/src/components/ConfirmSwapWarnings.tsx +35 -0
  147. package/src/components/Footer.tsx +8 -0
  148. package/src/components/Header.tsx +37 -0
  149. package/src/components/HeaderButtons.tsx +47 -0
  150. package/src/components/Layout.tsx +96 -0
  151. package/src/components/RoutesOverview.tsx +60 -0
  152. package/src/components/SwitchFromAndTo.tsx +30 -0
  153. package/src/components/TokenInfo.tsx +311 -0
  154. package/src/components/TokenPreview.tsx +175 -0
  155. package/src/components/UpdateUrl.tsx +162 -0
  156. package/src/components/warnings/BalanceWarnings.tsx +39 -0
  157. package/src/components/warnings/ConfirmSwapExtraMessages.tsx +20 -0
  158. package/src/components/warnings/HighSlippageWarning.tsx +18 -0
  159. package/src/components/warnings/MinRequiredSlippage.tsx +18 -0
  160. package/src/constants/errors.ts +3 -0
  161. package/src/constants/navigationRoutes.ts +14 -0
  162. package/src/constants/numbers.ts +3 -0
  163. package/src/constants/searchParams.ts +7 -0
  164. package/src/constants/swapSettings.ts +9 -0
  165. package/src/globalStyles.ts +26 -0
  166. package/src/hooks/useConfirmSwap.ts +260 -0
  167. package/src/hooks/useCopyToClipboard.ts +23 -0
  168. package/src/hooks/useNavigateBack.ts +40 -0
  169. package/src/hooks/usePrevious.ts +13 -0
  170. package/src/hooks/useSelectLanguage.ts +15 -0
  171. package/src/hooks/useTheme.ts +127 -0
  172. package/src/i18n.js +30 -0
  173. package/src/index.tsx +14 -0
  174. package/src/languages/en.json +14 -0
  175. package/src/languages/tr.json +11 -0
  176. package/src/lib.tsx +119 -0
  177. package/src/mockData/pendingSwap.ts +607 -0
  178. package/src/pages/ConfirmSwapPage.tsx +72 -0
  179. package/src/pages/ConfirmWalletsPage.tsx +127 -0
  180. package/src/pages/HistoryPage.tsx +29 -0
  181. package/src/pages/Home.tsx +228 -0
  182. package/src/pages/LiquiditySourcesPage.tsx +64 -0
  183. package/src/pages/SelectChainPage.tsx +42 -0
  184. package/src/pages/SelectTokenPage.tsx +64 -0
  185. package/src/pages/SettingsPage.tsx +98 -0
  186. package/src/pages/SwapDetailsPage.tsx +38 -0
  187. package/src/pages/WalletsPage.tsx +119 -0
  188. package/src/services/httpService.ts +5 -0
  189. package/src/store/bestRoute.ts +245 -0
  190. package/src/store/meta.ts +35 -0
  191. package/src/store/selectors.ts +19 -0
  192. package/src/store/settings.ts +84 -0
  193. package/src/store/ui.ts +21 -0
  194. package/src/store/wallets.ts +190 -0
  195. package/src/types/config.ts +44 -0
  196. package/src/types/index.ts +3 -0
  197. package/src/types/routing.ts +60 -0
  198. package/src/types/swap.ts +13 -0
  199. package/src/utils/common.ts +35 -0
  200. package/src/utils/numbers.ts +133 -0
  201. package/src/utils/queue.ts +24 -0
  202. package/src/utils/routing.ts +150 -0
  203. package/src/utils/swap.ts +552 -0
  204. package/src/utils/wallets.ts +481 -0
@@ -0,0 +1,96 @@
1
+ import { Button, AddWalletIcon, Typography, styled } from '@rango-dev/ui';
2
+ import React, { useEffect } from 'react';
3
+ import { useNavigate } from 'react-router-dom';
4
+ import { useWallets } from '@rango-dev/wallets-core';
5
+ import { navigationRoutes } from '../constants/navigationRoutes';
6
+ import { useUiStore } from '../store/ui';
7
+ import { AppRoutes } from './AppRoutes';
8
+ import { useWalletsStore } from '../store/wallets';
9
+ import {
10
+ calculateWalletUsdValue,
11
+ getSelectableWallets,
12
+ } from '../utils/wallets';
13
+ import { removeDuplicateFrom } from '../utils/common';
14
+ import { Configs } from '../types';
15
+ import { useTranslation } from 'react-i18next';
16
+ import { useBestRouteStore } from '../store/bestRoute';
17
+
18
+ const Header = styled('div', {
19
+ display: 'flex',
20
+ width: '100%',
21
+ justifyContent: 'end',
22
+ });
23
+
24
+ const WalletImage = styled('img', {
25
+ width: '$24',
26
+ height: '$24',
27
+ marginLeft: -15,
28
+ marginRight: '$6',
29
+ borderRadius: '99999px',
30
+ });
31
+
32
+ export type LayoutProps = {
33
+ configs?: Configs;
34
+ };
35
+
36
+ export function Layout({ configs }: LayoutProps) {
37
+ const navigate = useNavigate();
38
+ const { balances, accounts, selectedWallets } = useWalletsStore();
39
+ const { getWalletInfo } = useWallets();
40
+ const connectedWalletsImages = removeDuplicateFrom(
41
+ getSelectableWallets(accounts, selectedWallets, getWalletInfo).map(
42
+ (w) => w.image
43
+ )
44
+ );
45
+
46
+ const setFromChain = useBestRouteStore.use.setFromChain();
47
+ const setFromToken = useBestRouteStore.use.setFromToken();
48
+ const setToChain = useBestRouteStore.use.setToChain();
49
+ const setToToken = useBestRouteStore.use.setToToken();
50
+ const setInputAmount = useBestRouteStore.use.setInputAmount();
51
+
52
+ const totalBalance = calculateWalletUsdValue(balances);
53
+ const connectWalletsButtonDisabled =
54
+ useUiStore.use.connectWalletsButtonDisabled();
55
+ const { t } = useTranslation();
56
+ useEffect(() => {
57
+ setToChain(configs?.toChain || null);
58
+ setToToken(configs?.toToken || null);
59
+ }, [configs?.toChain, configs?.toToken]);
60
+ useEffect(() => {
61
+ setInputAmount(configs?.fromAmount?.toString() || '');
62
+ }, [configs?.fromAmount]);
63
+
64
+ useEffect(() => {
65
+ setFromToken(configs?.fromToken || null);
66
+ setFromChain(configs?.fromChain || null);
67
+ }, [configs?.fromToken, configs?.fromChain]);
68
+ return (
69
+ <>
70
+ <Header>
71
+ <Button
72
+ size="small"
73
+ suffix={<AddWalletIcon size={20} />}
74
+ variant="ghost"
75
+ flexContent
76
+ onClick={() => {
77
+ if (!connectWalletsButtonDisabled)
78
+ navigate(navigationRoutes.wallets);
79
+ }}
80
+ >
81
+ {connectedWalletsImages?.length ? (
82
+ connectedWalletsImages.map((walletImage, index) => (
83
+ <WalletImage key={index} src={walletImage} />
84
+ ))
85
+ ) : (
86
+ <></>
87
+ )}
88
+ <Typography variant="body2">
89
+ {!accounts?.length ? t('Connect Wallet') : `$${totalBalance || 0}`}
90
+ </Typography>
91
+ </Button>
92
+ </Header>
93
+ <AppRoutes configs={configs} />
94
+ </>
95
+ );
96
+ }
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ import { styled } from '@rango-dev/ui';
3
+ import { BestRouteResponse } from 'rango-sdk';
4
+ import { ChevronRightIcon } from '@rango-dev/ui';
5
+ import { GasIcon } from '@rango-dev/ui';
6
+ import { Spacer } from '@rango-dev/ui';
7
+
8
+ export const Container = styled('div', {
9
+ display: 'flex',
10
+ alignItems: 'center',
11
+ justifyContent: 'space-between',
12
+ padding: '$8',
13
+ borderRadius: '$5',
14
+ backgroundColor: '$neutrals300',
15
+ color: '$neutrals800',
16
+ fontSize: '$12',
17
+
18
+ '.routes': {
19
+ display: 'flex',
20
+ alignItems: 'center',
21
+ },
22
+ '.fee': {
23
+ display: 'flex',
24
+ alignItems: 'center',
25
+ },
26
+ });
27
+
28
+ interface PropTypes {
29
+ routes: BestRouteResponse | null;
30
+ totalFee?: string;
31
+ }
32
+ function RoutesOverview(props: PropTypes) {
33
+ if (!props.routes) return null;
34
+
35
+ const swaps = props.routes.result?.swaps;
36
+ return (
37
+ <Container>
38
+ <div className="routes">
39
+ {swaps?.map((swap, idx) => {
40
+ const isLast = idx + 1 == swaps.length;
41
+ return (
42
+ <>
43
+ <div className="route">{swap.from.symbol}</div>
44
+ <ChevronRightIcon size={12} />
45
+ {isLast ? <div className="route">{swap.to.symbol}</div> : null}
46
+ </>
47
+ );
48
+ })}
49
+ </div>
50
+ {props.totalFee ? (
51
+ <div className="fee">
52
+ <GasIcon size={12} />
53
+ <Spacer size={4} />${props.totalFee}
54
+ </div>
55
+ ) : null}
56
+ </Container>
57
+ );
58
+ }
59
+
60
+ export default RoutesOverview;
@@ -0,0 +1,30 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { useSearchParams } from 'react-router-dom';
3
+ import { SearchParams } from '../constants/searchParams';
4
+ import { useBestRouteStore } from '../store/bestRoute';
5
+
6
+ export function SwithFromAndTo({ count }: { count: number }) {
7
+ const firstRender = useRef(true);
8
+ const [searchParams, setSearchParams] = useSearchParams();
9
+ const outputAmount = useBestRouteStore.use.outputAmount();
10
+
11
+ useEffect(() => {
12
+ if (!firstRender.current) {
13
+ const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);
14
+ const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);
15
+ const toChainString = searchParams.get(SearchParams.TO_CHAIN);
16
+ const toTokenString = searchParams.get(SearchParams.TO_TOKEN);
17
+ setSearchParams({
18
+ ...(toChainString && { [SearchParams.FROM_CHAIN]: toChainString }),
19
+ ...(toTokenString && { [SearchParams.FROM_TOKEN]: toTokenString }),
20
+ ...(fromChainString && { [SearchParams.TO_CHAIN]: fromChainString }),
21
+ ...(fromTokenString && { [SearchParams.TO_TOKEN]: fromTokenString }),
22
+ ...(outputAmount && { [SearchParams.FROM_AMOUNT]: outputAmount.toString() }),
23
+ });
24
+ } else {
25
+ firstRender.current = false;
26
+ }
27
+ }, [count]);
28
+
29
+ return null;
30
+ }
@@ -0,0 +1,311 @@
1
+ import React from 'react';
2
+ import {
3
+ AngleDownIcon,
4
+ Button,
5
+ InfoCircleIcon,
6
+ styled,
7
+ TextField,
8
+ Typography,
9
+ } from '@rango-dev/ui';
10
+ import { useMetaStore } from '../store/meta';
11
+ import { BlockchainMeta, Token } from 'rango-sdk';
12
+ import { useNavigate } from 'react-router-dom';
13
+ import { useBestRouteStore } from '../store/bestRoute';
14
+ import { numberToString } from '../utils/numbers';
15
+ import BigNumber from 'bignumber.js';
16
+ import { getBalanceFromWallet } from '../utils/wallets';
17
+ import { useWalletsStore } from '../store/wallets';
18
+ import { useTranslation } from 'react-i18next';
19
+ import { Spacer } from '@rango-dev/ui';
20
+
21
+ type PropTypes = (
22
+ | {
23
+ type: 'From';
24
+ inputAmount: string;
25
+ onAmountChange: (amount: string) => void;
26
+ }
27
+ | {
28
+ type: 'To';
29
+ outputAmount: BigNumber | null;
30
+ outputUsdValue: BigNumber | null;
31
+ }
32
+ ) & { chain: BlockchainMeta | null; token: Token | null };
33
+
34
+ const Box = styled('div', {
35
+ display: 'flex',
36
+ flexDirection: 'column',
37
+ width: '100%',
38
+ });
39
+
40
+ const Container = styled('div', {
41
+ boxSizing: 'border-box',
42
+ borderRadius: '$5',
43
+ padding: '$8 $16 $16 $16',
44
+
45
+ variants: {
46
+ type: {
47
+ filled: {
48
+ backgroundColor: '$neutrals300',
49
+ },
50
+ outlined: {
51
+ border: '1px solid $neutrals300',
52
+ },
53
+ },
54
+ },
55
+
56
+ defaultVariants: {
57
+ type: 'filled',
58
+ },
59
+
60
+ '.head': {
61
+ display: 'flex',
62
+ justifyContent: 'space-between',
63
+ alignItems: 'center',
64
+ minHeight: '32px',
65
+ },
66
+ '.form': {
67
+ display: 'flex',
68
+ width: '100%',
69
+ padding: '$2 0',
70
+ '.selectors': {
71
+ width: '35%',
72
+
73
+ '._text': {
74
+ whiteSpace: 'nowrap',
75
+ overflow: 'hidden',
76
+ textOverflow: 'ellipsis',
77
+ },
78
+ },
79
+ '.amount': {
80
+ width: '30%',
81
+ },
82
+ },
83
+ });
84
+
85
+ const StyledImage = styled('img', {
86
+ width: '$24',
87
+ maxHeight: '$24',
88
+ });
89
+
90
+ const Options = styled('div', {
91
+ display: 'flex',
92
+ justifyContent: 'flex-end',
93
+
94
+ '.balance': {
95
+ display: 'flex',
96
+ alignItems: 'center',
97
+ },
98
+ });
99
+
100
+ const ImagePlaceholder = styled('span', {
101
+ width: '24px',
102
+ height: '24px',
103
+ backgroundColor: '$neutrals300',
104
+ borderRadius: '99999px',
105
+ });
106
+
107
+ const OutputContainer = styled('div', {
108
+ windth: '100%',
109
+ height: '$48',
110
+ borderRadius: '$5',
111
+ backgroundColor: '$background',
112
+ border: '1px solid transparent',
113
+ position: 'relative',
114
+ display: 'flex',
115
+ alignItems: 'center',
116
+ paddingLeft: '$8',
117
+ paddingRight: '$8',
118
+ });
119
+
120
+ export function TokenInfo(props: PropTypes) {
121
+ const { type, chain, token } = props;
122
+ const loadingStatus = useMetaStore.use.loadingStatus();
123
+ const fromChain = useBestRouteStore.use.fromChain();
124
+ const toChain = useBestRouteStore.use.toChain();
125
+ const inputUsdValue = useBestRouteStore.use.inputUsdValue();
126
+ const fromToken = useBestRouteStore.use.fromToken();
127
+ const setInputAmount = useBestRouteStore.use.setInputAmount();
128
+ const bestRoute = useBestRouteStore.use.bestRoute();
129
+ const inputAmount = useBestRouteStore.use.inputAmount();
130
+ const balances = useWalletsStore.use.balances();
131
+ const navigate = useNavigate();
132
+ const { t } = useTranslation();
133
+
134
+ const tokenBalance =
135
+ !!fromChain && !!fromToken
136
+ ? numberToString(
137
+ getBalanceFromWallet(
138
+ balances,
139
+ fromChain?.name,
140
+ fromToken?.symbol,
141
+ fromToken?.address
142
+ )?.amount || '0',
143
+ 8
144
+ )
145
+ : '0';
146
+
147
+ const tokenBalanceReal =
148
+ !!fromChain && !!fromToken
149
+ ? numberToString(
150
+ getBalanceFromWallet(
151
+ balances,
152
+ fromChain?.name,
153
+ fromToken?.symbol,
154
+ fromToken?.address
155
+ )?.amount || '0',
156
+ getBalanceFromWallet(
157
+ balances,
158
+ fromChain?.name,
159
+ fromToken?.symbol,
160
+ fromToken?.address
161
+ )?.decimal
162
+ )
163
+ : '0';
164
+
165
+ const ItemSuffix = (
166
+ <div
167
+ style={{
168
+ display: 'flex',
169
+ justifyContent: 'center',
170
+ alignItems: 'center',
171
+ }}
172
+ >
173
+ {loadingStatus === 'failed' && <InfoCircleIcon color="error" size={24} />}
174
+ <AngleDownIcon />
175
+ </div>
176
+ );
177
+
178
+ return (
179
+ <Box>
180
+ <Container type={props.type === 'From' ? 'filled' : 'outlined'}>
181
+ <div className="head">
182
+ <Typography variant="body2" color="neutrals800">
183
+ {t(type)}
184
+ </Typography>
185
+ {props.type === 'From' ? (
186
+ <Options>
187
+ <div
188
+ className="balance"
189
+ onClick={() => {
190
+ if (tokenBalance !== '0')
191
+ setInputAmount(tokenBalanceReal.split(',').join(''));
192
+ }}
193
+ >
194
+ <Typography variant="body3" color="neutrals600">{`${t(
195
+ 'Balance'
196
+ )}: ${tokenBalance} ${fromToken?.symbol || ''}`}</Typography>
197
+ <Spacer size={4} />
198
+ <Button type="primary" variant="ghost" size="compact">
199
+ {t('Max')}
200
+ </Button>
201
+ </div>
202
+ </Options>
203
+ ) : (
204
+ <Typography
205
+ variant="caption"
206
+ color="neutrals600"
207
+ >{`$${numberToString(props.outputUsdValue)}`}</Typography>
208
+ )}
209
+ </div>
210
+ <div className="form">
211
+ <Button
212
+ className="selectors"
213
+ onClick={() => {
214
+ navigate(`/${props.type.toLowerCase()}-chain`);
215
+ }}
216
+ variant="outlined"
217
+ disabled={loadingStatus === 'failed'}
218
+ loading={loadingStatus === 'loading'}
219
+ prefix={
220
+ loadingStatus === 'success' && chain ? (
221
+ <StyledImage src={chain.logo} />
222
+ ) : (
223
+ <ImagePlaceholder />
224
+ )
225
+ }
226
+ suffix={ItemSuffix}
227
+ align="start"
228
+ size="large"
229
+ >
230
+ {loadingStatus === 'success' && chain
231
+ ? chain.displayName
232
+ : t('Chain')}
233
+ </Button>
234
+ <Spacer size={12} />
235
+ <Button
236
+ className="selectors"
237
+ onClick={() => {
238
+ navigate(`/${props.type.toLowerCase()}-token`);
239
+ }}
240
+ variant="outlined"
241
+ disabled={
242
+ loadingStatus === 'failed' ||
243
+ (type === 'From' && !fromChain) ||
244
+ (type === 'To' && !toChain)
245
+ }
246
+ loading={loadingStatus === 'loading'}
247
+ prefix={
248
+ loadingStatus === 'success' && token ? (
249
+ <StyledImage src={token.image} />
250
+ ) : (
251
+ <ImagePlaceholder />
252
+ )
253
+ }
254
+ suffix={ItemSuffix}
255
+ size="large"
256
+ align="start"
257
+ >
258
+ {loadingStatus === 'success' && token ? token.symbol : t('Token')}
259
+ </Button>
260
+ <Spacer size={12} />
261
+ <div className="amount">
262
+ {props.type === 'From' ? (
263
+ <TextField
264
+ type="number"
265
+ size="large"
266
+ autoFocus
267
+ placeholder="0"
268
+ style={{
269
+ position: 'relative',
270
+ backgroundColor: '$background !important',
271
+ }}
272
+ suffix={
273
+ <span
274
+ style={{
275
+ position: 'absolute',
276
+ right: '4px',
277
+ bottom: '2px',
278
+ }}
279
+ >
280
+ <Typography
281
+ variant="caption"
282
+ color="neutrals800"
283
+ >{`$${numberToString(inputUsdValue)}`}</Typography>
284
+ </span>
285
+ }
286
+ value={props.inputAmount || ''}
287
+ onChange={
288
+ props.type === 'From'
289
+ ? (event) => {
290
+ props.onAmountChange(event.target.value);
291
+ }
292
+ : undefined
293
+ }
294
+ />
295
+ ) : (
296
+ <OutputContainer>
297
+ <Typography variant="h4">
298
+ {bestRoute
299
+ ? `≈ ${numberToString(props.outputAmount)}`
300
+ : inputAmount
301
+ ? '?'
302
+ : '0'}
303
+ </Typography>
304
+ </OutputContainer>
305
+ )}
306
+ </div>
307
+ </div>
308
+ </Container>
309
+ </Box>
310
+ );
311
+ }
@@ -0,0 +1,175 @@
1
+ import React from 'react';
2
+ import { Button, InfoCircleIcon, styled, Typography } from '@rango-dev/ui';
3
+ import { LoadingStatus } from '../store/meta';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { Spacer } from '@rango-dev/ui';
6
+ import BigNumber from 'bignumber.js';
7
+ import { numberToString } from '../utils/numbers';
8
+
9
+ const Box = styled('div', {
10
+ display: 'flex',
11
+ flexDirection: 'column',
12
+ width: '100%',
13
+ });
14
+
15
+ const Container = styled('div', {
16
+ boxSizing: 'border-box',
17
+ borderRadius: '$5',
18
+ padding: '$8 $16 $16 $16',
19
+
20
+ variants: {
21
+ type: {
22
+ filled: {
23
+ backgroundColor: '$neutrals300',
24
+ },
25
+ outlined: {
26
+ border: '1px solid $neutrals300',
27
+ },
28
+ },
29
+ },
30
+
31
+ defaultVariants: {
32
+ type: 'filled',
33
+ },
34
+
35
+ '.head': {
36
+ display: 'flex',
37
+ justifyContent: 'space-between',
38
+ alignItems: 'center',
39
+ minHeight: '32px',
40
+ },
41
+ '.form': {
42
+ display: 'flex',
43
+ width: '100%',
44
+ padding: '$2 0',
45
+ '.selectors': {
46
+ width: '35%',
47
+
48
+ '._text': {
49
+ whiteSpace: 'nowrap',
50
+ overflow: 'hidden',
51
+ textOverflow: 'ellipsis',
52
+ },
53
+ },
54
+ '.amount': {
55
+ width: '30%',
56
+ },
57
+ },
58
+ });
59
+
60
+ const StyledImage = styled('img', {
61
+ width: '$24',
62
+ maxHeight: '$24',
63
+ });
64
+
65
+ const ImagePlaceholder = styled('span', {
66
+ width: '24px',
67
+ height: '24px',
68
+ backgroundColor: '$neutrals300',
69
+ borderRadius: '99999px',
70
+ });
71
+
72
+ const OutputContainer = styled('div', {
73
+ windth: '100%',
74
+ height: '$48',
75
+ borderRadius: '$5',
76
+ backgroundColor: '$background',
77
+ border: '1px solid transparent',
78
+ position: 'relative',
79
+ display: 'flex',
80
+ alignItems: 'center',
81
+ paddingLeft: '$8',
82
+ paddingRight: '$8',
83
+ });
84
+
85
+ interface PropTypes {
86
+ label: string;
87
+ amount: string;
88
+ usdValue: BigNumber;
89
+ loadingStatus: LoadingStatus;
90
+ chain: {
91
+ displayName: string;
92
+ logo: string;
93
+ };
94
+ token: {
95
+ symbol: string;
96
+ image: string;
97
+ };
98
+ }
99
+
100
+ export function TokenPreview(props: PropTypes) {
101
+ const { chain, token, loadingStatus } = props;
102
+ const { t } = useTranslation();
103
+
104
+ const ItemSuffix = (
105
+ <div
106
+ style={{
107
+ display: 'flex',
108
+ justifyContent: 'center',
109
+ alignItems: 'center',
110
+ }}
111
+ >
112
+ {loadingStatus === 'failed' && <InfoCircleIcon color="error" size={24} />}
113
+ </div>
114
+ );
115
+
116
+ return (
117
+ <Box>
118
+ <Container type={'outlined'}>
119
+ <div className="head">
120
+ <Typography variant="body2" color="neutrals800">
121
+ {props.label}
122
+ </Typography>
123
+ <Typography variant="caption" color="neutrals600">{`$${numberToString(
124
+ props.usdValue
125
+ )}`}</Typography>
126
+ </div>
127
+ <div className="form">
128
+ <Button
129
+ className="selectors"
130
+ variant="outlined"
131
+ loading={loadingStatus === 'loading'}
132
+ prefix={
133
+ loadingStatus === 'success' && chain ? (
134
+ <StyledImage src={chain.logo} />
135
+ ) : (
136
+ <ImagePlaceholder />
137
+ )
138
+ }
139
+ suffix={ItemSuffix}
140
+ align="start"
141
+ size="large"
142
+ >
143
+ {loadingStatus === 'success' && chain
144
+ ? chain.displayName
145
+ : t('Chain')}
146
+ </Button>
147
+ <Spacer size={12} />
148
+ <Button
149
+ className="selectors"
150
+ variant="outlined"
151
+ loading={loadingStatus === 'loading'}
152
+ prefix={
153
+ loadingStatus === 'success' && token ? (
154
+ <StyledImage src={token.image} />
155
+ ) : (
156
+ <ImagePlaceholder />
157
+ )
158
+ }
159
+ suffix={ItemSuffix}
160
+ size="large"
161
+ align="start"
162
+ >
163
+ {loadingStatus === 'success' && token ? token.symbol : t('Token')}
164
+ </Button>
165
+ <Spacer size={12} />
166
+ <div className="amount">
167
+ <OutputContainer>
168
+ <Typography variant="h4">{props.amount}</Typography>
169
+ </OutputContainer>
170
+ </div>
171
+ </div>
172
+ </Container>
173
+ </Box>
174
+ );
175
+ }