@rango-dev/widget-embedded 0.20.1-next.2 → 0.20.1-next.20

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 (178) hide show
  1. package/dist/components/BlockchainList/BlockchainList.styles.d.ts +8 -0
  2. package/dist/components/BlockchainList/BlockchainList.styles.d.ts.map +1 -1
  3. package/dist/components/BlockchainsSection/BlockchainsSection.styles.d.ts +4 -0
  4. package/dist/components/BlockchainsSection/BlockchainsSection.styles.d.ts.map +1 -1
  5. package/dist/components/ConfirmWalletsModal/ConfirmWallets.styles.d.ts +514 -1088
  6. package/dist/components/ConfirmWalletsModal/ConfirmWallets.styles.d.ts.map +1 -1
  7. package/dist/components/ConfirmWalletsModal/ConfirmWalletsModal.d.ts.map +1 -1
  8. package/dist/components/ConfirmWalletsModal/WalletList.styles.d.ts +12 -0
  9. package/dist/components/ConfirmWalletsModal/WalletList.styles.d.ts.map +1 -1
  10. package/dist/components/CustomCollapsible/CustomCollapsible.d.ts +5 -0
  11. package/dist/components/CustomCollapsible/CustomCollapsible.d.ts.map +1 -0
  12. package/dist/components/CustomCollapsible/CustomCollapsible.styles.d.ts +654 -0
  13. package/dist/components/CustomCollapsible/CustomCollapsible.styles.d.ts.map +1 -0
  14. package/dist/components/CustomCollapsible/CustomCollapsible.types.d.ts +10 -0
  15. package/dist/components/CustomCollapsible/CustomCollapsible.types.d.ts.map +1 -0
  16. package/dist/components/HeaderButtons/HeaderButtons.styles.d.ts +179 -0
  17. package/dist/components/HeaderButtons/HeaderButtons.styles.d.ts.map +1 -1
  18. package/dist/components/HeaderButtons/HeaderButtons.types.d.ts +0 -1
  19. package/dist/components/HeaderButtons/HeaderButtons.types.d.ts.map +1 -1
  20. package/dist/components/HeaderButtons/HomeButtons.d.ts.map +1 -1
  21. package/dist/components/HeaderButtons/RefreshButton.d.ts +6 -0
  22. package/dist/components/HeaderButtons/RefreshButton.d.ts.map +1 -0
  23. package/dist/components/Layout/Layout.styles.d.ts +12 -0
  24. package/dist/components/Layout/Layout.styles.d.ts.map +1 -1
  25. package/dist/components/LoadingLiquiditySourceList/LoadingLiquiditySourceList.styles.d.ts +4 -0
  26. package/dist/components/LoadingLiquiditySourceList/LoadingLiquiditySourceList.styles.d.ts.map +1 -1
  27. package/dist/components/LoadingSwapDetails/LoadingSwapDetails.styles.d.ts +56 -0
  28. package/dist/components/LoadingSwapDetails/LoadingSwapDetails.styles.d.ts.map +1 -1
  29. package/dist/components/NoResult/NoResult.styles.d.ts +12 -0
  30. package/dist/components/NoResult/NoResult.styles.d.ts.map +1 -1
  31. package/dist/components/NotificationContent/NotificationContent.d.ts.map +1 -1
  32. package/dist/components/NotificationContent/NotificationContent.styles.d.ts +16 -0
  33. package/dist/components/NotificationContent/NotificationContent.styles.d.ts.map +1 -1
  34. package/dist/components/Quote/Quote.d.ts.map +1 -1
  35. package/dist/components/Quote/Quote.styles.d.ts +386 -2
  36. package/dist/components/Quote/Quote.styles.d.ts.map +1 -1
  37. package/dist/components/Quote/Quote.types.d.ts +19 -0
  38. package/dist/components/Quote/Quote.types.d.ts.map +1 -1
  39. package/dist/components/Quote/QuoteCostDetails.d.ts +4 -0
  40. package/dist/components/Quote/QuoteCostDetails.d.ts.map +1 -0
  41. package/dist/components/Quote/QuoteCostDetails.styles.d.ts +806 -0
  42. package/dist/components/Quote/QuoteCostDetails.styles.d.ts.map +1 -0
  43. package/dist/components/Quote/QuoteSummary.d.ts.map +1 -1
  44. package/dist/components/Quote/QuoteSummary.styles.d.ts +8 -0
  45. package/dist/components/Quote/QuoteSummary.styles.d.ts.map +1 -1
  46. package/dist/components/Quote/QuoteTrigger .d.ts +4 -0
  47. package/dist/components/Quote/QuoteTrigger .d.ts.map +1 -0
  48. package/dist/components/QuoteSkeleton/QuoteSkeleton.styles.d.ts +16 -0
  49. package/dist/components/QuoteSkeleton/QuoteSkeleton.styles.d.ts.map +1 -1
  50. package/dist/components/QuoteSkeleton/QuoteSummarySkeleton.styles.d.ts +40 -0
  51. package/dist/components/QuoteSkeleton/QuoteSummarySkeleton.styles.d.ts.map +1 -1
  52. package/dist/components/QuoteSkeleton/StepSkeleton.styles.d.ts +20 -0
  53. package/dist/components/QuoteSkeleton/StepSkeleton.styles.d.ts.map +1 -1
  54. package/dist/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.styles.d.ts +16 -0
  55. package/dist/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.styles.d.ts.map +1 -1
  56. package/dist/components/SearchInput/SearchInput.styles.d.ts +4 -0
  57. package/dist/components/SearchInput/SearchInput.styles.d.ts.map +1 -1
  58. package/dist/components/SettingsContainer/SettingsContainer.style.d.ts +16 -0
  59. package/dist/components/SettingsContainer/SettingsContainer.style.d.ts.map +1 -1
  60. package/dist/components/Slippage/Slippage.styles.d.ts +20 -0
  61. package/dist/components/Slippage/Slippage.styles.d.ts.map +1 -1
  62. package/dist/components/SwapDetails/SwapDetails.Placeholder.d.ts.map +1 -1
  63. package/dist/components/SwapDetails/SwapDetails.d.ts.map +1 -1
  64. package/dist/components/SwapDetails/SwapDetails.helpers.d.ts +1 -1
  65. package/dist/components/SwapDetails/SwapDetails.helpers.d.ts.map +1 -1
  66. package/dist/components/SwapDetails/SwapDetails.styles.d.ts +362 -0
  67. package/dist/components/SwapDetails/SwapDetails.styles.d.ts.map +1 -1
  68. package/dist/components/SwapDetailsAlerts/SwapDetailsAlerts.d.ts.map +1 -1
  69. package/dist/components/SwapDetailsAlerts/SwapDetailsAlerts.styles.d.ts +4 -0
  70. package/dist/components/SwapDetailsAlerts/SwapDetailsAlerts.styles.d.ts.map +1 -1
  71. package/dist/components/SwapDetailsAlerts/SwapDetailsAlerts.types.d.ts +2 -1
  72. package/dist/components/SwapDetailsAlerts/SwapDetailsAlerts.types.d.ts.map +1 -1
  73. package/dist/components/SwapDetailsModal/SwapDetailsModal.styles.d.ts +4 -0
  74. package/dist/components/SwapDetailsModal/SwapDetailsModal.styles.d.ts.map +1 -1
  75. package/dist/components/SwapsGroup/SwapsGroup.d.ts.map +1 -1
  76. package/dist/components/SwapsGroup/SwapsGroup.styles.d.ts +20 -0
  77. package/dist/components/SwapsGroup/SwapsGroup.styles.d.ts.map +1 -1
  78. package/dist/components/TokenList/TokenList.styles.d.ts +68 -0
  79. package/dist/components/TokenList/TokenList.styles.d.ts.map +1 -1
  80. package/dist/components/WalletModal/WalletModalContent.styles.d.ts +16 -0
  81. package/dist/components/WalletModal/WalletModalContent.styles.d.ts.map +1 -1
  82. package/dist/components/WidgetEvents.d.ts.map +1 -1
  83. package/dist/constants/index.d.ts +1 -0
  84. package/dist/constants/index.d.ts.map +1 -1
  85. package/dist/constants/quote.d.ts +12 -0
  86. package/dist/constants/quote.d.ts.map +1 -0
  87. package/dist/containers/App/App.d.ts.map +1 -1
  88. package/dist/containers/App/App.styles.d.ts +4 -0
  89. package/dist/containers/App/App.styles.d.ts.map +1 -1
  90. package/dist/containers/QuoteInfo/QuoteInfo.styles.d.ts +20 -0
  91. package/dist/containers/QuoteInfo/QuoteInfo.styles.d.ts.map +1 -1
  92. package/dist/containers/Wallets/Wallets.d.ts.map +1 -1
  93. package/dist/containers/WidgetInfo/WidgetInfo.d.ts.map +1 -1
  94. package/dist/containers/WidgetInfo/WidgetInfo.types.d.ts +5 -0
  95. package/dist/containers/WidgetInfo/WidgetInfo.types.d.ts.map +1 -1
  96. package/dist/containers/WidgetProvider/WidgetProvider.d.ts.map +1 -1
  97. package/dist/hooks/useLanguage.d.ts +2 -1
  98. package/dist/hooks/useLanguage.d.ts.map +1 -1
  99. package/dist/hooks/usePrepareBlockchainList/usePrepareBlockchainList.helpers.d.ts +2 -2
  100. package/dist/hooks/useSwapInput.d.ts.map +1 -1
  101. package/dist/hooks/useSyncStoresWithConfig.d.ts.map +1 -1
  102. package/dist/index.d.ts +6 -6
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +2 -1
  105. package/dist/index.js.map +4 -4
  106. package/dist/pages/ConfirmSwapPage.d.ts.map +1 -1
  107. package/dist/pages/Home.d.ts.map +1 -1
  108. package/dist/pages/LiquiditySourcePage.d.ts.map +1 -1
  109. package/dist/pages/SelectSwapItemsPage.d.ts.map +1 -1
  110. package/dist/store/AppStore.d.ts +2 -2
  111. package/dist/store/app.d.ts +2 -2
  112. package/dist/store/slices/data.d.ts.map +1 -1
  113. package/dist/store/slices/settings.d.ts +2 -2
  114. package/dist/store/slices/settings.d.ts.map +1 -1
  115. package/dist/types/config.d.ts +16 -3
  116. package/dist/types/config.d.ts.map +1 -1
  117. package/dist/types/notification.d.ts +1 -2
  118. package/dist/types/notification.d.ts.map +1 -1
  119. package/dist/utils/configs.d.ts +8 -0
  120. package/dist/utils/configs.d.ts.map +1 -1
  121. package/dist/utils/date.d.ts.map +1 -1
  122. package/dist/utils/quote.d.ts +5 -1
  123. package/dist/utils/quote.d.ts.map +1 -1
  124. package/dist/utils/settings.d.ts +1 -1
  125. package/dist/utils/swap.d.ts +5 -1
  126. package/dist/utils/swap.d.ts.map +1 -1
  127. package/package.json +6 -6
  128. package/src/components/ConfirmWalletsModal/ConfirmWallets.styles.ts +27 -96
  129. package/src/components/ConfirmWalletsModal/ConfirmWalletsModal.tsx +25 -40
  130. package/src/components/CustomCollapsible/CustomCollapsible.styles.ts +75 -0
  131. package/src/components/CustomCollapsible/CustomCollapsible.tsx +55 -0
  132. package/src/components/CustomCollapsible/CustomCollapsible.types.ts +10 -0
  133. package/src/components/HeaderButtons/HeaderButtons.styles.ts +16 -1
  134. package/src/components/HeaderButtons/HeaderButtons.types.ts +0 -1
  135. package/src/components/HeaderButtons/HomeButtons.tsx +20 -33
  136. package/src/components/HeaderButtons/RefreshButton.tsx +81 -0
  137. package/src/components/NotificationContent/NotificationContent.tsx +10 -1
  138. package/src/components/Quote/Quote.styles.ts +44 -5
  139. package/src/components/Quote/Quote.tsx +10 -77
  140. package/src/components/Quote/Quote.types.ts +22 -0
  141. package/src/components/Quote/QuoteCostDetails.styles.ts +50 -0
  142. package/src/components/Quote/QuoteCostDetails.tsx +218 -0
  143. package/src/components/Quote/QuoteSummary.tsx +3 -2
  144. package/src/components/Quote/QuoteTrigger .tsx +215 -0
  145. package/src/components/Slippage/Slippage.tsx +5 -5
  146. package/src/components/Slippage/SlippageTooltipContent.tsx +1 -1
  147. package/src/components/SwapDetails/SwapDetails.Placeholder.tsx +12 -12
  148. package/src/components/SwapDetails/SwapDetails.helpers.tsx +43 -3
  149. package/src/components/SwapDetails/SwapDetails.styles.ts +13 -0
  150. package/src/components/SwapDetails/SwapDetails.tsx +10 -0
  151. package/src/components/SwapDetailsAlerts/SwapDetailsAlerts.tsx +13 -7
  152. package/src/components/SwapDetailsAlerts/SwapDetailsAlerts.types.ts +2 -0
  153. package/src/components/SwapsGroup/SwapsGroup.tsx +18 -7
  154. package/src/components/WidgetEvents.tsx +2 -14
  155. package/src/constants/index.ts +1 -0
  156. package/src/constants/quote.ts +23 -0
  157. package/src/containers/App/App.tsx +1 -4
  158. package/src/containers/Wallets/Wallets.tsx +11 -2
  159. package/src/containers/WidgetInfo/WidgetInfo.tsx +8 -0
  160. package/src/containers/WidgetInfo/WidgetInfo.types.ts +5 -0
  161. package/src/containers/WidgetProvider/WidgetProvider.tsx +2 -1
  162. package/src/hooks/useLanguage.ts +6 -4
  163. package/src/hooks/useSwapInput.ts +6 -2
  164. package/src/hooks/useSyncStoresWithConfig.ts +17 -34
  165. package/src/index.ts +4 -2
  166. package/src/pages/ConfirmSwapPage.tsx +12 -10
  167. package/src/pages/Home.tsx +5 -1
  168. package/src/pages/LiquiditySourcePage.tsx +5 -2
  169. package/src/pages/SelectBlockchainPage.tsx +3 -3
  170. package/src/pages/SelectSwapItemsPage.tsx +5 -1
  171. package/src/store/slices/data.ts +5 -7
  172. package/src/store/slices/settings.ts +3 -3
  173. package/src/types/config.ts +16 -3
  174. package/src/types/notification.ts +0 -7
  175. package/src/utils/configs.ts +41 -0
  176. package/src/utils/date.ts +5 -4
  177. package/src/utils/quote.ts +18 -1
  178. package/src/utils/swap.ts +35 -0
@@ -0,0 +1,218 @@
1
+ import type { QuoteCostDetailsProps } from './Quote.types';
2
+ import type { NameOfFees } from '../../constants/quote';
3
+
4
+ import { i18n } from '@lingui/core';
5
+ import {
6
+ ChevronDownIcon,
7
+ CloseIcon,
8
+ Divider,
9
+ IconButton,
10
+ Modal,
11
+ QuoteCost,
12
+ Tooltip,
13
+ Typography,
14
+ } from '@rango-dev/ui';
15
+ import BigNumber from 'bignumber.js';
16
+ import React, { useState } from 'react';
17
+
18
+ import { NAME_OF_FEES } from '../../constants/quote';
19
+ import {
20
+ GAS_FEE_MAX_DECIMALS,
21
+ GAS_FEE_MIN_DECIMALS,
22
+ USD_VALUE_MAX_DECIMALS,
23
+ USD_VALUE_MIN_DECIMALS,
24
+ } from '../../constants/routing';
25
+ import { useAppStore } from '../../store/AppStore';
26
+ import { getContainer } from '../../utils/common';
27
+ import {
28
+ formatTooltipNumbers,
29
+ numberToString,
30
+ secondsToString,
31
+ totalArrivalTime,
32
+ } from '../../utils/numbers';
33
+ import {
34
+ getFeesGroup,
35
+ getTotalFeeInUsd,
36
+ getTotalFeesInUsd,
37
+ getUsdFee,
38
+ } from '../../utils/swap';
39
+ import { CustomCollapsible } from '../CustomCollapsible/CustomCollapsible';
40
+ import { ExpandedIcon } from '../CustomCollapsible/CustomCollapsible.styles';
41
+
42
+ import {
43
+ FeeSection,
44
+ Line,
45
+ ModalContainer,
46
+ ModalHeader,
47
+ trigger,
48
+ } from './QuoteCostDetails.styles';
49
+
50
+ const GAS_FEE_MAX = 30;
51
+
52
+ const NonPayableFee = (props: { fee: BigNumber; label: string }) => {
53
+ return !props.fee.isZero() ? (
54
+ <FeeSection>
55
+ <Typography variant="label" size="medium" color="neutral600">
56
+ {props.label}
57
+ </Typography>
58
+ <Typography variant="label" size="medium">
59
+ $
60
+ {numberToString(
61
+ props.fee,
62
+ USD_VALUE_MIN_DECIMALS,
63
+ USD_VALUE_MAX_DECIMALS
64
+ )}
65
+ </Typography>
66
+ </FeeSection>
67
+ ) : null;
68
+ };
69
+
70
+ export function QuoteCostDetails(props: QuoteCostDetailsProps) {
71
+ const [open, setOpen] = useState<boolean>(false);
72
+ const [openCollapse, setOpenCollapse] = useState<boolean>(false);
73
+ const { steps, quote } = props;
74
+ const tokens = useAppStore().tokens();
75
+ const totalTime = secondsToString(totalArrivalTime(quote.result?.swaps));
76
+ const swaps = quote.result?.swaps ?? [];
77
+ const container = getContainer();
78
+
79
+ const totalFee = getTotalFeeInUsd(swaps, tokens);
80
+
81
+ const feesGroup = getFeesGroup(swaps);
82
+
83
+ return (
84
+ <>
85
+ <QuoteCost
86
+ onClickFee={() => setOpen(!open)}
87
+ fee={numberToString(
88
+ totalFee,
89
+ GAS_FEE_MIN_DECIMALS,
90
+ GAS_FEE_MAX_DECIMALS
91
+ )}
92
+ feeWarning={totalFee.gte(new BigNumber(GAS_FEE_MAX))}
93
+ time={totalTime}
94
+ steps={steps}
95
+ tooltipGas={i18n.t('View more info')}
96
+ tooltipContainer={container}
97
+ />
98
+
99
+ <Modal
100
+ container={container}
101
+ open={open}
102
+ header={
103
+ <ModalHeader>
104
+ <Typography variant="title" size="medium">
105
+ {i18n.t('Gas & Fee Explanation')}
106
+ </Typography>
107
+
108
+ <IconButton onClick={() => setOpen(false)} variant="ghost">
109
+ <CloseIcon color="gray" size={14} />
110
+ </IconButton>
111
+ </ModalHeader>
112
+ }
113
+ onClose={() => setOpen(false)}>
114
+ <ModalContainer>
115
+ <Typography variant="title" size="small">
116
+ {i18n.t('Details')}
117
+ </Typography>
118
+ <Divider size={10} />
119
+ {Object.entries(feesGroup.payable).flatMap(
120
+ ([payableFeesKey, feeArray]) =>
121
+ feeArray.map((fee, index) => {
122
+ const key = `payable-fee-${index}`;
123
+ const usdValue = getUsdFee(fee);
124
+ return (
125
+ <FeeSection key={key}>
126
+ <Typography
127
+ variant="label"
128
+ size="medium"
129
+ color="neutral600">
130
+ {NAME_OF_FEES[payableFeesKey as NameOfFees]}
131
+ </Typography>
132
+ <Tooltip
133
+ content={formatTooltipNumbers(fee.amount)}
134
+ container={container}>
135
+ <Typography variant="label" size="medium">
136
+ {numberToString(
137
+ fee.amount,
138
+ GAS_FEE_MIN_DECIMALS,
139
+ GAS_FEE_MAX_DECIMALS
140
+ )}{' '}
141
+ {fee.asset.symbol} ($
142
+ {numberToString(
143
+ usdValue,
144
+ USD_VALUE_MIN_DECIMALS,
145
+ USD_VALUE_MAX_DECIMALS
146
+ )}
147
+ )
148
+ </Typography>
149
+ </Tooltip>
150
+ </FeeSection>
151
+ );
152
+ })
153
+ )}
154
+
155
+ <FeeSection className="total_payable_fee">
156
+ <Typography variant="label" size="medium">
157
+ {i18n.t('Total Payable Fee')}
158
+ </Typography>
159
+ <Typography variant="label" size="medium">
160
+ $
161
+ {numberToString(
162
+ totalFee,
163
+ USD_VALUE_MIN_DECIMALS,
164
+ USD_VALUE_MAX_DECIMALS
165
+ )}
166
+ </Typography>
167
+ </FeeSection>
168
+ <Line />
169
+ {Object.keys(feesGroup.nonePayable).length && (
170
+ <CustomCollapsible
171
+ triggerAnchor="bottom"
172
+ onClickTrigger={() => setOpenCollapse((prev) => !prev)}
173
+ trigger={
174
+ <div className={trigger()}>
175
+ <Typography size="small" variant="body" color="neutral700">
176
+ {openCollapse
177
+ ? i18n.t('Hide non-payable fees')
178
+ : i18n.t('Show non-payable fees')}
179
+ </Typography>
180
+ <Divider size={4} direction="horizontal" />
181
+ <ExpandedIcon orientation={openCollapse ? 'up' : 'down'}>
182
+ <ChevronDownIcon size={12} color="gray" />
183
+ </ExpandedIcon>
184
+ </div>
185
+ }
186
+ open={openCollapse}>
187
+ <Typography size="small" variant="title">
188
+ {i18n.t('Description')}
189
+ </Typography>
190
+ <Divider size={4} />
191
+ <Typography size="small" variant="body" color="neutral700">
192
+ {i18n.t(`The following fees are considered in the transaction output and
193
+ you won’t need to pay extra gas for them.`)}
194
+ </Typography>
195
+ <Divider size={10} />
196
+ {Object.entries(feesGroup.nonePayable).map(
197
+ ([nonPayableFeesKey, fees], index) => {
198
+ const totalFeeInUsd = getTotalFeesInUsd(fees);
199
+ const label = NAME_OF_FEES[nonPayableFeesKey as NameOfFees];
200
+ const key = `non-payable-fee-${index}`;
201
+ return (
202
+ <NonPayableFee
203
+ key={key}
204
+ fee={totalFeeInUsd}
205
+ label={label}
206
+ />
207
+ );
208
+ }
209
+ )}
210
+
211
+ <Line />
212
+ </CustomCollapsible>
213
+ )}
214
+ </ModalContainer>
215
+ </Modal>
216
+ </>
217
+ );
218
+ }
@@ -1,5 +1,6 @@
1
1
  import type { PriceImpactWarningLevel, Step } from '@rango-dev/ui';
2
2
 
3
+ import { i18n } from '@lingui/core';
3
4
  import { TokenAmount } from '@rango-dev/ui';
4
5
  import React from 'react';
5
6
 
@@ -21,7 +22,7 @@ export function QuoteSummary(props: PropTypes) {
21
22
  <Container>
22
23
  <TokenAmount
23
24
  direction="horizontal"
24
- label="Swap input"
25
+ label={i18n.t('Swap input')}
25
26
  type="input"
26
27
  tooltipContainer={getContainer()}
27
28
  price={{
@@ -39,8 +40,8 @@ export function QuoteSummary(props: PropTypes) {
39
40
  <div className={separatorStyles()} />
40
41
  <TokenAmount
41
42
  direction="horizontal"
42
- label="Estimated output"
43
43
  tooltipContainer={getContainer()}
44
+ label={i18n.t('Estimated output')}
44
45
  type="output"
45
46
  price={{
46
47
  value: to.price.value,
@@ -0,0 +1,215 @@
1
+ import type { QuoteTriggerImagesProps, QuoteTriggerProps } from './Quote.types';
2
+
3
+ import { i18n } from '@lingui/core';
4
+ import {
5
+ ChevronDownIcon,
6
+ ChevronRightIcon,
7
+ Divider,
8
+ Image,
9
+ Tooltip,
10
+ Typography,
11
+ } from '@rango-dev/ui';
12
+ import React, { useEffect, useState } from 'react';
13
+
14
+ import { getContainer } from '../../utils/common';
15
+ import { getUniqueBlockchains } from '../../utils/quote';
16
+
17
+ import {
18
+ IconContainer,
19
+ ImageContainer,
20
+ MoreStep,
21
+ rowStyles,
22
+ Trigger,
23
+ } from './Quote.styles';
24
+
25
+ const MAX_STEPS = 4;
26
+ const MAX_BLOCKCHAINS = 6;
27
+ const MIN_WIDTH_WINDOW = 375;
28
+
29
+ const ImageComponent = (props: QuoteTriggerImagesProps) => {
30
+ const tooltipContainer = getContainer();
31
+ const { content, src, className, open, state } = props;
32
+ return (
33
+ <Tooltip
34
+ container={tooltipContainer}
35
+ side="bottom"
36
+ sideOffset={4}
37
+ open={open}
38
+ content={content}>
39
+ <ImageContainer className={className} state={state}>
40
+ <Image src={src} size={16} />
41
+ </ImageContainer>
42
+ </Tooltip>
43
+ );
44
+ };
45
+
46
+ export function QuoteTrigger(props: QuoteTriggerProps) {
47
+ const { quoteRef, recommended, setExpanded, steps, expanded } = props;
48
+ const tooltipContainer = getContainer();
49
+ const numberOfSteps = steps.length;
50
+ const blockchains = getUniqueBlockchains(steps);
51
+ const [isMobile, setIsMobile] = useState(false);
52
+
53
+ //choose the screen size
54
+ const handleResize = () => {
55
+ if (window.innerWidth < MIN_WIDTH_WINDOW) {
56
+ setIsMobile(true);
57
+ } else {
58
+ setIsMobile(false);
59
+ }
60
+ };
61
+
62
+ useEffect(() => {
63
+ window.addEventListener('resize', handleResize);
64
+ });
65
+
66
+ return (
67
+ <Trigger
68
+ ref={(ref) => (quoteRef.current = ref)}
69
+ recommended={recommended}
70
+ onClick={() => setExpanded((prevState) => !prevState)}>
71
+ <div className={rowStyles()}>
72
+ <Typography variant="body" size="xsmall">
73
+ {i18n.t('Via:')}
74
+ </Typography>
75
+ <Divider direction="horizontal" size={4} />
76
+ {steps.map((step, index) => {
77
+ const key = `item-${index}`;
78
+ const arrow = (
79
+ <IconContainer>
80
+ <ChevronRightIcon size={12} color="black" />
81
+ </IconContainer>
82
+ );
83
+
84
+ return isMobile ? (
85
+ <>
86
+ <ImageComponent
87
+ content={step.swapper.displayName}
88
+ src={step.swapper.image}
89
+ state={step.state}
90
+ />
91
+ {index !== numberOfSteps - 1 && <>{arrow}</>}
92
+ </>
93
+ ) : (
94
+ <React.Fragment key={key}>
95
+ {numberOfSteps <= MAX_STEPS ||
96
+ (numberOfSteps > MAX_STEPS && index < MAX_STEPS - 1) ? (
97
+ <>
98
+ <ImageComponent
99
+ content={step.swapper.displayName}
100
+ src={step.swapper.image}
101
+ state={step.state}
102
+ />
103
+ {index !== numberOfSteps - 1 && <>{arrow}</>}
104
+ </>
105
+ ) : (
106
+ index === MAX_STEPS - 1 && (
107
+ <Tooltip
108
+ container={tooltipContainer}
109
+ side="bottom"
110
+ align="right"
111
+ sideOffset={4}
112
+ content={
113
+ <div className={rowStyles()}>
114
+ {arrow}
115
+ {steps.map((step, i) => {
116
+ const key = `image-${i}`;
117
+ return (
118
+ i >= index && (
119
+ <React.Fragment key={key}>
120
+ <ImageComponent
121
+ content={step.swapper.displayName}
122
+ src={step.swapper.image}
123
+ state={step.state}
124
+ open={false}
125
+ />
126
+ {i !== numberOfSteps - 1 && <>{arrow}</>}
127
+ </React.Fragment>
128
+ )
129
+ );
130
+ })}
131
+ </div>
132
+ }>
133
+ <MoreStep
134
+ state={
135
+ steps.find(
136
+ (step, i) =>
137
+ i >= index &&
138
+ (step.state === 'error' || step.state === 'warning')
139
+ )?.state
140
+ }>
141
+ <Typography size="xsmall" variant="body">
142
+ +{numberOfSteps - index}
143
+ </Typography>
144
+ </MoreStep>
145
+ </Tooltip>
146
+ )
147
+ )}
148
+ </React.Fragment>
149
+ );
150
+ })}
151
+ </div>
152
+ <div className={rowStyles()}>
153
+ <div className="blockchains_section">
154
+ <div className={rowStyles()}>
155
+ <Typography variant="body" size="xsmall">
156
+ {i18n.t('Chains:')}
157
+ </Typography>
158
+ <Divider direction="horizontal" size={4} />
159
+ {blockchains.map((blockchain, index) => (
160
+ <>
161
+ {blockchains.length <= MAX_BLOCKCHAINS ||
162
+ (blockchains.length > MAX_BLOCKCHAINS &&
163
+ index < MAX_BLOCKCHAINS - 1) ? (
164
+ <ImageComponent
165
+ key={blockchain.displayName}
166
+ content={''}
167
+ src={blockchain.image}
168
+ open={false}
169
+ className={index !== 0 ? 'blockchainImage' : ''}
170
+ />
171
+ ) : (
172
+ index === MAX_BLOCKCHAINS - 1 && (
173
+ <Tooltip
174
+ container={tooltipContainer}
175
+ side="bottom"
176
+ align="right"
177
+ sideOffset={4}
178
+ content={
179
+ <div className={rowStyles()}>
180
+ {blockchains.map(
181
+ (chain, i) =>
182
+ i >= index && (
183
+ <ImageComponent
184
+ key={chain.displayName}
185
+ content={''}
186
+ src={chain.image}
187
+ open={false}
188
+ className={i > index ? 'blockchainImage' : ''}
189
+ />
190
+ )
191
+ )}
192
+ </div>
193
+ }>
194
+ <MoreStep className={'blockchainImage'}>
195
+ <Typography size="xsmall" variant="body">
196
+ +{blockchains.length - index}
197
+ </Typography>
198
+ </MoreStep>
199
+ </Tooltip>
200
+ )
201
+ )}
202
+ </>
203
+ ))}
204
+
205
+ <Divider direction="horizontal" size={32} />
206
+ </div>
207
+ </div>
208
+
209
+ <IconContainer orientation={expanded ? 'up' : 'down'}>
210
+ <ChevronDownIcon size={12} color="black" />
211
+ </IconContainer>
212
+ </div>
213
+ </Trigger>
214
+ );
215
+ }
@@ -72,12 +72,12 @@ export function Slippage() {
72
72
  value={customSlippage || ''}
73
73
  color="dark"
74
74
  onChange={(event) => {
75
- const parsedValue = parseFloat(event.target.value);
76
- if (
77
- !parsedValue ||
78
- (parsedValue >= MIN_SLIPPGAE && parsedValue <= MAX_SLIPPAGE)
79
- ) {
75
+ const value = event.target.value;
76
+ const parsedValue = parseFloat(value);
77
+ if (parsedValue >= MIN_SLIPPGAE && parsedValue <= MAX_SLIPPAGE) {
80
78
  setCustomSlippage(parsedValue);
79
+ } else {
80
+ setCustomSlippage(null);
81
81
  }
82
82
  }}
83
83
  suffix={
@@ -15,7 +15,7 @@ export function SlippageTooltipContent() {
15
15
  <br />
16
16
  <b>{i18n.t('Warning')}</b>:
17
17
  {i18n.t(
18
- 'This setting is applied per step, e.g. 1Inch, Thorchain, etc. and only that step will be reverted, not the whole transaction'
18
+ 'This setting is applied per step (e.g. 1Inch, Thorchain, etc) which means only the step will be reverted, not the whole transaction.'
19
19
  )}
20
20
  </Typography>
21
21
  </SlippageTooltipContainer>
@@ -1,13 +1,7 @@
1
1
  import type { SwapDetailsPlaceholderPropTypes } from './SwapDetails.types';
2
2
 
3
3
  import { i18n } from '@lingui/core';
4
- import {
5
- CopyIcon,
6
- IconButton,
7
- NotFound,
8
- Skeleton,
9
- Typography,
10
- } from '@rango-dev/ui';
4
+ import { Divider, NotFound, Skeleton, Typography } from '@rango-dev/ui';
11
5
  import React from 'react';
12
6
 
13
7
  import { SuffixContainer } from '../HeaderButtons/HeaderButtons.styles';
@@ -16,6 +10,7 @@ import { LoadingSwapDetails } from '../LoadingSwapDetails';
16
10
 
17
11
  import {
18
12
  Container,
13
+ datePlaceholderStyles,
19
14
  HeaderDetails,
20
15
  PlaceholderContainer,
21
16
  requestIdStyles,
@@ -42,14 +37,19 @@ export function SwapDetailsPlaceholder(props: SwapDetailsPlaceholderPropTypes) {
42
37
  <Typography variant="label" size="small" color="neutral700">
43
38
  <Skeleton width={60} height={10} variant="rounded" />
44
39
  </Typography>
45
- <IconButton variant="ghost">
46
- <CopyIcon size={16} color="gray" />
47
- </IconButton>
40
+ <Divider direction="horizontal" size={4} />
41
+ <Skeleton width={16} height={16} variant="rectangular" />
42
+ <Divider direction="horizontal" size={4} />
43
+ <Skeleton width={16} height={16} variant="rectangular" />
48
44
  </div>
49
45
  </div>
50
46
  <div className={rowStyles()}>
51
- <Typography variant="label" size="large" color="neutral700">
52
- {`${i18n.t('Created at')}:`}
47
+ <Typography
48
+ className={datePlaceholderStyles()}
49
+ variant="label"
50
+ size="large"
51
+ color="neutral700">
52
+ <Skeleton width={60} height={10} variant="rounded" />
53
53
  </Typography>
54
54
  <Typography variant="label" size="small" color="neutral700">
55
55
  <Skeleton width={60} height={10} variant="rounded" />
@@ -8,7 +8,10 @@ import {
8
8
  TOKEN_AMOUNT_MAX_DECIMALS,
9
9
  TOKEN_AMOUNT_MIN_DECIMALS,
10
10
  } from '../../constants/routing';
11
- import { getBlockchainShortNameFor } from '../../utils/meta';
11
+ import {
12
+ getBlockchainShortNameFor,
13
+ getSwapperDisplayName,
14
+ } from '../../utils/meta';
12
15
  import { numberToString } from '../../utils/numbers';
13
16
  import { isNetworkStatusInWarningState } from '../../utils/swap';
14
17
  import { SwapDetailsAlerts } from '../SwapDetailsAlerts';
@@ -16,7 +19,12 @@ import { SwapDetailsAlerts } from '../SwapDetailsAlerts';
16
19
  export const RESET_INTERVAL = 2_000;
17
20
  export const SECONDS = 60;
18
21
 
19
- export const getSteps = ({ swap, blockchains, ...args }: GetStep): Step[] => {
22
+ export const getSteps = ({
23
+ swap,
24
+ blockchains,
25
+ swappers,
26
+ ...args
27
+ }: GetStep): Step[] => {
20
28
  const hasAlreadyProceededToSign = swap.hasAlreadyProceededToSign !== false;
21
29
  return swap.steps.map((step, index) => {
22
30
  const amountToConvert =
@@ -58,7 +66,39 @@ export const getSteps = ({ swap, blockchains, ...args }: GetStep): Step[] => {
58
66
  step.outputAmount || step.expectedOutputAmountHumanReadable,
59
67
  },
60
68
  },
61
- swapper: { displayName: step.swapperId, image: step.swapperLogo ?? '' },
69
+ swapper: {
70
+ displayName: getSwapperDisplayName(step.swapperId, swappers),
71
+ image: step.swapperLogo ?? '',
72
+ type: step.swapperType,
73
+ },
74
+ internalSwaps: step.internalSwaps
75
+ ? step.internalSwaps.map((internalSwap) => {
76
+ return {
77
+ from: {
78
+ blockchain:
79
+ getBlockchainShortNameFor(
80
+ internalSwap.fromBlockchain,
81
+ blockchains
82
+ ) ?? '',
83
+ },
84
+ to: {
85
+ blockchain:
86
+ getBlockchainShortNameFor(
87
+ internalSwap.toBlockchain,
88
+ blockchains
89
+ ) ?? '',
90
+ },
91
+ swapper: {
92
+ displayName: getSwapperDisplayName(
93
+ internalSwap.swapperId,
94
+ swappers
95
+ ),
96
+ image: internalSwap.swapperLogo ?? '',
97
+ type: internalSwap.swapperType,
98
+ },
99
+ };
100
+ })
101
+ : [],
62
102
  alerts: (
63
103
  <SwapDetailsAlerts
64
104
  step={step}
@@ -54,6 +54,10 @@ export const rowStyles = css({
54
54
  color: '$neutral500',
55
55
  });
56
56
 
57
+ export const datePlaceholderStyles = css({
58
+ padding: '$5 0',
59
+ });
60
+
57
61
  export const requestIdStyles = css({
58
62
  display: 'flex',
59
63
  justifyContent: 'center',
@@ -73,3 +77,12 @@ export const titleStepsStyles = css({
73
77
  width: '100%',
74
78
  padding: '0 $20 $10',
75
79
  });
80
+
81
+ export const StyledLink = styled('a', {
82
+ fontSize: '$16',
83
+ fontWeight: '$400',
84
+ color: '$neutral700',
85
+ display: 'flex',
86
+ alignItems: 'center',
87
+ justifyContent: 'center',
88
+ });
@@ -12,6 +12,7 @@ import {
12
12
  CopyIcon,
13
13
  Divider,
14
14
  IconButton,
15
+ LinkIcon,
15
16
  QuoteCost,
16
17
  StepDetails,
17
18
  Typography,
@@ -23,6 +24,7 @@ import { PendingSwapNetworkStatus } from 'rango-types';
23
24
  import React, { useEffect, useRef, useState } from 'react';
24
25
  import { useNavigate } from 'react-router-dom';
25
26
 
27
+ import { SCANNER_BASE_URL } from '../../constants';
26
28
  import {
27
29
  GAS_FEE_MAX_DECIMALS,
28
30
  GAS_FEE_MIN_DECIMALS,
@@ -67,6 +69,7 @@ import {
67
69
  requestIdStyles,
68
70
  rowStyles,
69
71
  StepsList,
72
+ StyledLink,
70
73
  titleStepsStyles,
71
74
  } from './SwapDetails.styles';
72
75
 
@@ -74,6 +77,7 @@ export function SwapDetails(props: SwapDetailsProps) {
74
77
  const { swap, requestId, onDelete, onCancel: onCancelProps } = props;
75
78
  const { canSwitchNetworkTo, connect, getWalletInfo } = useWallets();
76
79
  const blockchains = useAppStore().blockchains();
80
+ const swappers = useAppStore().swappers();
77
81
  const tokens = useAppStore().tokens();
78
82
  const retry = useQuoteStore.use.retry();
79
83
  const navigate = useNavigate();
@@ -158,6 +162,7 @@ export function SwapDetails(props: SwapDetailsProps) {
158
162
  setNetworkModal: setModalState,
159
163
  message: stepMessage,
160
164
  blockchains: blockchains,
165
+ swappers: swappers,
161
166
  });
162
167
  const numberOfSteps = steps.length;
163
168
  const [firstStep, lastStep] = [swap.steps[0], swap.steps[numberOfSteps - 1]];
@@ -289,6 +294,11 @@ export function SwapDetails(props: SwapDetailsProps) {
289
294
  onClick={handleCopy.bind(null, requestId || '')}>
290
295
  <CopyIcon size={16} color="gray" />
291
296
  </IconButton>
297
+ <StyledLink
298
+ target="_blank"
299
+ href={`${SCANNER_BASE_URL}/swap/${requestId}`}>
300
+ <LinkIcon size={16} />
301
+ </StyledLink>
292
302
  </div>
293
303
  </div>
294
304
  <div className={rowStyles()}>