@xswap-link/sdk 0.14.1 → 0.15.1

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 (68) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.global.js +99 -93
  3. package/dist/index.js +2061 -1846
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +1901 -1689
  6. package/dist/index.mjs.map +1 -1
  7. package/localTheme.ts +1 -1
  8. package/package.json +2 -1
  9. package/postcss.config.js +2 -0
  10. package/src/assets/icons/ChainlinkMarkIcon.tsx +4 -5
  11. package/src/assets/icons/CheckCircleThinIcon.tsx +22 -0
  12. package/src/assets/icons/ChevronDownThinIcon.tsx +39 -0
  13. package/src/assets/icons/ChevronDownWideThinIcon.tsx +18 -0
  14. package/src/assets/icons/ChevronRightThinIcon.tsx +23 -0
  15. package/src/assets/icons/ChevronsUpDownThinIcon.tsx +21 -0
  16. package/src/assets/icons/CloseIcon.tsx +3 -2
  17. package/src/assets/icons/ErrorCircleThinIcon.tsx +22 -0
  18. package/src/assets/icons/InfoThinIcon.tsx +33 -0
  19. package/src/assets/icons/LinkExternalThinIcon.tsx +19 -0
  20. package/src/assets/icons/LoadingRingIcon.tsx +22 -0
  21. package/src/assets/icons/ProgressRingThinIcon.tsx +29 -0
  22. package/src/assets/icons/RedirectThinIcon.tsx +15 -0
  23. package/src/assets/icons/SearchThinIcon.tsx +15 -0
  24. package/src/assets/icons/SignThinIcon.tsx +15 -0
  25. package/src/assets/icons/WalletCheckThinIcon.tsx +24 -0
  26. package/src/assets/icons/index.ts +14 -0
  27. package/src/components/PoweredBy/index.tsx +1 -1
  28. package/src/components/Swap/Header/index.tsx +5 -5
  29. package/src/components/Swap/HistoryView/ActivityCard/index.tsx +110 -115
  30. package/src/components/Swap/HistoryView/index.tsx +10 -7
  31. package/src/components/Swap/ReorderButton/ReorderButton.tsx +7 -4
  32. package/src/components/Swap/SettingsView/Delivery/index.tsx +20 -18
  33. package/src/components/Swap/SettingsView/InfiniteApproval/index.tsx +20 -18
  34. package/src/components/Swap/SettingsView/Slippage/index.tsx +57 -49
  35. package/src/components/Swap/SwapView/ConfirmationView/TokenTiles/index.tsx +72 -0
  36. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/Header/index.tsx +13 -25
  37. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/Steps/index.tsx +65 -113
  38. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/index.tsx +19 -23
  39. package/src/components/Swap/SwapView/ConfirmationView/TxResult/index.tsx +47 -69
  40. package/src/components/Swap/SwapView/FeesPanel/Fees/index.tsx +1 -1
  41. package/src/components/Swap/SwapView/FeesPanel/index.tsx +6 -4
  42. package/src/components/Swap/SwapView/SwapButton/index.tsx +0 -29
  43. package/src/components/Swap/SwapView/SwapPanel/AmountPanel/index.tsx +11 -2
  44. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/ChainPicker/index.tsx +4 -4
  45. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/NetworkFilter/index.tsx +62 -51
  46. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/TokenItem/index.tsx +1 -1
  47. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/index.tsx +94 -43
  48. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/index.tsx +27 -5
  49. package/src/components/Swap/SwapView/SwapPanel/UsdValue/index.tsx +2 -2
  50. package/src/components/Swap/SwapView/SwapPanel/WalletPanel/index.tsx +23 -18
  51. package/src/components/Swap/SwapView/SwapPanel/index.tsx +17 -5
  52. package/src/components/Swap/SwapView/WalletPicker/index.tsx +131 -139
  53. package/src/components/Swap/SwapView/index.tsx +11 -7
  54. package/src/components/Swap/WalletPickerView/index.tsx +65 -0
  55. package/src/components/Swap/index.tsx +23 -6
  56. package/src/components/ToggleButton/index.tsx +6 -6
  57. package/src/components/TokenLogo/index.tsx +1 -1
  58. package/src/components/TxModal/index.tsx +13 -7
  59. package/src/components/global.css +103 -1
  60. package/src/config/fonts.ts +15 -2
  61. package/src/constants/index.ts +4 -0
  62. package/src/context/SwapProvider.tsx +106 -19
  63. package/src/context/TxUIWrapper.tsx +0 -1
  64. package/src/utils/validation.ts +9 -4
  65. package/tailwind.config.js +3 -9
  66. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/ArrowIcon.tsx +0 -13
  67. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/SwapPanel/index.tsx +0 -72
  68. package/src/components/Swap/SwapView/ConfirmationView/TxResult/TokenItem/index.tsx +0 -25
@@ -1,14 +1,9 @@
1
1
  import {
2
- faArrowUpRightFromSquare,
3
- faChevronRight,
4
- } from "@fortawesome/free-solid-svg-icons";
5
- import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
6
- import {
7
- Spinner,
8
- Timer,
9
- TimerDisplayFormat,
10
- TokenLogo,
11
- } from "@src/components";
2
+ ChevronRightThinIcon,
3
+ LinkExternalThinIcon,
4
+ LoadingRingIcon,
5
+ } from "@src/assets/icons";
6
+ import { Timer, TimerDisplayFormat, TokenLogoWithChain } from "@src/components";
12
7
  import { CCIP_EXPLORER } from "@src/constants";
13
8
  import { useSwapContext } from "@src/context";
14
9
  import { useWallet } from "@src/context/WalletProvider";
@@ -54,16 +49,12 @@ export const ActivityCard = ({ transaction }: Props) => {
54
49
  (chain) => chain.chainId === transaction.targetChainId,
55
50
  );
56
51
 
57
- const date = format(
58
- new Date(transaction.timestamp * 1000),
59
- "dd.MM.yyyy · hh.mmaa",
60
- );
52
+ const txDate = new Date(transaction.timestamp * 1000);
53
+ const date = format(txDate, "dd.MM.yyyy");
54
+ const time = format(txDate, "hh.mmaa");
61
55
 
62
56
  const receivedToken = dstToken || srcToken;
63
57
 
64
- const amountToken =
65
- transaction.tokenOutAmount && dstToken ? dstToken : srcToken;
66
-
67
58
  const amount = useMemo(() => {
68
59
  if (transaction.tokenOutAmount && dstToken) {
69
60
  return weiToHumanReadable({
@@ -98,112 +89,116 @@ export const ActivityCard = ({ transaction }: Props) => {
98
89
  )?.transactionExplorer
99
90
  }/${transaction.hash}`;
100
91
 
92
+ const destinationChain = dstChain || srcChain;
93
+
101
94
  return (
102
- <div className="flex flex-col gap-px pb-2">
103
- <div className="flex items-center justify-between gap-2 px-4 py-2 rounded-t-xl bg-t_bg_tertiary bg-opacity-5">
104
- <p className="text-xs leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-50 whitespace-nowrap">
105
- {date}
106
- </p>
107
- <div className="flex items-center gap-2">
108
- {transaction.status === "IN_PROGRESS" ? (
109
- <div className="flex items-center gap-1.5 px-2 py-1 rounded-md bg-t_warning_dark bg-opacity-10 text-t_text_orange">
110
- <Spinner className="w-3 h-3" />
111
- <p className="text-xs leading-[18px] whitespace-nowrap">
112
- {`Est. Time `}
113
- <Timer
114
- displayFormat={TimerDisplayFormat.Minutes}
115
- expiryTimestamp={
116
- new Date(transaction.estimatedDeliveryTimestamp)
117
- }
118
- customTextOnExpire="finalizing"
119
- />
120
- </p>
121
- </div>
122
- ) : transaction.status === "DONE" ? (
123
- <p className="text-xs leading-[18px] text-t_text_green px-2 py-1">
124
- Done
125
- </p>
126
- ) : transaction.status === "REVERTED" ? (
127
- <p className="text-xs leading-[18px] text-t_text_red px-2 py-1">
128
- Reverted
129
- </p>
130
- ) : null}
131
- <a
132
- href={explorerUrl}
133
- target="_blank"
134
- rel="noreferrer"
135
- className="flex items-center justify-center w-6 h-6 rounded-md bg-t_bg_tertiary bg-opacity-5 no-underline text-t_text_primary hover:bg-opacity-10 transition-colors"
136
- aria-label="Show the transaction in the chain explorer"
137
- >
138
- <FontAwesomeIcon
139
- icon={faArrowUpRightFromSquare}
140
- className="w-3 h-3 opacity-70"
141
- />
142
- </a>
95
+ <div className="pb-2">
96
+ <div className="flex flex-col gap-4 p-4 rounded-2xl bg-t_bg_tertiary bg-opacity-[0.03]">
97
+ <div className="flex items-center justify-between gap-2">
98
+ <div className="flex items-center gap-2 px-3 py-2 rounded-md bg-t_bg_tertiary bg-opacity-[0.03]">
99
+ <span className="text-xs leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-50 whitespace-nowrap">
100
+ {date}
101
+ </span>
102
+ <span className="w-0.5 h-0.5 shrink-0 bg-t_text_primary opacity-25" />
103
+ <span className="text-xs leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-50 whitespace-nowrap">
104
+ {time}
105
+ </span>
106
+ </div>
107
+ <div className="flex items-center gap-2">
108
+ {transaction.status === "IN_PROGRESS" ? (
109
+ <div className="flex items-center gap-2 px-3 py-2 rounded-md bg-t_text_orange bg-opacity-[0.07] text-t_text_orange">
110
+ <LoadingRingIcon className="w-4 h-4 shrink-0 animate-spin" />
111
+ <p className="text-xs leading-[18px] whitespace-nowrap">
112
+ {`Est. Time `}
113
+ <Timer
114
+ displayFormat={TimerDisplayFormat.Minutes}
115
+ expiryTimestamp={
116
+ new Date(transaction.estimatedDeliveryTimestamp)
117
+ }
118
+ customTextOnExpire="- finalizing"
119
+ />
120
+ </p>
121
+ </div>
122
+ ) : transaction.status === "DONE" ? (
123
+ <div className="flex items-center px-3 py-2 rounded-md bg-t_text_green bg-opacity-5">
124
+ <p className="text-xs leading-[18px] whitespace-nowrap text-t_text_green text-opacity-80">
125
+ Done
126
+ </p>
127
+ </div>
128
+ ) : transaction.status === "REVERTED" ? (
129
+ <div className="flex items-center px-3 py-2 rounded-md bg-t_bg_tertiary bg-opacity-[0.03]">
130
+ <p className="text-xs leading-[18px] whitespace-nowrap text-t_text_primary text-opacity-50">
131
+ Reverted
132
+ </p>
133
+ </div>
134
+ ) : null}
135
+ <a
136
+ href={explorerUrl}
137
+ target="_blank"
138
+ rel="noreferrer"
139
+ className="flex items-center justify-center w-[34px] h-[34px] shrink-0 rounded-md bg-t_bg_tertiary bg-opacity-5 no-underline text-t_text_primary hover:bg-opacity-10 transition-colors"
140
+ aria-label="Show the transaction in the chain explorer"
141
+ >
142
+ <LinkExternalThinIcon className="w-3 h-3 opacity-50" />
143
+ </a>
144
+ </div>
143
145
  </div>
144
- </div>
145
- <div className="flex items-center gap-3 px-4 py-3 rounded-b-xl bg-t_bg_tertiary bg-opacity-[0.03]">
146
- <div className="flex items-center shrink-0">
147
- {dstToken && (
148
- <div className="flex items-end -mr-2">
149
- <TokenLogo
150
- token={srcToken}
151
- className="min-w-[38px] w-[38px] h-[38px] -mr-2.5"
152
- generatedLogoClassName="min-w-[38px] w-[38px] h-[38px] text-[15px] -mr-2.5"
153
- />
154
- {srcChain && (
155
- <img
156
- src={srcChain.image}
157
- alt={srcChain.name}
158
- className="w-4 h-4 shrink-0 border border-solid border-t_bg_secondary rounded-full"
146
+ <div className="flex items-center gap-3">
147
+ <div className="flex items-center shrink-0">
148
+ {dstToken && (
149
+ <div className="-mr-2">
150
+ <TokenLogoWithChain
151
+ token={srcToken}
152
+ chain={srcChain}
153
+ tokenLogoClassName="min-w-10 w-10 h-10 border border-solid border-t_bg_secondary"
154
+ generatedLogoClassName="min-w-10 w-10 h-10 text-[16px] border border-solid border-t_bg_secondary"
155
+ chainLogoClassName="w-[18px]"
159
156
  />
160
- )}
161
- </div>
162
- )}
163
- <div className="flex items-end">
164
- <TokenLogo
157
+ </div>
158
+ )}
159
+ <TokenLogoWithChain
165
160
  token={receivedToken}
166
- className="min-w-[38px] w-[38px] h-[38px] -mr-2.5"
167
- generatedLogoClassName="min-w-[38px] w-[38px] h-[38px] text-[15px] -mr-2.5"
161
+ chain={dstChain}
162
+ tokenLogoClassName="min-w-10 w-10 h-10 border border-solid border-t_bg_secondary"
163
+ generatedLogoClassName="min-w-10 w-10 h-10 text-[16px] border border-solid border-t_bg_secondary"
164
+ chainLogoClassName="w-[18px]"
168
165
  />
169
- {dstChain && (
170
- <img
171
- src={dstChain.image}
172
- alt={dstChain.name}
173
- className="w-4 h-4 shrink-0 border border-solid border-t_bg_secondary rounded-full"
174
- />
175
- )}
176
166
  </div>
177
- </div>
178
- <div className="flex justify-between items-center gap-2 w-full min-w-0">
179
- <div className="text-left min-w-0">
180
- <div className="flex items-center gap-1.5 text-sm font-medium leading-5 tracking-[0.01em] text-t_text_primary">
181
- <span>{srcToken?.symbol || "?"}</span>
182
- {dstToken && (
183
- <>
184
- <FontAwesomeIcon
185
- icon={faChevronRight}
186
- className="w-2.5 h-2.5 opacity-50"
187
- />
188
- <span>{dstToken.symbol}</span>
189
- </>
190
- )}
191
- </div>
192
- <div className="flex gap-2 items-center text-xs leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-50">
193
- <span className="whitespace-nowrap truncate">
194
- {`Receiver ${receiverAddress ? shortAddress(receiverAddress) : "-"}`}
195
- </span>
196
- </div>
197
- </div>
198
- <div className="text-right shrink-0">
199
- <div className="text-sm font-medium leading-5 tracking-[0.01em] text-t_text_primary">
200
- {amountToken ? `${amount} ${amountToken.symbol}` : amount}
167
+ <div className="flex justify-between items-center gap-2 w-full min-w-0">
168
+ <div className="flex flex-col gap-0.5 text-left min-w-0">
169
+ <div className="flex items-center gap-2 text-sm font-medium leading-5 tracking-[0.01em] text-t_text_primary">
170
+ <span>{srcToken?.symbol || "?"}</span>
171
+ {dstToken && (
172
+ <>
173
+ <ChevronRightThinIcon className="shrink-0 opacity-50" />
174
+ <span className="truncate">{dstToken.symbol}</span>
175
+ </>
176
+ )}
177
+ </div>
178
+ <div className="flex items-center gap-2 text-xs leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-50 min-w-0">
179
+ {destinationChain && (
180
+ <>
181
+ <span className="whitespace-nowrap truncate">
182
+ {`Destination ${destinationChain.displayName || destinationChain.name}`}
183
+ </span>
184
+ <span className="w-0.5 h-0.5 shrink-0 bg-t_text_primary opacity-25" />
185
+ </>
186
+ )}
187
+ <span className="whitespace-nowrap">
188
+ {receiverAddress ? shortAddress(receiverAddress) : "-"}
189
+ </span>
190
+ </div>
201
191
  </div>
202
- {amountUsd && (
203
- <div className="text-xs leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-50">
204
- {`${amountUsd} USD`}
192
+ <div className="flex flex-col gap-0.5 text-right shrink-0">
193
+ <div className="text-sm font-medium leading-5 tracking-[0.01em] text-t_text_primary">
194
+ {amount}
205
195
  </div>
206
- )}
196
+ {amountUsd && (
197
+ <div className="text-xs leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-50">
198
+ {`${amountUsd} USD`}
199
+ </div>
200
+ )}
201
+ </div>
207
202
  </div>
208
203
  </div>
209
204
  </div>
@@ -56,13 +56,16 @@ export const HistoryView = () => {
56
56
  }
57
57
 
58
58
  return (
59
- <Virtuoso
60
- data={unifiedHistory}
61
- style={{ height: "424px" }}
62
- itemContent={(_, transaction) => {
63
- return <ActivityCard transaction={transaction} />;
64
- }}
65
- />
59
+ <div className="relative h-full">
60
+ <Virtuoso
61
+ data={unifiedHistory}
62
+ style={{ height: "100%" }}
63
+ itemContent={(_, transaction) => {
64
+ return <ActivityCard transaction={transaction} />;
65
+ }}
66
+ />
67
+ <div className="pointer-events-none absolute bottom-0 inset-x-0 h-16 bg-gradient-to-t from-t_bg_primary/[0.65] to-transparent" />
68
+ </div>
66
69
  );
67
70
  }, [
68
71
  historyLoadedOnce,
@@ -1,4 +1,4 @@
1
- import { CaretsUpDownIcon } from "@src/assets/icons";
1
+ import { ChevronsUpDownThinIcon } from "@src/assets/icons";
2
2
  import { useSwapContext } from "@src/context";
3
3
  import { FC } from "react";
4
4
 
@@ -23,13 +23,16 @@ export const ReorderButton: FC = () => {
23
23
 
24
24
  return (
25
25
  <div className="h-0 w-full relative z-[1]">
26
+ {/* Opaque bg on purpose: Chromium ignores backdrop-filter nested
27
+ inside the widget's own backdrop-blur, so a translucent bg would
28
+ let the panel edges show through the button. */}
26
29
  <button
27
30
  onClick={onReorderClick}
28
31
  aria-label="Switch target token with the source token"
29
- className="absolute left-1/2 -translate-x-1/2 -translate-y-1/2 flex items-center justify-center w-8 h-8 rounded-md bg-t_bg_secondary border border-solid border-t_text_primary border-opacity-10 hover:border-opacity-25 transition-colors"
32
+ className="absolute left-1/2 -translate-x-1/2 -translate-y-1/2 flex items-center justify-center w-8 h-8 rounded-md backdrop-blur-[24px] bg-t_bg_secondary bg-gradient-to-r from-t_bg_tertiary/5 to-t_bg_tertiary/5 hover:from-t_bg_tertiary/10 hover:to-t_bg_tertiary/10 transition-colors"
30
33
  >
31
- <div className="flex fill-t_text_primary opacity-75 [&_svg]:w-2.5 [&_svg]:h-4">
32
- <CaretsUpDownIcon />
34
+ <div className="flex text-t_text_primary opacity-50">
35
+ <ChevronsUpDownThinIcon />
33
36
  </div>
34
37
  </button>
35
38
  </div>
@@ -1,4 +1,4 @@
1
- import { HelpIcon } from "@src/assets/icons";
1
+ import { InfoThinIcon } from "@src/assets/icons";
2
2
  import { ToggleButton, Tooltip } from "@src/components";
3
3
  import { useSwapContext } from "@src/context";
4
4
  import { useRef } from "react";
@@ -8,27 +8,29 @@ export const Delivery = () => {
8
8
  const { expressDelivery, setExpressDelivery } = useSwapContext();
9
9
 
10
10
  return (
11
- <div className="flex gap-2 items-center justify-between p-4 rounded-xl bg-gradient-to-r from-t_bg_tertiary/[0.02] to-t_bg_tertiary/[0.01]">
12
- <div className="flex items-center gap-3 min-w-0">
11
+ <div className="flex gap-2 items-center justify-between py-4 px-6 rounded-xl bg-gradient-to-r from-t_bg_tertiary/[0.03] to-t_bg_tertiary/[0.01]">
12
+ <div className="flex items-center gap-2 min-w-0">
13
13
  <h2 className="text-sm leading-6 tracking-[0.01em] text-t_text_primary whitespace-nowrap">
14
14
  Fast Delivery
15
15
  </h2>
16
16
  <div className="w-0.5 h-0.5 bg-t_text_primary opacity-25 shrink-0" />
17
- <p className="text-sm leading-6 tracking-[0.01em] text-t_text_primary text-opacity-50 whitespace-nowrap truncate">
18
- {expressDelivery ? "Est. Time 30 Sec." : "Est. Time 30 Min."}
19
- </p>
20
- <Tooltip
21
- text={
22
- "Fast Delivery is a special feature of XSwap that reduces transaction time across chains to around 30 seconds. It is currently available for swaps below a value of $1000 USD."
23
- }
24
- position="BOTTOM"
25
- triggerRef={tooltipTriggerRef}
26
- id="express-delivery-tooltip"
27
- />
28
- <HelpIcon
29
- ref={tooltipTriggerRef}
30
- className="cursor-help fill-t_text_primary opacity-30 w-4 h-4 shrink-0"
31
- />
17
+ <div className="flex items-center gap-1.5 min-w-0">
18
+ <p className="text-sm leading-6 tracking-[0.01em] text-t_text_primary text-opacity-50 whitespace-nowrap truncate">
19
+ {expressDelivery ? "Est. Time 30 Sec." : "Est. Time 30 Min."}
20
+ </p>
21
+ <Tooltip
22
+ text={
23
+ "Fast Delivery is a special feature of XSwap that reduces transaction time across chains to around 30 seconds. It is currently available for swaps below a value of $1000 USD."
24
+ }
25
+ position="BOTTOM"
26
+ triggerRef={tooltipTriggerRef}
27
+ id="express-delivery-tooltip"
28
+ />
29
+ <InfoThinIcon
30
+ ref={tooltipTriggerRef}
31
+ className="cursor-help text-t_text_primary w-4 h-4 shrink-0"
32
+ />
33
+ </div>
32
34
  </div>
33
35
  <ToggleButton
34
36
  checked={expressDelivery}
@@ -1,4 +1,4 @@
1
- import { HelpIcon } from "@src/assets/icons";
1
+ import { InfoThinIcon } from "@src/assets/icons";
2
2
  import { ToggleButton } from "@src/components/ToggleButton";
3
3
  import { Tooltip } from "@src/components/Tooltip";
4
4
  import { useSwapContext } from "@src/context";
@@ -9,27 +9,29 @@ export const InfiniteApproval = () => {
9
9
  const { infiniteApproval, setInfiniteApproval } = useSwapContext();
10
10
 
11
11
  return (
12
- <div className="flex gap-2 items-center justify-between p-4 rounded-xl bg-gradient-to-r from-t_bg_tertiary/[0.02] to-t_bg_tertiary/[0.01]">
13
- <div className="flex items-center gap-3 min-w-0">
12
+ <div className="flex gap-2 items-center justify-between py-4 px-6 rounded-xl bg-gradient-to-r from-t_bg_tertiary/[0.03] to-t_bg_tertiary/[0.01]">
13
+ <div className="flex items-center gap-2 min-w-0">
14
14
  <h2 className="text-sm leading-6 tracking-[0.01em] text-t_text_primary whitespace-nowrap">
15
15
  Persistent Access
16
16
  </h2>
17
17
  <div className="w-0.5 h-0.5 bg-t_text_primary opacity-25 shrink-0" />
18
- <p className="text-sm leading-6 tracking-[0.01em] text-t_text_primary text-opacity-50 whitespace-nowrap truncate">
19
- Don't Ask Every Tx.
20
- </p>
21
- <Tooltip
22
- text={
23
- "Enabling persistent access (infinite approval) allows to access your tokens without requiring repeated approvals for each transaction. This streamlines multiple transactions but may pose a security risk if the spender's address is compromised."
24
- }
25
- position="BOTTOM"
26
- triggerRef={tooltipTriggerRef}
27
- id="infinite-approval-tooltip"
28
- />
29
- <HelpIcon
30
- ref={tooltipTriggerRef}
31
- className="cursor-help fill-t_text_primary opacity-30 w-4 h-4 shrink-0"
32
- />
18
+ <div className="flex items-center gap-1.5 min-w-0">
19
+ <p className="text-sm leading-6 tracking-[0.01em] text-t_text_primary text-opacity-50 whitespace-nowrap truncate">
20
+ Don't Ask Every Tx.
21
+ </p>
22
+ <Tooltip
23
+ text={
24
+ "Enabling persistent access (infinite approval) allows to access your tokens without requiring repeated approvals for each transaction. This streamlines multiple transactions but may pose a security risk if the spender's address is compromised."
25
+ }
26
+ position="BOTTOM"
27
+ triggerRef={tooltipTriggerRef}
28
+ id="infinite-approval-tooltip"
29
+ />
30
+ <InfoThinIcon
31
+ ref={tooltipTriggerRef}
32
+ className="cursor-help text-t_text_primary w-4 h-4 shrink-0"
33
+ />
34
+ </div>
33
35
  </div>
34
36
  <ToggleButton
35
37
  checked={infiniteApproval}
@@ -27,59 +27,67 @@ export const Slippage = () => {
27
27
  };
28
28
 
29
29
  return (
30
- <div className="flex flex-col gap-5 p-4 rounded-xl bg-gradient-to-b from-t_bg_tertiary/[0.02] to-t_bg_tertiary/0">
31
- <div className="flex items-center gap-2">
32
- <h2 className="text-sm leading-5 tracking-[0.01em] text-t_text_primary">
33
- Price Tolerance
34
- </h2>
35
- <div className="w-0.5 h-0.5 bg-t_text_primary opacity-25 shrink-0" />
36
- <p className="text-sm leading-5 tracking-[0.01em] text-t_text_primary text-opacity-50">
37
- {`${Number(slippage).toFixed(2)}%`}
38
- </p>
39
- </div>
40
- <div className="flex items-center gap-4 w-full">
41
- <div className="flex items-center justify-between flex-1 gap-3 p-3 rounded-[10px] bg-t_bg_tertiary bg-opacity-5 border border-solid border-t_text_primary border-opacity-25">
42
- <div className="flex items-center gap-3 min-w-0 flex-1">
43
- <div className="flex items-center justify-center w-6 h-6 rounded bg-t_bg_tertiary bg-opacity-5 shrink-0">
44
- <AdjustmentsIcon className="w-3.5 h-3.5 text-t_text_primary opacity-70" />
30
+ <div className="flex flex-col gap-6 py-4 px-6 rounded-xl bg-gradient-to-r from-t_bg_tertiary/[0.03] to-t_bg_tertiary/[0.01]">
31
+ <div className="flex flex-col gap-4">
32
+ <div className="flex items-center gap-2">
33
+ <h2 className="text-sm leading-6 tracking-[0.01em] text-t_text_primary">
34
+ Slippage
35
+ </h2>
36
+ <div className="w-0.5 h-0.5 bg-t_text_primary opacity-25 shrink-0" />
37
+ <p className="text-sm leading-6 tracking-[0.01em] text-t_text_primary text-opacity-50">
38
+ {`${Number(slippage).toFixed(2)}%`}
39
+ </p>
40
+ </div>
41
+ <div className="flex items-center gap-4 w-full">
42
+ <div className="flex items-center justify-between flex-1 h-12 gap-3 p-3 rounded-[10px] bg-gradient-to-r from-t_bg_tertiary/[0.02] to-t_bg_tertiary/[0.02] bg-[rgba(40,40,40,0.15)] border border-solid border-t_text_primary border-opacity-5">
43
+ <div className="flex items-center gap-3 min-w-0 flex-1">
44
+ <div className="flex items-center justify-center w-6 h-6 rounded bg-t_bg_tertiary bg-opacity-5 shrink-0">
45
+ <AdjustmentsIcon className="w-3.5 h-3.5 text-t_text_primary" />
46
+ </div>
47
+ <SafeInput
48
+ id="slippage-input"
49
+ placeholder="0.00"
50
+ regex={NUMBER_INPUT_REGEX}
51
+ value={customSlippage}
52
+ onChange={onInputChange}
53
+ className="text-sm leading-6 bg-transparent border-none px-0 w-full min-w-0 placeholder:text-t_text_primary placeholder:text-opacity-50 focus:outline-none text-t_text_primary"
54
+ />
45
55
  </div>
46
- <SafeInput
47
- id="slippage-input"
48
- placeholder="0.00"
49
- regex={NUMBER_INPUT_REGEX}
50
- value={customSlippage}
51
- onChange={onInputChange}
52
- className="text-sm leading-6 bg-transparent border-none px-0 w-full min-w-0 placeholder:text-t_text_primary placeholder:text-opacity-50 focus:outline-none text-t_text_primary"
53
- />
56
+ <span className="text-sm leading-6 text-t_text_primary text-opacity-50 shrink-0">
57
+ %
58
+ </span>
59
+ </div>
60
+ <div className="w-0.5 h-0.5 bg-t_text_primary opacity-25 shrink-0 hidden sm:block" />
61
+ <div className="flex items-center gap-2">
62
+ {presets.map((preset) => (
63
+ <button
64
+ key={preset}
65
+ type="button"
66
+ onClick={() => onInputChange(preset)}
67
+ className={`w-14 sm:w-[72px] h-12 px-3 rounded-[10px] text-sm leading-6 text-center transition-colors ${
68
+ slippage === preset
69
+ ? "border border-solid border-t_main_accent_light/60 bg-gradient-to-r from-t_main_accent_light/10 to-t_main_accent_dark/10 text-t_text_primary"
70
+ : "bg-t_bg_tertiary bg-opacity-[0.04] text-t_text_primary text-opacity-60 hover:bg-opacity-10"
71
+ }`}
72
+ >
73
+ {`${preset}%`}
74
+ </button>
75
+ ))}
54
76
  </div>
55
- <span className="text-sm leading-6 text-t_text_primary text-opacity-50 shrink-0">
56
- %
57
- </span>
58
- </div>
59
- <div className="w-0.5 h-0.5 bg-t_text_primary opacity-25 shrink-0 hidden sm:block" />
60
- <div className="flex items-center gap-2">
61
- {presets.map((preset) => (
62
- <button
63
- key={preset}
64
- type="button"
65
- onClick={() => onInputChange(preset)}
66
- className={`w-14 sm:w-[72px] px-3 py-2.5 rounded-lg text-sm leading-5 tracking-[0.06em] text-center transition-colors ${
67
- slippage === preset
68
- ? "bg-gradient-to-r from-t_main_accent_light/40 to-t_main_accent_dark/60 text-t_text_primary"
69
- : "bg-t_bg_tertiary bg-opacity-5 text-t_text_primary text-opacity-75 hover:bg-opacity-10"
70
- }`}
71
- >
72
- {`${preset}%`}
73
- </button>
74
- ))}
75
77
  </div>
76
78
  </div>
77
- <p className="text-sm leading-5 tracking-[0.01em] text-t_text_primary text-opacity-40">
78
- <span className="font-medium">Price Tolerance</span>
79
- {` defines how much a price can change before your transfer falls back
80
- to USDC. If the price moves more than your tolerance allows, you'll
81
- receive USDC on your destination chain.`}
82
- </p>
79
+ <div className="flex flex-col gap-3">
80
+ <p className="text-[10px] leading-4 tracking-[0.015em] text-t_text_primary text-opacity-30">
81
+ NOTE.
82
+ </p>
83
+ <p className="text-sm leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-40">
84
+ {/* The design sets the leading term in Medium, the rest Regular. */}
85
+ <span className="font-medium">Slippage</span>
86
+ {` defines how much a price can change before your
87
+ transfer falls back to USDC. If the price moves more than your
88
+ tolerance allows, you'll receive USDC on your destination chain.`}
89
+ </p>
90
+ </div>
83
91
  </div>
84
92
  );
85
93
  };
@@ -0,0 +1,72 @@
1
+ import { ChevronDownWideThinIcon } from "@src/assets/icons";
2
+ import { TokenLogoWithChain } from "@src/components";
3
+ import { useSwapContext } from "@src/context";
4
+ import { Ecosystem } from "@src/models";
5
+ import { useMemo } from "react";
6
+ import { SwapPanelType } from "../../index";
7
+
8
+ const TokenTile = ({ type }: { type: SwapPanelType }) => {
9
+ const {
10
+ srcToken,
11
+ srcChain,
12
+ dstToken,
13
+ dstChain,
14
+ srcValue,
15
+ dstValue,
16
+ bridgeUI,
17
+ } = useSwapContext();
18
+
19
+ const token = type === "source" ? srcToken : dstToken;
20
+ const chain = type === "source" ? srcChain : dstChain;
21
+
22
+ const value = useMemo(() => {
23
+ if (
24
+ type === "destination" &&
25
+ bridgeUI &&
26
+ srcChain?.ecosystem === Ecosystem.SOLANA
27
+ ) {
28
+ return srcValue;
29
+ }
30
+ return type === "source" ? srcValue : dstValue;
31
+ }, [type, bridgeUI, srcChain?.ecosystem, srcValue, dstValue]);
32
+
33
+ return (
34
+ <div className="flex items-center justify-between gap-4 h-[72px] px-4 sm:px-6 rounded-xl backdrop-blur-[12px] bg-t_bg_tertiary bg-opacity-5">
35
+ <div className="text-2xl leading-6 text-t_text_primary opacity-50 truncate min-w-0">
36
+ {value}
37
+ </div>
38
+ <div className="flex items-center gap-3 shrink-0">
39
+ <p className="text-sm font-medium leading-6 tracking-[0.01em] text-t_text_primary">
40
+ {token?.symbol}
41
+ </p>
42
+ <TokenLogoWithChain
43
+ token={token}
44
+ chain={chain}
45
+ tokenLogoClassName="w-10 h-10"
46
+ generatedLogoClassName="w-10 h-10 text-[16px]"
47
+ chainLogoClassName="w-[18px]"
48
+ />
49
+ </div>
50
+ </div>
51
+ );
52
+ };
53
+
54
+ /** Source and destination amounts of the pending swap as two stacked tiles
55
+ * with a decorative direction marker between them. */
56
+ export const TokenTiles = () => {
57
+ return (
58
+ <div className="flex flex-col gap-1.5">
59
+ <TokenTile type="source" />
60
+ {/* Zero-height anchor between the tiles, like ReorderButton in SwapView.
61
+ Opaque bg on purpose: Chromium ignores backdrop-filter nested inside
62
+ the widget's own backdrop-blur, so a translucent bg would let the
63
+ tile edges show through the marker. */}
64
+ <div className="h-0 w-full relative z-[1]">
65
+ <div className="absolute left-1/2 -translate-x-1/2 -translate-y-1/2 flex items-center justify-center w-8 h-8 rounded-md backdrop-blur-[24px] bg-t_bg_secondary bg-gradient-to-b from-t_bg_tertiary/10 to-t_bg_tertiary/[0.08]">
66
+ <ChevronDownWideThinIcon className="w-6 h-6 text-t_text_primary opacity-50" />
67
+ </div>
68
+ </div>
69
+ <TokenTile type="destination" />
70
+ </div>
71
+ );
72
+ };