@xswap-link/sdk 0.14.0 → 0.15.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 (78) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/index.d.mts +4 -0
  3. package/dist/index.d.ts +4 -0
  4. package/dist/index.global.js +92 -92
  5. package/dist/index.js +3208 -2862
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +3083 -2740
  8. package/dist/index.mjs.map +1 -1
  9. package/localTheme.ts +6 -4
  10. package/package.json +1 -1
  11. package/src/assets/icons/AdjustmentsIcon.tsx +5 -7
  12. package/src/assets/icons/ChainlinkMarkIcon.tsx +4 -5
  13. package/src/assets/icons/CheckCircleThinIcon.tsx +22 -0
  14. package/src/assets/icons/ChevronDownThinIcon.tsx +39 -0
  15. package/src/assets/icons/ChevronDownWideThinIcon.tsx +18 -0
  16. package/src/assets/icons/ChevronsUpDownThinIcon.tsx +21 -0
  17. package/src/assets/icons/ClockIcon.tsx +3 -7
  18. package/src/assets/icons/CloseIcon.tsx +9 -4
  19. package/src/assets/icons/ErrorCircleThinIcon.tsx +22 -0
  20. package/src/assets/icons/LinkExternalThinIcon.tsx +19 -0
  21. package/src/assets/icons/LoadingRingIcon.tsx +22 -0
  22. package/src/assets/icons/ProgressRingThinIcon.tsx +29 -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/WarningIcon.tsx +8 -5
  27. package/src/assets/icons/index.ts +11 -0
  28. package/src/components/Modal/index.tsx +14 -9
  29. package/src/components/PoweredBy/index.tsx +6 -8
  30. package/src/components/Swap/Header/index.tsx +2 -4
  31. package/src/components/Swap/HistoryView/ActivityCard/index.tsx +110 -115
  32. package/src/components/Swap/HistoryView/index.tsx +10 -7
  33. package/src/components/Swap/PickerView/index.tsx +151 -0
  34. package/src/components/Swap/ReorderButton/ReorderButton.tsx +4 -4
  35. package/src/components/Swap/SettingsView/Delivery/index.tsx +19 -17
  36. package/src/components/Swap/SettingsView/InfiniteApproval/index.tsx +19 -17
  37. package/src/components/Swap/SettingsView/Slippage/index.tsx +55 -49
  38. package/src/components/Swap/SwapView/ConfirmationView/TokenTiles/index.tsx +69 -0
  39. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/Header/index.tsx +13 -25
  40. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/Steps/index.tsx +65 -113
  41. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/index.tsx +68 -26
  42. package/src/components/Swap/SwapView/ConfirmationView/TxResult/index.tsx +51 -74
  43. package/src/components/Swap/SwapView/FeesPanel/DeliveryInfo/index.tsx +1 -1
  44. package/src/components/Swap/SwapView/FeesPanel/index.tsx +5 -5
  45. package/src/components/Swap/SwapView/SwapButton/index.tsx +2 -31
  46. package/src/components/Swap/SwapView/SwapPanel/AmountPanel/Balance/index.tsx +2 -2
  47. package/src/components/Swap/SwapView/SwapPanel/AmountPanel/index.tsx +2 -2
  48. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/ChainPicker/index.tsx +143 -0
  49. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/NetworkFilter/index.tsx +19 -16
  50. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/TokenItem/index.tsx +11 -4
  51. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/index.tsx +185 -105
  52. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/index.tsx +54 -120
  53. package/src/components/Swap/SwapView/SwapPanel/UsdValue/index.tsx +2 -2
  54. package/src/components/Swap/SwapView/SwapPanel/WalletPanel/index.tsx +10 -16
  55. package/src/components/Swap/SwapView/SwapPanel/index.tsx +4 -4
  56. package/src/components/Swap/SwapView/WalletPicker/index.tsx +131 -139
  57. package/src/components/Swap/SwapView/index.tsx +11 -7
  58. package/src/components/Swap/WalletPickerView/index.tsx +65 -0
  59. package/src/components/Swap/index.tsx +39 -8
  60. package/src/components/ToggleButton/index.tsx +5 -7
  61. package/src/components/TokenLogo/index.tsx +1 -1
  62. package/src/components/TxConfigForm/index.tsx +2 -2
  63. package/src/components/TxModal/index.tsx +14 -4
  64. package/src/components/global.css +18 -1
  65. package/src/constants/index.ts +4 -0
  66. package/src/context/HistoryProvider.tsx +1 -1
  67. package/src/context/SwapProvider.tsx +193 -81
  68. package/src/context/TxUIWrapper.tsx +3 -3
  69. package/src/hooks/useEvmContractApi.ts +28 -4
  70. package/src/models/payloads/GetBalancesPayload.ts +1 -0
  71. package/src/services/api.ts +37 -0
  72. package/src/utils/index.ts +27 -1
  73. package/src/utils/tokens.ts +20 -1
  74. package/src/utils/validation.ts +9 -4
  75. package/tailwind.config.js +4 -1
  76. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/ArrowIcon.tsx +0 -13
  77. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/SwapPanel/index.tsx +0 -72
  78. package/src/components/Swap/SwapView/ConfirmationView/TxResult/TokenItem/index.tsx +0 -25
@@ -7,14 +7,18 @@ export type SwapPanelType = "source" | "destination";
7
7
 
8
8
  export const SwapView = () => {
9
9
  return (
10
- <div className="flex flex-col gap-6 fill-t_text_primary">
11
- <div className="flex flex-col gap-1.5">
12
- <SwapPanel type="source" />
13
- <ReorderButton />
14
- <SwapPanel type="destination" />
10
+ <div className="flex flex-col gap-8 fill-t_text_primary">
11
+ <div className="flex flex-col gap-6">
12
+ {/* ReorderButton is a zero-height anchor between the panels, so the
13
+ flex gap applies twice — 6px above and below it, 12px total. */}
14
+ <div className="flex flex-col gap-1.5">
15
+ <SwapPanel type="source" />
16
+ <ReorderButton />
17
+ <SwapPanel type="destination" />
18
+ </div>
19
+ <div className="h-px w-full gradient-sections-separator-container" />
20
+ <FeesPanel />
15
21
  </div>
16
- <div className="h-px w-full gradient-sections-separator-container" />
17
- <FeesPanel />
18
22
  <SwapButton />
19
23
  </div>
20
24
  );
@@ -0,0 +1,65 @@
1
+ import { Ecosystem } from "@src/models";
2
+ import { useWallet } from "@src/context/WalletProvider";
3
+ import { WalletPicker } from "../SwapView/WalletPicker";
4
+
5
+ /**
6
+ * Wallet picker rendered while one of the wallet modals is open, presented
7
+ * exactly like PickerView:
8
+ * - sm and up it replaces the swap view inside the widget container, so it
9
+ * sits on the exact same glass background,
10
+ * - below sm the same element becomes a bottom sheet pinned to the viewport.
11
+ */
12
+ export const WalletPickerView = () => {
13
+ const {
14
+ openEVMWalletModal,
15
+ setOpenEVMWalletModal,
16
+ openSolanaWalletModal,
17
+ setOpenSolanaWalletModal,
18
+ openSuiWalletModal,
19
+ setOpenSuiWalletModal,
20
+ } = useWallet();
21
+
22
+ const ecosystem = openEVMWalletModal
23
+ ? Ecosystem.EVM
24
+ : openSolanaWalletModal
25
+ ? Ecosystem.SOLANA
26
+ : openSuiWalletModal
27
+ ? Ecosystem.SUI
28
+ : null;
29
+
30
+ const close = () => {
31
+ setOpenEVMWalletModal(false);
32
+ setOpenSolanaWalletModal(false);
33
+ setOpenSuiWalletModal(false);
34
+ };
35
+
36
+ if (!ecosystem) {
37
+ return null;
38
+ }
39
+
40
+ return (
41
+ <div
42
+ className="fixed top-0 left-0 right-0 bottom-0 z-10 flex flex-col justify-end bg-[rgba(2,2,2,0.8)] sm:absolute sm:z-[2] sm:justify-start sm:bg-transparent"
43
+ onMouseDown={(e) => {
44
+ if (e.target === e.currentTarget) {
45
+ e.stopPropagation();
46
+ e.nativeEvent.stopImmediatePropagation();
47
+ e.preventDefault();
48
+ close();
49
+ }
50
+ }}
51
+ >
52
+ <div className="flex flex-col w-full h-[85vh] max-h-full overflow-hidden p-4 pt-2.5 rounded-t-[24px] border-t border-solid border-t_text_primary border-opacity-10 bg-gradient-to-r from-t_bg_secondary/50 to-t_bg_secondary/50 bg-t_bg_primary sm:h-full sm:p-0 sm:rounded-none sm:border-0 sm:bg-none sm:bg-transparent">
53
+ <div className="sm:hidden mx-auto mb-4 h-1 w-8 rounded-full bg-t_bg_tertiary bg-opacity-10 shrink-0" />
54
+ <WalletPicker ecosystem={ecosystem} onClose={close} />
55
+ </div>
56
+ </div>
57
+ );
58
+ };
59
+
60
+ /** True while any of the wallet picker modals is requested open. */
61
+ export const useWalletPickerOpen = () => {
62
+ const { openEVMWalletModal, openSolanaWalletModal, openSuiWalletModal } =
63
+ useWallet();
64
+ return openEVMWalletModal || openSolanaWalletModal || openSuiWalletModal;
65
+ };
@@ -3,8 +3,10 @@ import { useSwapContext } from "@src/context";
3
3
  import { useMemo } from "react";
4
4
  import { Header } from "./Header";
5
5
  import { HistoryView } from "./HistoryView";
6
+ import { PickerView } from "./PickerView";
6
7
  import { SettingsView } from "./SettingsView";
7
8
  import { SwapView } from "./SwapView";
9
+ import { WalletPickerView, useWalletPickerOpen } from "./WalletPickerView";
8
10
  import { UnifiedRoute } from "@src/models";
9
11
 
10
12
  type Props = {
@@ -12,24 +14,53 @@ type Props = {
12
14
  onClose: () => void;
13
15
  };
14
16
  export const Swap = ({ onClose }: Props) => {
15
- const { tab } = useSwapContext();
17
+ const { tab, activePicker } = useSwapContext();
18
+ const walletPickerOpen = useWalletPickerOpen();
16
19
 
17
- const view = useMemo(() => {
20
+ const overlayView = useMemo(() => {
18
21
  return tab === "Settings" ? (
19
22
  <SettingsView />
20
23
  ) : tab === "History" ? (
21
24
  <HistoryView />
22
- ) : (
23
- <SwapView />
24
- );
25
+ ) : null;
25
26
  }, [tab]);
26
27
 
27
28
  return (
28
29
  <div
29
- className={`relative flex flex-col gap-6 p-5 sm:p-6 text-t_text_primary bg-t_bg_secondary bg-opacity-50 backdrop-blur-[12px] rounded-[20px] border border-solid border-t_text_primary border-opacity-10 flex-1`}
30
+ className={`relative flex flex-col gap-6 p-4 sm:p-8 text-t_text_primary bg-gradient-to-r from-t_bg_tertiary/[0.01] to-t_bg_tertiary/[0.01] bg-t_bg_secondary bg-opacity-50 backdrop-blur-[48px] rounded-[32px] border border-solid border-t_text_primary border-opacity-10 flex-1`}
30
31
  >
31
- <Header onClose={onClose} />
32
- <div className="flex flex-col flex-1 min-h-0">{view}</div>
32
+ {/* On sm+ the picker replaces the header and the current view in
33
+ place; below sm it renders as a bottom sheet over them. The
34
+ replaced content stays in the layout (visibility only), so it keeps
35
+ defining the widget height for the picker to fill. */}
36
+ <div className="relative flex flex-col flex-1 min-h-0">
37
+ {activePicker && <PickerView />}
38
+ <WalletPickerView />
39
+ <div
40
+ className={`flex flex-col gap-6 flex-1 min-h-0 ${
41
+ activePicker || walletPickerOpen ? "sm:invisible" : ""
42
+ }`}
43
+ >
44
+ <Header onClose={onClose} />
45
+ {/* SwapView stays in the layout on every tab (visibility only), so
46
+ it keeps defining one shared widget height; Settings/History
47
+ render as an overlay filling that height. */}
48
+ <div className="relative flex flex-col flex-1 min-h-0">
49
+ <div
50
+ className={`flex flex-col flex-1 min-h-0 ${
51
+ overlayView ? "invisible" : ""
52
+ }`}
53
+ >
54
+ <SwapView />
55
+ </div>
56
+ {overlayView && (
57
+ <div className="absolute inset-0 flex flex-col min-h-0">
58
+ {overlayView}
59
+ </div>
60
+ )}
61
+ </div>
62
+ </div>
63
+ </div>
33
64
  <PoweredBy />
34
65
  </div>
35
66
  );
@@ -10,17 +10,15 @@ const ToggleButton = ({ checked, onClick }: Props) => {
10
10
  role="switch"
11
11
  aria-checked={checked}
12
12
  onClick={onClick}
13
- className={`relative inline-flex items-center w-12 h-6 p-[3px] rounded-full cursor-pointer transition-colors border-none ${
13
+ className={`relative inline-flex items-center w-10 h-5 p-0.5 rounded-full cursor-pointer transition-opacity border-none bg-gradient-to-r ${
14
14
  checked
15
- ? "bg-gradient-to-r from-t_main_accent_light/40 to-t_main_accent_dark/60"
16
- : "bg-t_bg_tertiary bg-opacity-10"
15
+ ? "from-t_main_accent_light/25 to-t_main_accent_dark/25"
16
+ : "from-t_main_accent_light/20 to-t_main_accent_dark/20 opacity-50"
17
17
  }`}
18
18
  >
19
19
  <span
20
- className={`w-[18px] h-[18px] rounded-full transition-transform ${
21
- checked
22
- ? "translate-x-6 bg-t_main_accent_light"
23
- : "translate-x-0 bg-t_text_primary opacity-40"
20
+ className={`w-4 h-4 rounded-full transition-transform bg-gradient-to-r from-t_main_accent_light to-t_main_accent_dark ${
21
+ checked ? "translate-x-5" : "translate-x-0"
24
22
  }`}
25
23
  ></span>
26
24
  </button>
@@ -32,7 +32,7 @@ export const TokenLogo = ({
32
32
  <img
33
33
  src={token.image}
34
34
  alt={token.name}
35
- className={`border border-solid border-t_text_primary border-opacity-10 rounded-2xl ${className}`}
35
+ className={`rounded-full ${className}`}
36
36
  onError={() => setErrorOccured(true)}
37
37
  />
38
38
  ) : (
@@ -189,12 +189,12 @@ export const TxConfigForm = (props: TxConfigFormProps) => {
189
189
  className="top-0 left-0 right-0 bottom-0 bg-[rgba(0,0,0,0.8)] fixed flex flex-col items-center justify-center z-10"
190
190
  onMouseDown={onBackdropClick}
191
191
  >
192
- <div className="relative rounded-[20px] overflow-auto text-t_text_primary w-x_modal min-w-x_modal max-w-x_modal min-h-[532px] flex flex-col">
192
+ <div className="relative rounded-[32px] overflow-auto text-t_text_primary w-x_modal min-w-x_modal max-w-x_modal min-h-[532px] flex flex-col">
193
193
  <Swap onSubmit={onSubmit} onClose={onClose} />
194
194
  </div>
195
195
  </div>
196
196
  ) : (
197
- <div className="rounded-[20px] overflow-auto text-t_text_primary min-h-[532px] w-x_modal min-w-x_modal max-w-x_modal flex flex-col">
197
+ <div className="rounded-[32px] overflow-auto text-t_text_primary min-h-[532px] w-x_modal min-w-x_modal max-w-x_modal flex flex-col">
198
198
  <Swap onSubmit={() => {}} onClose={() => {}} />
199
199
  </div>
200
200
  )}
@@ -38,11 +38,11 @@ export const TxModal = ({
38
38
  onMouseDown={onBackdropClick}
39
39
  >
40
40
  <div
41
- className={`relative bg-t_bg_primary rounded-3xl p-4 w-full min-w-[340px] overflow-auto max-w-x_modal border-2 ${
41
+ className={`relative rounded-[32px] p-6 sm:p-8 w-full min-w-[340px] overflow-auto max-w-x_modal backdrop-blur-[32px] bg-t_bg_secondary bg-opacity-75 border border-solid ${
42
42
  type === "error"
43
- ? "border-t_error_dark"
43
+ ? "border-[#F44336]"
44
44
  : type === "success"
45
- ? "border-t_success_dark"
45
+ ? "border-[#6AE89B]"
46
46
  : type === "warning"
47
47
  ? "border-t_warning_dark"
48
48
  : type === "waiting"
@@ -50,7 +50,17 @@ export const TxModal = ({
50
50
  : "border-t_text_primary border-opacity-10"
51
51
  } ${className}`}
52
52
  >
53
- {children}
53
+ {(type === "error" || type === "success") && (
54
+ <div
55
+ aria-hidden
56
+ className={`absolute inset-0 rounded-[inherit] pointer-events-none ${
57
+ type === "error"
58
+ ? "tx-modal-glow-error"
59
+ : "tx-modal-glow-success"
60
+ }`}
61
+ />
62
+ )}
63
+ <div className="relative">{children}</div>
54
64
  </div>
55
65
  </div>,
56
66
  xpayShadowRoot!,
@@ -36,13 +36,30 @@
36
36
  }
37
37
 
38
38
  .gradient-sections-separator-container {
39
- @apply bg-gradient-to-r from-transparent via-t_bg_tertiary/25 to-transparent;
39
+ @apply bg-gradient-to-r from-transparent via-t_bg_tertiary/10 to-transparent;
40
40
  }
41
41
 
42
42
  .x-border {
43
43
  @apply border border-solid border-t_text_primary border-opacity-10;
44
44
  }
45
45
 
46
+ /* Corner glow of the transaction result modal, fading towards the center */
47
+ .tx-modal-glow-success {
48
+ background: radial-gradient(
49
+ 120% 60% at 0% 0%,
50
+ rgba(76, 175, 80, 0.25) 0%,
51
+ transparent 45%
52
+ );
53
+ }
54
+
55
+ .tx-modal-glow-error {
56
+ background: radial-gradient(
57
+ 120% 60% at 0% 0%,
58
+ rgba(244, 67, 54, 0.25) 0%,
59
+ transparent 45%
60
+ );
61
+ }
62
+
46
63
  .xpay-tx-status {
47
64
  @apply fixed bottom-5 right-2 flex flex-col gap-3 pl-9 items-end w-full z-50;
48
65
  }
@@ -49,6 +49,10 @@ export const MINIMUM_DISPLAYED_TOKEN_AMOUNT = 0.0001;
49
49
  export const DEFAULT_SOURCE_CHAIN_ID = "1";
50
50
  export const DEFAULT_SOURCE_TOKEN_ADDR = constants.AddressZero;
51
51
  export const DEFAULT_DESTINATION_CHAIN_ID = "1";
52
+ // Default bridge route: Ethereum -> Base; the token defaults to XSWAP via
53
+ // getDefaultBridgeTokenForChain.
54
+ export const DEFAULT_BRIDGE_SOURCE_CHAIN_ID = "1";
55
+ export const DEFAULT_BRIDGE_DESTINATION_CHAIN_ID = "8453";
52
56
  export const DEFAULT_DESTINATION_TOKEN_ADDR =
53
57
  "0x8fe815417913a93ea99049fc0718ee1647a2a07c"; // XSWAP token
54
58
  export const CCIP_EXPLORER = "https://ccip.chain.link/";
@@ -360,7 +360,7 @@ export const HistoryProvider = ({ children }: HistoryProviderProps) => {
360
360
  </Button>
361
361
 
362
362
  <div
363
- className="transaction-provider__close fill-white leading-[0px]"
363
+ className="transaction-provider__close fill-white text-white leading-[0px]"
364
364
  onClick={() => closeSnackbar(messageId)}
365
365
  >
366
366
  <CloseIcon />