@layerswap/widget 1.1.2 → 1.1.4

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 (101) hide show
  1. package/dist/esm/Models/Theme.js +1 -75
  2. package/dist/esm/components/Buttons/connectButton.js +1 -1
  3. package/dist/esm/components/Common/ConnectWalletButton.js +1 -1
  4. package/dist/esm/components/Icons/CircularLoader.js +1 -1
  5. package/dist/esm/components/Icons/MenuIcon.js +1 -1
  6. package/dist/esm/components/Icons/Wallets/Solflare.js +1 -1
  7. package/dist/esm/components/Input/Amount/MinMax.js +15 -22
  8. package/dist/esm/components/Input/Amount/PriceImpact.js +1 -1
  9. package/dist/esm/components/Input/Amount/helpers.js +4 -4
  10. package/dist/esm/components/Input/CexPicker.js +1 -1
  11. package/dist/esm/components/Input/DestinationWalletPicker.js +1 -1
  12. package/dist/esm/components/Input/NumericInput.js +3 -3
  13. package/dist/esm/components/Input/RoutePicker/Routes.js +3 -9
  14. package/dist/esm/components/Input/RoutePicker/TokenTitleDetails.js +2 -4
  15. package/dist/esm/components/Input/RoutePicker/index.js +1 -1
  16. package/dist/esm/components/Input/SourceWalletPicker.js +1 -1
  17. package/dist/esm/components/Modal/modalWithoutAnimation.js +4 -4
  18. package/dist/esm/components/Modal/vaulModal.js +2 -2
  19. package/dist/esm/components/Pages/Campaigns/Details/index.js +1 -1
  20. package/dist/esm/components/Pages/Swap/Form/FeeDetails/Rate.js +5 -11
  21. package/dist/esm/components/Pages/Swap/Form/FeeDetails/Slippage.js +1 -1
  22. package/dist/esm/components/Pages/Swap/Form/FeeDetails/SwapQuote/DetailedEstimates.js +4 -4
  23. package/dist/esm/components/Pages/Swap/Form/FeeDetails/SwapQuote/SummaryRow.js +1 -1
  24. package/dist/esm/components/Pages/Swap/Form/FeeDetails/index.js +1 -1
  25. package/dist/esm/components/Pages/Swap/Form/SecondaryComponents/FormButton.js +1 -1
  26. package/dist/esm/components/Pages/Swap/Withdraw/Wallet/Common/actionMessage.js +2 -2
  27. package/dist/esm/components/Pages/Swap/Withdraw/Wallet/RPCUnhealthyMessage.js +46 -0
  28. package/dist/esm/components/Pages/Swap/Withdraw/Wallet/index.js +8 -0
  29. package/dist/esm/components/Pages/Swap/Withdraw/messages/Message.js +5 -2
  30. package/dist/esm/components/Pages/Swap/Withdraw/messages/TransactionMessages.js +3 -3
  31. package/dist/esm/components/Widget/Footer.js +13 -13
  32. package/dist/esm/components/Widget/Index.js +4 -1
  33. package/dist/esm/context/resolverContext.js +6 -2
  34. package/dist/esm/context/rpcHealthContext.js +18 -0
  35. package/dist/esm/context/settings.js +13 -4
  36. package/dist/esm/exports/internal.js +1 -0
  37. package/dist/esm/hooks/useFormRoutes.js +15 -7
  38. package/dist/esm/hooks/useFormValidation.js +1 -1
  39. package/dist/esm/lib/apiClients/layerSwapApiClient.js +6 -0
  40. package/dist/esm/lib/knownIds.js +1 -0
  41. package/dist/esm/lib/resolvers/resolverService.js +7 -1
  42. package/dist/esm/lib/rpcHealth/rpcHealthCheckResolver.js +8 -0
  43. package/dist/esm/types/index.js +1 -0
  44. package/dist/esm/types/rpcHealth.js +1 -0
  45. package/dist/index.css +1 -1
  46. package/dist/tsconfig.tsbuildinfo +1 -1
  47. package/dist/types/Models/Theme.d.ts.map +1 -1
  48. package/dist/types/components/Buttons/connectButton.d.ts.map +1 -1
  49. package/dist/types/components/Common/ConnectWalletButton.d.ts.map +1 -1
  50. package/dist/types/components/Input/Amount/MinMax.d.ts +1 -1
  51. package/dist/types/components/Input/Amount/MinMax.d.ts.map +1 -1
  52. package/dist/types/components/Input/DestinationWalletPicker.d.ts.map +1 -1
  53. package/dist/types/components/Input/RoutePicker/Routes.d.ts.map +1 -1
  54. package/dist/types/components/Input/RoutePicker/TokenTitleDetails.d.ts +1 -2
  55. package/dist/types/components/Input/RoutePicker/TokenTitleDetails.d.ts.map +1 -1
  56. package/dist/types/components/Input/SourceWalletPicker.d.ts.map +1 -1
  57. package/dist/types/components/Modal/modalWithoutAnimation.d.ts +2 -2
  58. package/dist/types/components/Modal/modalWithoutAnimation.d.ts.map +1 -1
  59. package/dist/types/components/Pages/Swap/Form/FeeDetails/Rate.d.ts +3 -5
  60. package/dist/types/components/Pages/Swap/Form/FeeDetails/Rate.d.ts.map +1 -1
  61. package/dist/types/components/Pages/Swap/Form/FeeDetails/Slippage.d.ts.map +1 -1
  62. package/dist/types/components/Pages/Swap/Form/FeeDetails/SwapQuote/SummaryRow.d.ts.map +1 -1
  63. package/dist/types/components/Pages/Swap/Form/FeeDetails/index.d.ts.map +1 -1
  64. package/dist/types/components/Pages/Swap/Form/SecondaryComponents/FormButton.d.ts.map +1 -1
  65. package/dist/types/components/Pages/Swap/Withdraw/ManualWithdraw.d.ts.map +1 -1
  66. package/dist/types/components/Pages/Swap/Withdraw/Wallet/RPCUnhealthyMessage.d.ts +12 -0
  67. package/dist/types/components/Pages/Swap/Withdraw/Wallet/RPCUnhealthyMessage.d.ts.map +1 -0
  68. package/dist/types/components/Pages/Swap/Withdraw/Wallet/index.d.ts.map +1 -1
  69. package/dist/types/components/Pages/Swap/Withdraw/messages/Message.d.ts +1 -1
  70. package/dist/types/components/Pages/Swap/Withdraw/messages/Message.d.ts.map +1 -1
  71. package/dist/types/components/Pages/Swap/Withdraw/messages/TransactionMessages.d.ts +1 -3
  72. package/dist/types/components/Pages/Swap/Withdraw/messages/TransactionMessages.d.ts.map +1 -1
  73. package/dist/types/components/Widget/Footer.d.ts.map +1 -1
  74. package/dist/types/components/Widget/Index.d.ts.map +1 -1
  75. package/dist/types/context/resolverContext.d.ts.map +1 -1
  76. package/dist/types/context/rpcHealthContext.d.ts +10 -0
  77. package/dist/types/context/rpcHealthContext.d.ts.map +1 -0
  78. package/dist/types/context/settings.d.ts +8 -1
  79. package/dist/types/context/settings.d.ts.map +1 -1
  80. package/dist/types/exports/internal.d.ts +1 -0
  81. package/dist/types/exports/internal.d.ts.map +1 -1
  82. package/dist/types/lib/apiClients/layerSwapApiClient.d.ts +1 -0
  83. package/dist/types/lib/apiClients/layerSwapApiClient.d.ts.map +1 -1
  84. package/dist/types/lib/knownIds.d.ts +1 -0
  85. package/dist/types/lib/knownIds.d.ts.map +1 -1
  86. package/dist/types/lib/resolvers/resolverService.d.ts +5 -1
  87. package/dist/types/lib/resolvers/resolverService.d.ts.map +1 -1
  88. package/dist/types/lib/rpcHealth/rpcHealthCheckResolver.d.ts +8 -0
  89. package/dist/types/lib/rpcHealth/rpcHealthCheckResolver.d.ts.map +1 -0
  90. package/dist/types/types/index.d.ts +1 -0
  91. package/dist/types/types/index.d.ts.map +1 -1
  92. package/dist/types/types/logEvents.d.ts +11 -2
  93. package/dist/types/types/logEvents.d.ts.map +1 -1
  94. package/dist/types/types/rpcHealth.d.ts +40 -0
  95. package/dist/types/types/rpcHealth.d.ts.map +1 -0
  96. package/dist/types/types/wallet.d.ts +3 -0
  97. package/dist/types/types/wallet.d.ts.map +1 -1
  98. package/package.json +1 -1
  99. package/dist/esm/lib/isNewListed.js +0 -8
  100. package/dist/types/lib/isNewListed.d.ts +0 -4
  101. package/dist/types/lib/isNewListed.d.ts.map +0 -1
@@ -12,6 +12,6 @@ const FormButton = ({ shouldConnectWallet, values, disabled, error, isSubmitting
12
12
  if (values?.to && !values?.destination_address && !error) {
13
13
  return (_jsx(Address, { partner: partner, children: () => (_jsx(SubmitButton, { type: "button", className: "w-full", children: _jsx("span", { className: "grow text-center", children: "Enter destination address" }) })) }));
14
14
  }
15
- return (_jsx(SubmitButton, { type: "submit", isDisabled: disabled, isSubmitting: isSubmitting, children: actionDisplayName }));
15
+ return (_jsx(SubmitButton, { "data-attr": "submit-swap", type: "submit", isDisabled: disabled, isSubmitting: isSubmitting, children: actionDisplayName }));
16
16
  };
17
17
  export default FormButton;
@@ -35,8 +35,8 @@ export const ActionMessage = ({ error, isLoading }) => {
35
35
  }
36
36
  else if (error) {
37
37
  if (!error.message)
38
- return _jsx(ActionMessages.UnexpectedErrorMessage, { message: 'Something went wrong' });
39
- return _jsx(ActionMessages.UnexpectedErrorMessage, { message: error.message });
38
+ return _jsx(ActionMessages.UnexpectedErrorMessage, {});
39
+ return _jsx(ActionMessages.UnexpectedErrorMessage, {});
40
40
  }
41
41
  else
42
42
  return _jsx(_Fragment, {});
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { ButtonWrapper } from "./Common/buttons";
4
+ import FailIcon from "../../../../../components/Icons/FailIcon";
5
+ import { Tooltip, TooltipContent, TooltipTrigger } from "../../../../../components/shadcn/tooltip";
6
+ import useCopyClipboard from "../../../../../hooks/useCopyClipboard";
7
+ import { Check, CopyIcon } from "lucide-react";
8
+ const HEALTH_CHECK_INTERVAL = 1500; // 1.5 seconds
9
+ const RPCUnhealthyMessage = ({ network, suggestRpcForCurrentChain, isSuggestingRpc, checkManually }) => {
10
+ const [rpcAddStatus, setRpcAddStatus] = useState('idle');
11
+ // Poll health check while unhealthy
12
+ useEffect(() => {
13
+ const interval = setInterval(() => {
14
+ checkManually();
15
+ }, HEALTH_CHECK_INTERVAL);
16
+ return () => clearInterval(interval);
17
+ }, [checkManually]);
18
+ const handleAddRpc = async () => {
19
+ setRpcAddStatus('idle');
20
+ const result = await suggestRpcForCurrentChain(network.node_url, {
21
+ chainName: network.display_name,
22
+ nativeCurrency: {
23
+ name: network.display_name,
24
+ symbol: network.token?.symbol,
25
+ decimals: network.token?.decimals
26
+ }
27
+ });
28
+ setRpcAddStatus(result.success ? 'success' : 'error');
29
+ };
30
+ return (_jsxs("div", { className: "w-full space-y-3 h-fit text-primary-text", children: [_jsx(MessageContent, { RPCUrl: network.node_url, isSuggestingRpc: isSuggestingRpc, rpcAddStatus: rpcAddStatus }), rpcAddStatus !== "success" &&
31
+ _jsx(ButtonWrapper, { onClick: handleAddRpc, isDisabled: isSuggestingRpc, children: isSuggestingRpc ? 'Confirm in wallet...' : 'Add RPC URL to wallet' })] }));
32
+ };
33
+ const MessageContent = ({ RPCUrl, isSuggestingRpc, rpcAddStatus }) => {
34
+ const [isCopied, setCopied] = useCopyClipboard(2000);
35
+ const getMessage = () => {
36
+ if (isSuggestingRpc) {
37
+ return _jsx("p", { className: "text-secondary-text text-sm leading-[18px]", children: "Please confirm the RPC change in your wallet..." });
38
+ }
39
+ if (rpcAddStatus === 'success') {
40
+ return _jsx("p", { className: "text-secondary-text text-sm leading-[18px]", children: "RPC URL added! Please switch to the new RPC in your wallet settings." });
41
+ }
42
+ return _jsxs("p", { className: "text-secondary-text text-sm leading-[18px] space-x-1", children: [_jsx("span", { children: "Update your RPC URL manually or add our" }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { onClick: () => setCopied(RPCUrl), children: _jsxs("span", { className: "text-primary-text cursor-pointer underline flex items-baseline gap-1", children: [isCopied ? (_jsx(Check, { className: "h-3 w-3" })) : _jsx(CopyIcon, { className: "h-3 w-3" }), _jsx("span", { children: "RPC URL" })] }) }), _jsx(TooltipContent, { sticky: "always", children: _jsx("span", { className: "flex items-center gap-1", children: _jsx("span", { children: RPCUrl }) }) })] }), _jsx("span", { children: "to your wallet" })] });
43
+ };
44
+ return _jsx("div", { className: "px-2 py-3 rounded-2xl bg-secondary-400", children: _jsxs("div", { className: "flex items-start gap-2 relative", children: [_jsx("span", { className: "shrink-0 p-0.5", children: rpcAddStatus === 'success' ? (_jsx(Check, { className: "relative top-0 left-0 h-5 w-5 text-green-500" })) : (_jsx(FailIcon, { className: "relative top-0 left-0 h-5 w-5" })) }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("p", { className: "text-white font-medium leading-4 text-base mt-0.5", children: rpcAddStatus === 'success' ? 'RPC URL added successfully' : 'Your wallet RPC has network issues' }), getMessage()] })] }) });
45
+ };
46
+ export default RPCUnhealthyMessage;
@@ -10,6 +10,8 @@ import { useBalance } from "../../../../../lib/balances/useBalance";
10
10
  import { ActionMessage } from "./Common/actionMessage";
11
11
  import { ActionMessages } from "../messages/TransactionMessages";
12
12
  import { useTransfer } from "../../../../../hooks/useTransfer";
13
+ import { useRpcHealth } from "../../../../../context/rpcHealthContext";
14
+ import RPCUnhealthyMessage from "./RPCUnhealthyMessage";
13
15
  export const WalletTransferAction = ({ swapData, swapId, refuel, onWalletWithdrawalSuccess, onCancelWithdrawal }) => {
14
16
  const { source_network } = swapData;
15
17
  const { provider, wallets } = useWallet(source_network, "withdrawal");
@@ -79,6 +81,8 @@ const TransferTokenButton = ({ savedTransactionHash, chainId, swapData, refuel }
79
81
  const { balances } = useBalance(selectedSourceAccount?.address, networkWithTokens);
80
82
  const wallet = wallets.find(w => w.id === selectedSourceAccount?.id);
81
83
  const { executeTransfer } = useTransfer();
84
+ const rpcHealth = useRpcHealth(swapData.source_network);
85
+ console.log("rpcHealth", rpcHealth);
82
86
  const clickHandler = useCallback(async ({ amount, callData, depositAddress, swapId }) => {
83
87
  setButtonClicked(true);
84
88
  setError(undefined);
@@ -139,6 +143,10 @@ const TransferTokenButton = ({ savedTransactionHash, chainId, swapData, refuel }
139
143
  throw e;
140
144
  }
141
145
  }, [executeTransfer, chainId, selectedSourceAccount?.address, wallet, swapData, balances]);
146
+ // Show RPC health message if available and unhealthy (EVM wallets only)
147
+ if (rpcHealth?.health.status === 'unhealthy') {
148
+ return _jsx(RPCUnhealthyMessage, { network: swapData.source_network, suggestRpcForCurrentChain: rpcHealth.suggestRpcForCurrentChain, isSuggestingRpc: rpcHealth.isSuggestingRpc, checkManually: rpcHealth.checkManually });
149
+ }
142
150
  return _jsxs("div", { className: "w-full space-y-3 flex flex-col justify-between h-full text-primary-text", children: [buttonClicked &&
143
151
  _jsx(ActionMessage, { error: error, isLoading: loading }), !loading &&
144
152
  _jsx(SendTransactionButton, { onClick: clickHandler, icon: _jsx(WalletIcon, { className: "stroke-2 w-6 h-6" }), error: !!error && buttonClicked, swapData: swapData, refuel: refuel })] });
@@ -2,10 +2,13 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
2
2
  import { ChevronDown } from "lucide-react";
3
3
  import FailIcon from "../../../../Icons/FailIcon";
4
4
  import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "../../../../../components/shadcn/accordion";
5
- const WalletMessage = ({ header, details, status, showInModal }) => {
5
+ const WalletMessage = ({ header, details, status }) => {
6
6
  return _jsx(_Fragment, { children: _jsx("div", { className: "px-2 py-3 rounded-2xl bg-secondary-400", children: _jsxs("div", { className: "flex items-start gap-2 relative", children: [_jsx("span", { className: "shrink-0 p-0.5", children: status === "error" ?
7
7
  _jsx(FailIcon, { className: "relative top-0 left-0 h-5 w-5" })
8
8
  :
9
- _jsxs(_Fragment, { children: [_jsx("div", { className: 'absolute top-1.5 left-1.5 w-4 h-4 md:w-5 md:h-5 opacity-40 bg bg-primary rounded-full animate-ping' }), _jsx("div", { className: 'absolute top-2.5 left-2.5 w-2 h-2 md:w-3 md:h-3 opacity-40 bg bg-primary rounded-full animate-ping' }), _jsx("div", { className: 'relative top-0 left-0 w-6 h-6 md:w-7 md:h-7 scale-50 bg bg-primary rounded-full ' })] }) }), showInModal ? (_jsx("div", { className: "text-left space-y-1 w-full max-w-2xl", children: _jsx(Accordion, { type: "single", collapsible: true, children: _jsxs(AccordionItem, { value: "wallet-message", children: [_jsxs(AccordionTrigger, { className: "flex justify-between w-full items-center mt-0.5", children: [_jsx("p", { className: "text-primary-text font-medium leading-4 text-base mt-0.5", children: header }), _jsx(ChevronDown, { className: "h-4 w-4 shrink-0 text-primary-text transition-transform duration-200 data-[state=open]:rotate-180" })] }), _jsx(AccordionContent, { children: _jsx("div", { className: "text-left space-y-1", children: _jsx("p", { className: "text-sm text-secondary-text wrap-anywhere whitespace-pre-wrap", children: details }) }) })] }) }) })) : (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("p", { className: "text-primary-text font-medium leading-4 text-base mt-0.5", children: header }), details ? _jsx("p", { className: "text-secondary-text text-sm leading-[18px]", children: details }) : null] }))] }) }) });
9
+ _jsxs(_Fragment, { children: [_jsx("div", { className: 'absolute top-1.5 left-1.5 w-4 h-4 md:w-5 md:h-5 opacity-40 bg bg-primary rounded-full animate-ping' }), _jsx("div", { className: 'absolute top-2.5 left-2.5 w-2 h-2 md:w-3 md:h-3 opacity-40 bg bg-primary rounded-full animate-ping' }), _jsx("div", { className: 'relative top-0 left-0 w-6 h-6 md:w-7 md:h-7 scale-50 bg bg-primary rounded-full ' })] }) }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("p", { className: "text-white font-medium leading-4 text-base mt-0.5", children: header }), details ? _jsx("p", { className: "text-secondary-text text-sm leading-[18px]", children: details }) : null] })] }) }) });
10
+ };
11
+ export const WalletUnknownError = () => {
12
+ return _jsx("div", { className: "text-left space-y-1 w-full max-w-2xl rounded-2xl ", children: _jsx(Accordion, { type: "single", collapsible: true, className: "rounded-2xl bg-secondary-500 overflow-hidden", children: _jsxs(AccordionItem, { value: "wallet-message", children: [_jsxs(AccordionTrigger, { className: "flex justify-between w-full gap-2 items-center px-2 py-3 bg-secondary-400 rounded-2xl group", children: [_jsx("div", { className: "shrink-0 p-0.5 self-start", children: _jsx(FailIcon, { className: "h-5 w-5" }) }), _jsxs("div", { className: "flex flex-col gap-1 items-start", children: [_jsx("p", { className: "text-white font-medium leading-4 text-base", children: "Wallet error" }), _jsx("p", { className: "text-sm text-secondary-text text-left wrap-anywhere whitespace-pre-wrap", children: "An error occurred, the swap wasn\u2019t initiated your assets were not moved." })] }), _jsx(ChevronDown, { className: "h-4 w-4 self-start shrink-0 text-primary-text transition-transform duration-200 group-aria-expanded:rotate-180" })] }), _jsx(AccordionContent, { children: _jsx("div", { className: "text-left space-y-1 bg-secondary-500 px-10 py-3", children: _jsxs("p", { className: "text-sm text-secondary-text wrap-anywhere whitespace-pre-wrap", children: [_jsx("span", { children: "Try one of the following:" }), _jsxs("ul", { className: "list-outside pl-6 list-disc", children: [_jsx("li", { children: "Reconnect your wallet" }), _jsx("li", { children: "Switch the wallet network, to match the swap\u2019s source network" }), _jsx("li", { children: "Restart the browser and the wallet app" })] }), _jsx("br", {}), _jsx("p", { children: "If the error persists try the manual transfer options" })] }) }) })] }) }) });
10
13
  };
11
14
  export default WalletMessage;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import WalletMessage from "./Message";
2
+ import WalletMessage, { WalletUnknownError } from "./Message";
3
3
  import shortenAddress from "../../../../../components/utils/ShortenAddress";
4
4
  const ConfirmActionMessage = () => {
5
5
  return _jsx(WalletMessage, { status: "pending", header: 'Confirm in wallet', details: 'Please confirm the transaction in your wallet' });
@@ -25,8 +25,8 @@ const WaletMismatchMessage = ({ address }) => {
25
25
  const SwapErrorMessage = ({ message }) => {
26
26
  return _jsx(WalletMessage, { status: "error", header: 'API error', details: message });
27
27
  };
28
- const UnexpectedErrorMessage = ({ message }) => {
29
- return _jsx(WalletMessage, { status: "error", header: 'Unexpected error', details: message, showInModal: true });
28
+ const UnexpectedErrorMessage = () => {
29
+ return _jsx(WalletUnknownError, {});
30
30
  };
31
31
  export const ActionMessages = {
32
32
  ConfirmActionMessage,
@@ -29,19 +29,19 @@ const Comp = ({ children, hidden, sticky = true, showPoweredBy }) => {
29
29
  return (_jsx(_Fragment, { children: sticky ?
30
30
  _jsxs(_Fragment, { children: [_jsx(motion.div, { ref: footerRef, transition: {
31
31
  duration: 0.15,
32
- }, custom: { direction: -1, width: 100 }, variants: variants, className: `text-primary-text text-base
33
- max-sm:fixed
34
- max-sm:inset-x-0
35
- max-sm:bottom-0
36
- max-sm:z-30
37
- max-sm:bg-secondary-700
38
- max-sm:shadow-widget-footer
39
- max-sm:p-4
40
- max-sm:px-4
41
- max-sm:w-full ${hidden ? 'animation-slide-out' : ''} w-full`, children: children }), _jsx("div", { style: { height: `${height}px` }, className: `text-primary-text text-base
42
- max-sm:inset-x-0
43
- max-sm:bottom-0
44
- max-sm:p-4 max-sm:w-full invisible sm:hidden w-full` })] })
32
+ }, custom: { direction: -1, width: 100 }, style: AppSettings.ThemeData?.cardBackgroundStyle, variants: variants, className: `text-primary-text text-base
33
+ max-sm:fixed
34
+ max-sm:inset-x-0
35
+ max-sm:bottom-0
36
+ max-sm:z-30
37
+ max-sm:bg-secondary-700
38
+ max-sm:shadow-widget-footer
39
+ max-sm:p-4
40
+ max-sm:px-4
41
+ max-sm:w-full ${hidden ? 'animation-slide-out' : ''} w-full`, children: children }), _jsx("div", { style: { height: `${height}px` }, className: `text-primary-text text-base
42
+ max-sm:inset-x-0
43
+ max-sm:bottom-0
44
+ max-sm:p-4 max-sm:w-full invisible sm:hidden w-full` })] })
45
45
  :
46
46
  _jsx("div", { className: clsx('space-y-3', { 'mb-3 sm:mb-0': !showPoweredBy }), children: children }) }));
47
47
  };
@@ -6,11 +6,14 @@ import { default as Footer } from './Footer';
6
6
  import { useRef } from "react";
7
7
  import AppSettings from "../../lib/AppSettings";
8
8
  import clsx from "clsx";
9
+ import { useSettingsState } from "../../exports";
9
10
  const Widget = ({ children, hideMenu, goBack, contextualMenu }) => {
10
11
  const wrapper = useRef(null);
11
- return _jsxs("div", { className: "relative p-px h-full", children: [AppSettings.ThemeData?.enableWideVersion &&
12
+ const { isEmbedded } = useSettingsState();
13
+ return _jsxs("div", { className: "relative p-px h-full", children: [AppSettings.ThemeData?.enableWideVersion && !isEmbedded &&
12
14
  _jsx("div", { className: "invisible sm:visible absolute inset-0 rounded-[25px] bg-linear-to-t from-secondary-800 to-secondary-300 pointer-events-none" }), _jsxs("div", { id: "widget", style: AppSettings.ThemeData?.cardBackgroundStyle, className: clsx("sm:pb-4 rounded-3xl w-full overflow-hidden relative bg-secondary-700 h-full flex flex-col has-expandContainerHeight:min-h-[650px]", {
13
15
  "max-sm:has-openpicker:min-h-svh max-sm:min-h-[99.8svh] sm:has-openpicker:min-h-[79svh]": AppSettings.ThemeData?.enableWideVersion,
16
+ "max-sm:min-h-[99svh]!": isEmbedded,
14
17
  "has-openpicker:min-h-[675px]": !AppSettings.ThemeData?.enableWideVersion
15
18
  }), children: [AppSettings.ApiVersion === 'testnet' &&
16
19
  _jsx("div", { className: "relative z-20", children: _jsx("div", { className: "absolute -top-1 right-[calc(50%-68px)] bg-warning-foreground py-0.5 px-10 rounded-b-md text-xs scale-75", children: "TESTNET" }) }), !hideMenu &&
@@ -12,6 +12,10 @@ export const ResolverProviders = ({ children, walletProviders }) => {
12
12
  .map(provider => provider.contractAddressProvider)
13
13
  .flat()
14
14
  .filter((provider) => Boolean(provider));
15
+ const rpcHealthCheckProviders = walletProviders
16
+ .map(provider => provider.rpcHealthCheckProvider)
17
+ .flat()
18
+ .filter((provider) => Boolean(provider));
15
19
  const isInitialized = useMemo(() => {
16
20
  // Extract balance providers from wallet providers
17
21
  const balanceProviders = walletProviders
@@ -32,9 +36,9 @@ export const ResolverProviders = ({ children, walletProviders }) => {
32
36
  .map(provider => provider.nftProvider)
33
37
  .flat()
34
38
  .filter((provider) => Boolean(provider));
35
- resolverService.setProviders(balanceProviders, gasProviders, addressUtilsProviders, nftProviders, transferProviders, contractAddressProviders);
39
+ resolverService.setProviders(balanceProviders, gasProviders, addressUtilsProviders, nftProviders, transferProviders, contractAddressProviders, rpcHealthCheckProviders);
36
40
  return true;
37
- }, [walletProviders, transferProviders]);
41
+ }, [walletProviders, transferProviders, contractAddressProviders, rpcHealthCheckProviders]);
38
42
  return (_jsx(ResolverContext.Provider, { value: { isInitialized }, children: children }));
39
43
  };
40
44
  export const useResolvers = () => {
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+ import { resolverService } from '../lib/resolvers/resolverService';
3
+ /**
4
+ * Hook to access RPC health check functionality for a specific network.
5
+ * Returns null if no RPC health check provider is available for the network.
6
+ *
7
+ * @param network - The network to check RPC health for
8
+ */
9
+ export function useRpcHealth(network) {
10
+ const resolver = resolverService.getRpcHealthCheckResolver();
11
+ const provider = resolver?.getProviderForNetwork(network);
12
+ // If no provider for this network, return null
13
+ if (!provider) {
14
+ return null;
15
+ }
16
+ // Call the hook from the provider
17
+ return provider.useRpcHealthCheck();
18
+ }
@@ -1,19 +1,28 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import React from 'react';
2
+ import React, { useEffect, useState } from 'react';
3
+ import inIframe from '../components/utils/inIframe';
3
4
  export const SettingsStateContext = React.createContext(null);
4
5
  export const SettingsProvider = ({ children, initialLayerswapData, initialSettings: initialSettings = {} }) => {
5
6
  const value = {
6
7
  settings: initialLayerswapData,
7
- initialSettings: mapLegacySettings(initialSettings)
8
+ initialSettings: mapLegacySettings(initialSettings),
9
+ isEmbedded: false,
8
10
  };
9
- return (_jsx(SettingsStateContext.Provider, { value: value, children: children }));
11
+ const [embedded, setEmbedded] = useState(false);
12
+ useEffect(() => {
13
+ setEmbedded(inIframe());
14
+ }, []);
15
+ return (_jsx(SettingsStateContext.Provider, { value: { ...value, isEmbedded: embedded }, children: children }));
10
16
  };
11
17
  export function useSettingsState() {
12
18
  const data = React.useContext(SettingsStateContext);
13
19
  if (data === undefined) {
14
20
  throw new Error('useSettingsState must be used within a SettingsProvider');
15
21
  }
16
- return data.settings;
22
+ return {
23
+ ...data.settings,
24
+ isEmbedded: data.isEmbedded,
25
+ };
17
26
  }
18
27
  export function useInitialSettings() {
19
28
  const data = React.useContext(SettingsStateContext);
@@ -27,3 +27,4 @@ export { default as shortenAddress } from "../components/utils/ShortenAddress";
27
27
  export * from "../context/swap";
28
28
  export { useWalletProvidersList } from "../components/Wallet/WalletProviders";
29
29
  export { ErrorHandler } from '../lib/ErrorHandler';
30
+ export { useRpcHealth } from "../context/rpcHealthContext";
@@ -143,20 +143,28 @@ function sortGroupedTokensByBalance(tokenElements, balances) {
143
143
  }).sort((a, b) => b.totalUSD - a.totalUSD);
144
144
  }
145
145
  function resolveSearch(routes, search, direction, balances, routesHistory) {
146
- const matchedNetworks = searchInNetworks(routes, search);
146
+ const matchedNetworks = searchInNetworks(routes, search, direction, balances);
147
147
  const matchedTokens = searchInTokens(routes, search).sort(sortSuggestedTokenElements(direction, balances, routesHistory));
148
148
  return [
149
149
  ...(matchedNetworks.length ? [resolveTitle('Networks'), ...matchedNetworks] : []),
150
150
  ...(matchedTokens.length ? [resolveTitle('Tokens'), ...matchedTokens] : [])
151
151
  ];
152
152
  }
153
- const searchInNetworks = (routes, search) => {
153
+ const searchInNetworks = (routes, search, direction, balances) => {
154
154
  const lower = search.toLowerCase().trim();
155
155
  return routes.filter(r => {
156
156
  const internalNameMatch = r.name.toLowerCase().includes(lower);
157
157
  const displayNameMatch = r.display_name?.toLowerCase().includes(lower);
158
158
  return internalNameMatch || displayNameMatch;
159
- }).map(r => ({ type: 'network', route: r }));
159
+ }).map(r => ({
160
+ type: 'network',
161
+ route: {
162
+ ...r,
163
+ tokens: (direction === "from" && balances)
164
+ ? sortNetworkTokens(r, balances)
165
+ : r.tokens
166
+ }
167
+ }));
160
168
  };
161
169
  const searchInTokens = (routes, search) => {
162
170
  const lower = search.toLowerCase().replace(/\s+/g, " ").trim();
@@ -311,8 +319,8 @@ const sortSuggestedTokenElements = (direction, balances, routesHistory) => (a, b
311
319
  }
312
320
  }
313
321
  if (routesHistory) {
314
- const a_used = getUsedCount(a, routesHistory);
315
- const b_used = getUsedCount(b, routesHistory);
322
+ const a_used = getUsedCount(a, routesHistory, direction);
323
+ const b_used = getUsedCount(b, routesHistory, direction);
316
324
  if (a_used !== b_used) {
317
325
  return b_used - a_used;
318
326
  }
@@ -324,8 +332,8 @@ const sortSuggestedTokenElements = (direction, balances, routesHistory) => (a, b
324
332
  const getNetworkTokenElementBalance = (item, balances) => {
325
333
  return (balances[item.route.route.name]?.balances?.find(b => b.token === item.route.token.symbol)?.amount || 0) * item.route.token.price_in_usd;
326
334
  };
327
- const getUsedCount = (item, history) => {
328
- return history[item.route.route.name]?.[item.route.token.symbol] || 0;
335
+ const getUsedCount = (item, history, direction) => {
336
+ return direction === "from" ? history.sourceRoutes?.[item.route.route.name]?.[item.route.token.symbol] || 0 : history.destinationRoutes?.[item.route.route.name]?.[item.route.token.symbol] || 0;
329
337
  };
330
338
  const getRank = (item, direction) => {
331
339
  switch (direction) {
@@ -18,7 +18,7 @@ export function resolveFormValidation({ values, maxAllowedAmount, minAllowedAmou
18
18
  if (!values.toAsset) {
19
19
  return { message: 'Select destination asset' };
20
20
  }
21
- if (!amount) {
21
+ if (amount === undefined || isNaN(Number(amount))) {
22
22
  return { message: 'Enter an amount' };
23
23
  }
24
24
  if (amount < 0) {
@@ -50,6 +50,12 @@ class LayerSwapApiClient {
50
50
  }
51
51
  ErrorHandler({
52
52
  type: 'APIError',
53
+ endpoint: endpoint,
54
+ status: reason.response?.status,
55
+ statusText: reason.response?.statusText,
56
+ responseData: reason.response?.data,
57
+ requestUrl: reason.request?.url,
58
+ requestMethod: reason.request?.method,
53
59
  message: error.message,
54
60
  name: error.name,
55
61
  stack: error.stack,
@@ -63,6 +63,7 @@ KnownInternalNames.Networks = (_b = class {
63
63
  _b.ImmutableXGoerli = "IMMUTABLEX_GOERLI",
64
64
  _b.ImmutableXSepolia = "IMMUTABLEX_SEPOLIA",
65
65
  _b.ImmutableZkEVM = "IMMUTABLEZK_MAINNET",
66
+ _b.ImmutableZkTestnet = "IMMUTABLEZK_TESTNET",
66
67
  _b.AstarMainnet = "ASTAR_MAINNET",
67
68
  _b.NahmiiMainnet = "NAHMII_MAINNET",
68
69
  _b.RhinoFiMainnet = "RHINOFI_MAINNET",
@@ -4,6 +4,7 @@ import { AddressUtilsResolver } from '../../lib/address/addressUtilsResolver';
4
4
  import { NftBalanceResolver } from "../nft/nftBalanceResolver";
5
5
  import { TransferResolver } from "../transfers/transferResolver";
6
6
  import { ContractAddressResolver } from "../../lib/address/contractAddressResolver";
7
+ import { RpcHealthCheckResolver } from "../rpcHealth/rpcHealthCheckResolver";
7
8
  class UtilsResolverService {
8
9
  constructor() {
9
10
  this.balanceResolver = null;
@@ -12,14 +13,16 @@ class UtilsResolverService {
12
13
  this.nftResolver = null;
13
14
  this.transferResolver = null;
14
15
  this.contractAddressResolver = null;
16
+ this.rpcHealthCheckResolver = null;
15
17
  }
16
- setProviders(balanceProviders, gasProviders, addressUtilsProviders, nftProviders, transferProviders, contractAddressProviders) {
18
+ setProviders(balanceProviders, gasProviders, addressUtilsProviders, nftProviders, transferProviders, contractAddressProviders, rpcHealthCheckProviders) {
17
19
  this.balanceResolver = new BalanceResolver(balanceProviders);
18
20
  this.gasResolver = new GasResolver(gasProviders);
19
21
  this.addressUtilsResolver = new AddressUtilsResolver(addressUtilsProviders);
20
22
  this.nftResolver = new NftBalanceResolver(nftProviders);
21
23
  this.transferResolver = new TransferResolver(transferProviders);
22
24
  this.contractAddressResolver = new ContractAddressResolver(contractAddressProviders);
25
+ this.rpcHealthCheckResolver = new RpcHealthCheckResolver(rpcHealthCheckProviders);
23
26
  }
24
27
  getBalanceResolver() {
25
28
  if (!this.balanceResolver) {
@@ -57,5 +60,8 @@ class UtilsResolverService {
57
60
  }
58
61
  return this.contractAddressResolver;
59
62
  }
63
+ getRpcHealthCheckResolver() {
64
+ return this.rpcHealthCheckResolver;
65
+ }
60
66
  }
61
67
  export const resolverService = new UtilsResolverService();
@@ -0,0 +1,8 @@
1
+ export class RpcHealthCheckResolver {
2
+ constructor(providers) {
3
+ this.providers = providers || [];
4
+ }
5
+ getProviderForNetwork(network) {
6
+ return this.providers.find(p => p.supportsNetwork(network));
7
+ }
8
+ }
@@ -7,6 +7,7 @@ export * from './contract';
7
7
  export * from './transfer';
8
8
  export * from './nft';
9
9
  export * from './multiStepTransfer';
10
+ export * from './rpcHealth';
10
11
  export * from '../Models';
11
12
  export * from '../components/Pages/Swap/Withdraw/messages/TransactionMessages';
12
13
  export * from '../components/Pages/Swap/Withdraw/Wallet/Common/sharedTypes';
@@ -0,0 +1 @@
1
+ export {};