@xswap-link/sdk 0.13.0 → 0.14.0

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 (61) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/index.d.mts +6 -2
  3. package/dist/index.d.ts +6 -2
  4. package/dist/index.global.js +90 -89
  5. package/dist/index.js +1633 -1519
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +1597 -1480
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +1 -1
  10. package/src/assets/icons/AdjustmentsIcon.tsx +18 -0
  11. package/src/assets/icons/CaretDownIcon.tsx +12 -0
  12. package/src/assets/icons/CaretsUpDownIcon.tsx +13 -0
  13. package/src/assets/icons/ChainlinkMarkIcon.tsx +17 -0
  14. package/src/assets/icons/ClockIcon.tsx +18 -0
  15. package/src/assets/icons/WarningIcon.tsx +16 -0
  16. package/src/assets/icons/index.ts +6 -0
  17. package/src/components/Modal/index.tsx +2 -2
  18. package/src/components/PoweredBy/index.tsx +14 -5
  19. package/src/components/Swap/Header/Controls/index.tsx +50 -36
  20. package/src/components/Swap/Header/index.tsx +12 -5
  21. package/src/components/Swap/HistoryView/ActivityCard/index.tsx +212 -0
  22. package/src/components/Swap/HistoryView/index.tsx +24 -6
  23. package/src/components/Swap/ReorderButton/ReorderButton.tsx +5 -7
  24. package/src/components/Swap/SettingsView/Delivery/index.tsx +27 -28
  25. package/src/components/Swap/SettingsView/InfiniteApproval/index.tsx +27 -24
  26. package/src/components/Swap/SettingsView/Slippage/index.tsx +44 -43
  27. package/src/components/Swap/SettingsView/index.tsx +1 -1
  28. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/index.tsx +2 -2
  29. package/src/components/Swap/SwapView/FeesPanel/DeliveryInfo/index.tsx +9 -19
  30. package/src/components/Swap/SwapView/FeesPanel/Fee/index.tsx +4 -4
  31. package/src/components/Swap/SwapView/FeesPanel/Fees/index.tsx +5 -9
  32. package/src/components/Swap/SwapView/FeesPanel/index.tsx +21 -22
  33. package/src/components/Swap/SwapView/SwapButton/index.tsx +25 -6
  34. package/src/components/Swap/SwapView/SwapPanel/AmountPanel/Balance/index.tsx +56 -12
  35. package/src/components/Swap/SwapView/SwapPanel/AmountPanel/index.tsx +42 -41
  36. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/NetworkFilter/index.tsx +157 -0
  37. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/TokenItem/index.tsx +98 -55
  38. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/index.tsx +160 -239
  39. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/index.tsx +57 -31
  40. package/src/components/Swap/SwapView/SwapPanel/UsdValue/index.tsx +27 -0
  41. package/src/components/Swap/SwapView/SwapPanel/WalletPanel/index.tsx +60 -49
  42. package/src/components/Swap/SwapView/SwapPanel/index.tsx +20 -25
  43. package/src/components/Swap/SwapView/WalletPicker/index.tsx +6 -1
  44. package/src/components/Swap/SwapView/index.tsx +2 -1
  45. package/src/components/Swap/index.tsx +4 -2
  46. package/src/components/ToggleButton/index.tsx +18 -15
  47. package/src/components/TxConfigForm/index.tsx +5 -5
  48. package/src/components/TxWidgetWC/index.tsx +4 -0
  49. package/src/components/TxWidgetWCWrapped/index.tsx +2 -0
  50. package/src/context/HistoryProvider.tsx +1 -0
  51. package/src/context/SwapProvider.tsx +94 -67
  52. package/src/models/TransactionHistory.ts +1 -0
  53. package/src/models/payloads/ModalIntegrationPayload.ts +1 -0
  54. package/src/models/payloads/WidgetIntegrationPayload.ts +1 -0
  55. package/src/utils/index.ts +21 -0
  56. package/tailwind.config.js +2 -2
  57. package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/ChainItem/index.tsx +0 -97
  58. package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/index.tsx +0 -103
  59. package/src/components/Swap/SwapView/SwapPanel/ChainPanel/index.tsx +0 -65
  60. package/src/components/Swap/SwapView/SwapPanel/MaxPanel/index.tsx +0 -43
  61. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/QuickPickTokenItem/index.tsx +0 -37
@@ -8,35 +8,34 @@ export const Delivery = () => {
8
8
  const { expressDelivery, setExpressDelivery } = useSwapContext();
9
9
 
10
10
  return (
11
- <div className="flex flex-col gap-5 pt-5 border-t border-solid border-t_text_primary border-opacity-10">
12
- <h1 className="text-sm font-medium text-left">Delivery</h1>
13
- <div className="flex gap-2 items-center justify-between flex-wrap">
14
- <div className="flex items-center">
15
- <h2 className="text-xs">Express delivery: </h2>
16
- <ToggleButton
17
- checked={expressDelivery}
18
- onClick={() => {
19
- setExpressDelivery((x) => !x);
20
- }}
21
- />
22
- <Tooltip
23
- text={
24
- "Express 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."
25
- }
26
- position="BOTTOM"
27
- triggerRef={tooltipTriggerRef}
28
- id="express-delivery-tooltip"
29
- />
30
- <HelpIcon
31
- ref={tooltipTriggerRef}
32
- className="cursor-help fill-t_main_accent_light w-[18px] h-[18px]"
33
- />
34
- </div>
35
- <div className="text-xs font-medium">
36
- <span className="text-xs font-medium opacity-60">{`Max time: `}</span>
37
- {expressDelivery ? "30 sec" : "30 min"}
38
- </div>
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">
13
+ <h2 className="text-sm leading-6 tracking-[0.01em] text-t_text_primary whitespace-nowrap">
14
+ Fast Delivery
15
+ </h2>
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 ? "Max. Time 30 Sec." : "Max. 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
+ />
39
32
  </div>
33
+ <ToggleButton
34
+ checked={expressDelivery}
35
+ onClick={() => {
36
+ setExpressDelivery((x) => !x);
37
+ }}
38
+ />
40
39
  </div>
41
40
  );
42
41
  };
@@ -9,31 +9,34 @@ export const InfiniteApproval = () => {
9
9
  const { infiniteApproval, setInfiniteApproval } = useSwapContext();
10
10
 
11
11
  return (
12
- <div className="flex flex-col gap-5 pt-5 border-t border-solid border-white border-opacity-10">
13
- <h1 className="text-sm font-medium text-left">Approval</h1>
14
- <div className="flex gap-2 items-center justify-between flex-wrap">
15
- <div className="flex items-center">
16
- <h2 className="text-xs">Infinite approval: </h2>
17
- <ToggleButton
18
- checked={infiniteApproval}
19
- onClick={() => {
20
- setInfiniteApproval((x) => !x);
21
- }}
22
- />
23
- <Tooltip
24
- text={
25
- "Enabling 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."
26
- }
27
- position="BOTTOM"
28
- triggerRef={tooltipTriggerRef}
29
- id="infinite-approval-tooltip"
30
- />
31
- <HelpIcon
32
- ref={tooltipTriggerRef}
33
- className="cursor-help fill-t_main_accent_light w-[18px] h-[18px]"
34
- />
35
- </div>
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">
14
+ <h2 className="text-sm leading-6 tracking-[0.01em] text-t_text_primary whitespace-nowrap">
15
+ Persistent Access
16
+ </h2>
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
+ />
36
33
  </div>
34
+ <ToggleButton
35
+ checked={infiniteApproval}
36
+ onClick={() => {
37
+ setInfiniteApproval((x) => !x);
38
+ }}
39
+ />
37
40
  </div>
38
41
  );
39
42
  };
@@ -1,8 +1,12 @@
1
+ import { AdjustmentsIcon } from "@src/assets/icons";
1
2
  import { SafeInput } from "@src/components";
2
3
  import { NUMBER_INPUT_REGEX } from "@src/constants";
3
4
  import { useSwapContext } from "@src/context";
4
5
  import { useState } from "react";
5
6
 
7
+ const defaultPreset = "1.5";
8
+ const presets = ["1", "2", "6"];
9
+
6
10
  export const Slippage = () => {
7
11
  const { slippage, setSlippage } = useSwapContext();
8
12
  const [customSlippage, setCustomSlippage] = useState(slippage);
@@ -22,63 +26,60 @@ export const Slippage = () => {
22
26
  }
23
27
  };
24
28
 
25
- const defaultPreset = "1.5";
26
- const presets = ["0.5", "1.5", "3.0"];
27
29
  return (
28
- <div className="flex flex-col gap-5 pt-5 border-t border-solid border-t_text_primary border-opacity-10">
29
- <h1 className="text-sm font-medium text-left">Slippage</h1>
30
- <div className="flex items-center gap-2 w-full">
31
- <div className="flex items-center bg-t_bg_tertiary bg-opacity-5 p-1 border border-solid border-t_text_primary border-opacity-10 rounded-xl gap-2">
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" />
45
+ </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
+ />
54
+ </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">
32
61
  {presets.map((preset) => (
33
62
  <button
34
63
  key={preset}
35
64
  type="button"
36
65
  onClick={() => onInputChange(preset)}
37
- className={`block rounded-lg text-sm bg-transparent h-7 px-1 hover:bg-gradient-to-r hover:from-t_main_accent_light hover:to-t_main_accent_dark hover:opacity-100 ${
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 ${
38
67
  slippage === preset
39
- ? "gradient-slippage-container-blue text-white opacity-100"
40
- : "text-t_text_primary opacity-20"
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"
41
70
  }`}
42
71
  >
43
72
  {`${preset}%`}
44
73
  </button>
45
74
  ))}
46
75
  </div>
47
- <div
48
- className={`${
49
- customSlippage
50
- ? "gradient-slippage-container-blue p-[1px] rounded-xl"
51
- : ""
52
- }`}
53
- >
54
- <div
55
- className={`bg-t_bg_primary p-1 h-full border border-solid border-t_text_primary border-opacity-10 rounded-xl`}
56
- >
57
- <SafeInput
58
- id="slippage-input"
59
- placeholder="1.5"
60
- regex={NUMBER_INPUT_REGEX}
61
- value={customSlippage}
62
- onChange={onInputChange}
63
- className={`text-sm leading-none bg-transparent px-0.5 placeholder:text-t_text_primary/20 focus:outline-none ${
64
- customSlippage ? "text-t_text_primary" : "text-white"
65
- } `}
66
- />{" "}
67
- %
68
- </div>
69
- </div>
70
- </div>
71
- <div className="text-sm opacity-60">
72
- <p>
73
- Slippage is the price variation you are willing to accept in the event
74
- that the price of the trade changes while it is processing.
75
- </p>
76
- <br />
77
- <p>
78
- If the trade fails due to too low slippage, you will receive USDC on
79
- the destination chain.
80
- </p>
81
76
  </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>
82
83
  </div>
83
84
  );
84
85
  };
@@ -4,7 +4,7 @@ import { Slippage } from "./Slippage";
4
4
 
5
5
  export const SettingsView = () => {
6
6
  return (
7
- <div className="flex flex-col gap-5 px-4">
7
+ <div className="flex flex-col gap-2">
8
8
  <Delivery />
9
9
  <InfiniteApproval />
10
10
  <Slippage />
@@ -222,7 +222,7 @@ export const TxOverview = ({ onCloseClick }: Props) => {
222
222
  handlers: {
223
223
  onSuccess: (data) => {
224
224
  setTxStatus(TxStatus.COMPLETED);
225
- refreshBalance();
225
+ refreshBalance({ forceRpc: true });
226
226
  trackTransaction(data);
227
227
  if (
228
228
  srcChain?.chainId &&
@@ -400,7 +400,7 @@ export const TxOverview = ({ onCloseClick }: Props) => {
400
400
  handlers: {
401
401
  onSuccess: () => {
402
402
  setTxStatus(TxStatus.COMPLETED);
403
- refreshBalance();
403
+ refreshBalance({ forceRpc: true });
404
404
  },
405
405
  },
406
406
  network: Ecosystem.SOLANA,
@@ -1,27 +1,17 @@
1
- import { TimerIcon } from "@src/assets/icons";
2
1
  import { useSwapContext } from "@src/context";
3
2
 
4
3
  export const DeliveryInfo = () => {
5
4
  const { isExpressDeliveryActive } = useSwapContext();
6
5
 
7
6
  return (
8
- <div className="flex items-center">
9
- <div
10
- className={`w-4 h-4 mr-1 ${
11
- isExpressDeliveryActive
12
- ? "fill-t_success_light"
13
- : "fill-t_text_primary opacity-50"
14
- } `}
15
- >
16
- <TimerIcon />
17
- </div>
18
- <span
19
- className={`text-xs font-medium sm:text-sm ${
20
- isExpressDeliveryActive ? "text-t_success_light" : "opacity-50"
21
- }`}
22
- >
23
- {isExpressDeliveryActive ? "Fast ~ 30sec " : "Normal ~ 30min"}
24
- </span>
25
- </div>
7
+ <span
8
+ className={`text-sm leading-6 tracking-[0.01em] whitespace-nowrap ${
9
+ isExpressDeliveryActive
10
+ ? "text-t_success_light"
11
+ : "text-t_text_primary opacity-50"
12
+ }`}
13
+ >
14
+ {isExpressDeliveryActive ? "Max. Time 30 Sec." : "Max. Time 30 Min."}
15
+ </span>
26
16
  );
27
17
  };
@@ -8,10 +8,10 @@ type Props = {
8
8
  export const Fee = ({ name, value }: Props) => {
9
9
  const { isFetchingRoute } = useSwapContext();
10
10
  return (
11
- <div className="flex gap-x-1 justify-between text-xs font-medium">
12
- <div className="opacity-60">{name}</div>
13
- <div>
14
- {isFetchingRoute ? <Skeleton className="w-[60px] h-full" /> : value}
11
+ <div className="flex gap-x-1 justify-between text-sm leading-6 tracking-[0.01em]">
12
+ <div className="text-t_text_primary text-opacity-50">{name}</div>
13
+ <div className="text-t_text_primary text-opacity-80">
14
+ {isFetchingRoute ? <Skeleton className="w-[60px] h-[20px]" /> : value}
15
15
  </div>
16
16
  </div>
17
17
  );
@@ -24,7 +24,7 @@ export const Fees = ({
24
24
  } ${feeToken?.symbol || ""}`,
25
25
  },
26
26
  {
27
- name: "Native Fee: ",
27
+ name: "Net. Fee: ",
28
28
  value: `${
29
29
  weiToHumanReadable({
30
30
  amount: route?.xSwapFees.xSwapFee.nativeFee || "0",
@@ -47,9 +47,9 @@ export const Fees = ({
47
47
  },
48
48
  ]
49
49
  : []),
50
- { name: "Slippage: ", value: `${slippage}%` },
50
+ { name: "Price Tolerance: ", value: `${slippage}%` },
51
51
  {
52
- name: "Min out: ",
52
+ name: "Min. Received: ",
53
53
  value: `${
54
54
  weiToHumanReadable({
55
55
  amount: route?.minAmountOut || "0",
@@ -61,12 +61,8 @@ export const Fees = ({
61
61
  ];
62
62
 
63
63
  return (
64
- <div className="border-t border-solid border-t_text_primary border-opacity-10 pt-3 mt-3">
65
- <div
66
- className={`flex flex-col gap-y-2 gap-x-10 sm:grid ${
67
- fees.length === 4 ? "sm:grid-rows-2" : "sm:grid-rows-3"
68
- } sm:grid-flow-col`}
69
- >
64
+ <div className="border-t border-solid border-t_text_primary border-opacity-10 pt-3 mt-2 mb-1">
65
+ <div className="flex flex-col gap-y-2">
70
66
  {fees.map(({ name, value }) => (
71
67
  <Fee key={name} name={name} value={value} />
72
68
  ))}
@@ -1,4 +1,4 @@
1
- import { ArrowDownIcon, TokensIcon } from "@src/assets/icons";
1
+ import { CaretDownIcon } from "@src/assets/icons";
2
2
  import { Skeleton } from "@src/components";
3
3
  import { useSwapContext } from "@src/context";
4
4
  import { safeBigNumberFrom, weiToHumanReadable } from "@src/utils";
@@ -176,38 +176,37 @@ export const FeesPanel = () => {
176
176
  isFetchingSolanaFee);
177
177
 
178
178
  return (
179
- <div className="flex flex-col x-border rounded-xl py-2 px-4 bg-t_bg_tertiary bg-opacity-5">
179
+ <div className="flex flex-col rounded-xl py-2 px-4 sm:px-6 bg-gradient-to-r from-t_bg_tertiary/[0.02] to-t_bg_tertiary/0">
180
180
  <button
181
181
  aria-label={`${expanded ? "Collapse" : "Expand"} fees panel`}
182
182
  type="button"
183
183
  onClick={() => setExpanded((e) => !e)}
184
184
  >
185
- <div className="flex justify-between">
186
- <div className="flex gap-2 items-center text-xs font-medium sm:text-sm fill-t_text_primary">
187
- <TokensIcon />
188
- <p className="opacity-60">Fee: </p>
185
+ <div className="flex justify-between items-center py-1">
186
+ <div className="flex gap-2 items-center text-sm leading-6 tracking-[0.01em]">
187
+ <p className="text-t_text_primary text-opacity-50">Fee</p>
188
+ <div className="w-0.5 h-0.5 bg-t_text_primary opacity-25" />
189
189
  {isLoading ? (
190
- <Skeleton className="w-[100px] h-full" />
190
+ <Skeleton className="w-[100px] h-[20px]" />
191
191
  ) : (
192
- <p>{`${solanaBridgeFee ? solanaBridgeFee : totalFee} ${
193
- feeToken?.symbol || ""
194
- }`}</p>
192
+ <p className="text-t_text_primary text-opacity-80">{`${
193
+ solanaBridgeFee ? solanaBridgeFee : totalFee
194
+ } ${feeToken?.symbol || ""}`}</p>
195
195
  )}
196
- </div>
197
- <div className="flex gap-2 items-center fill-t_text_primary">
198
196
  {route && !isLoading && srcChain?.chainId !== dstChain?.chainId && (
199
- <DeliveryInfo />
200
- )}
201
- {expanded ? (
202
- <div className="w-4 h-2 rotate-180">
203
- <ArrowDownIcon />
204
- </div>
205
- ) : (
206
- <div className="w-4 h-2">
207
- <ArrowDownIcon />
208
- </div>
197
+ <>
198
+ <div className="w-0.5 h-0.5 bg-t_text_primary opacity-25" />
199
+ <DeliveryInfo />
200
+ </>
209
201
  )}
210
202
  </div>
203
+ <div
204
+ className={`flex items-center justify-center w-6 h-6 fill-t_text_primary opacity-75 transition-transform [&_svg]:w-2.5 [&_svg]:h-[5px] ${
205
+ expanded ? "rotate-180" : ""
206
+ }`}
207
+ >
208
+ <CaretDownIcon />
209
+ </div>
211
210
  </div>
212
211
  {expanded && <Fees solanaBridgeFee={solanaBridgeFee} />}
213
212
  </button>
@@ -60,6 +60,7 @@ export const SwapButton = () => {
60
60
  openSuiWalletModal,
61
61
  setOpenSuiWalletModal,
62
62
  solana,
63
+ sui,
63
64
  } = useWallet();
64
65
 
65
66
  const { allowance, approve } = useERC20Token({
@@ -121,7 +122,10 @@ export const SwapButton = () => {
121
122
  };
122
123
  }
123
124
 
124
- if (srcChain?.ecosystem !== Ecosystem.SOLANA && !address) {
125
+ if (
126
+ (!srcChain || srcChain.ecosystem === Ecosystem.EVM) &&
127
+ !address
128
+ ) {
125
129
  return {
126
130
  text:
127
131
  integrationConfig.defaultWalletPicker || hasOnConnectWalletCallback
@@ -193,7 +197,20 @@ export const SwapButton = () => {
193
197
  };
194
198
  }
195
199
  if (
196
- srcChain?.ecosystem !== Ecosystem.SOLANA &&
200
+ (srcChain?.ecosystem === Ecosystem.SUI ||
201
+ dstChain?.ecosystem === Ecosystem.SUI) &&
202
+ !sui.address
203
+ ) {
204
+ return {
205
+ text: "Connect SUI Wallet",
206
+ fn: () => {
207
+ setOpenSuiWalletModal(true);
208
+ },
209
+ disabled: false,
210
+ };
211
+ }
212
+ if (
213
+ srcChain?.ecosystem === Ecosystem.EVM &&
197
214
  chainId?.toString() !== srcChainId
198
215
  ) {
199
216
  return {
@@ -256,7 +273,7 @@ export const SwapButton = () => {
256
273
  }
257
274
 
258
275
  return {
259
- text: bridgeUI ? "Bridge" : "Swap",
276
+ text: bridgeUI ? "Bridge Now" : "SWAP Now",
260
277
  fn: async () => {
261
278
  showSwapConfirmationView();
262
279
  },
@@ -265,7 +282,7 @@ export const SwapButton = () => {
265
282
  }, [
266
283
  isAsyncDataLoaded,
267
284
  error,
268
- srcChain?.ecosystem,
285
+ srcChain,
269
286
  dstChain?.ecosystem,
270
287
  address,
271
288
  srcChainId,
@@ -273,6 +290,8 @@ export const SwapButton = () => {
273
290
  srcTokenAddress,
274
291
  dstTokenAddress,
275
292
  solana.address,
293
+ sui.address,
294
+ setOpenSuiWalletModal,
276
295
  chainId,
277
296
  srcValueWei,
278
297
  isFetchingRoute,
@@ -323,10 +342,10 @@ export const SwapButton = () => {
323
342
  type="button"
324
343
  disabled={button.disabled}
325
344
  onClick={button.fn}
326
- className={`text-xl font-sans-bold font-bold w-full py-5 cursor-pointer disabled:cursor-not-allowed rounded-2xl border-none ${
345
+ className={`text-sm font-medium leading-6 tracking-[0.01em] w-full px-6 py-3 cursor-pointer disabled:cursor-not-allowed rounded-[10px] border-none transition-opacity ${
327
346
  button.disabled
328
347
  ? "bg-t_button_pr_off_bg text-t_button_pr_off_text"
329
- : "bg-gradient-to-r from-t_main_accent_light to-t_main_accent_dark text-t_button_pr_text"
348
+ : "bg-gradient-to-br from-t_main_accent_light to-t_main_accent_dark text-t_button_pr_text hover:opacity-90"
330
349
  }`}
331
350
  >
332
351
  {button.text}
@@ -1,21 +1,65 @@
1
1
  import { Skeleton } from "@src/components";
2
2
  import { useSwapContext } from "@src/context";
3
+ import { weiToHumanReadable } from "@src/utils";
4
+ import { useMemo } from "react";
5
+ import { SwapPanelType } from "../../../../SwapView";
3
6
 
4
- export const Balance = () => {
5
- const { srcTokenBalanceInfo, isFetchingBalance } = useSwapContext();
7
+ type Props = {
8
+ type: SwapPanelType;
9
+ };
10
+
11
+ export const Balance = ({ type }: Props) => {
12
+ const {
13
+ srcToken,
14
+ srcTokenBalanceInfo,
15
+ isFetchingBalance,
16
+ isFetchingBalances,
17
+ dstToken,
18
+ dstChain,
19
+ dstChainTokensOptions,
20
+ } = useSwapContext();
21
+
22
+ const dstTokenBalanceInfo = useMemo(() => {
23
+ if (!dstToken || !dstChain) {
24
+ return "";
25
+ }
26
+ const tokenOption = dstChainTokensOptions.find(
27
+ (token) =>
28
+ token.address.toLowerCase() === dstToken.address.toLowerCase() &&
29
+ token.chainId === dstChain.chainId,
30
+ );
31
+ if (!tokenOption?.balance || tokenOption.balance.eq(0)) {
32
+ return "";
33
+ }
34
+ return weiToHumanReadable({
35
+ amount: tokenOption.balance.toString(),
36
+ decimals: dstToken.decimals,
37
+ precisionFractionalPlaces: 5,
38
+ });
39
+ }, [dstToken, dstChain, dstChainTokensOptions]);
40
+
41
+ const token = type === "source" ? srcToken : dstToken;
42
+ const balanceInfo =
43
+ type === "source" ? srcTokenBalanceInfo : dstTokenBalanceInfo;
44
+ const isLoading =
45
+ type === "source" ? isFetchingBalance : isFetchingBalances;
46
+
47
+ if (!token || (!balanceInfo && !isLoading)) {
48
+ return null;
49
+ }
6
50
 
7
51
  return (
8
- <div className="flex flex-col items-end">
9
- <p className="text-xs font-medium opacity-60">Balance:</p>
10
- {isFetchingBalance ? (
11
- <Skeleton className="w-[50px] h-[16px]" />
52
+ <div className="flex items-center justify-end py-1">
53
+ {isLoading ? (
54
+ <Skeleton className="w-[80px] h-[16px]" />
12
55
  ) : (
13
- <p
14
- className={`text-xs font-medium ${
15
- !srcTokenBalanceInfo && "opacity-60"
16
- }`}
17
- >
18
- {srcTokenBalanceInfo || "-"}
56
+ <p className="text-[10px] leading-4 text-right whitespace-nowrap">
57
+ <span className="text-t_text_primary text-opacity-50">
58
+ {`Balance `}
59
+ </span>
60
+ <span className="text-t_text_primary text-opacity-75">
61
+ {`${balanceInfo} ${token.symbol}`}
62
+ </span>
19
63
  </p>
20
64
  )}
21
65
  </div>