@getpara/react-sdk-lite 2.10.0 → 2.12.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 (55) hide show
  1. package/dist/modal/ParaModal.js +14 -1
  2. package/dist/modal/components/Account/Account.js +114 -22
  3. package/dist/modal/components/Account/AccountMonitorTx.d.ts +1 -0
  4. package/dist/modal/components/Account/AccountMonitorTx.js +256 -0
  5. package/dist/modal/components/Account/AccountSend/AccountSendAsset.js +2 -2
  6. package/dist/modal/components/Account/AccountSend/AccountSendForm.js +68 -10
  7. package/dist/modal/components/Account/AccountSend/context.d.ts +2 -0
  8. package/dist/modal/components/Account/AccountSend/context.js +50 -110
  9. package/dist/modal/components/Account/AccountWallet.js +1 -6
  10. package/dist/modal/components/Account/AccountWalletSelect.js +5 -12
  11. package/dist/modal/components/AddFunds/AddFundsContext.js +70 -25
  12. package/dist/modal/components/AddFunds/AddFundsReceive.js +1 -1
  13. package/dist/modal/components/AddFunds/AddFundsSettings.js +134 -29
  14. package/dist/modal/components/AuthInput/hooks/useDropdownPosition.d.ts +1 -1
  15. package/dist/modal/components/AuthInput/hooks/useDropdownPosition.js +25 -17
  16. package/dist/modal/components/AuthOptions/AuthOptions.js +1 -1
  17. package/dist/modal/components/Body/Body.js +4 -0
  18. package/dist/modal/components/Controls/ChainSelect.js +2 -3
  19. package/dist/modal/components/ErrorBoundary.d.ts +20 -0
  20. package/dist/modal/components/ErrorBoundary.js +27 -0
  21. package/dist/modal/components/ExternalWalletStep/ExternalWalletStep.js +1 -1
  22. package/dist/modal/components/OnRampComponents/OnRampProviderButton.js +3 -8
  23. package/dist/modal/components/WalletSelectOld/WalletSelectOld.js +6 -13
  24. package/dist/modal/components/common.d.ts +10 -1
  25. package/dist/modal/components/common.js +44 -11
  26. package/dist/modal/hooks/index.d.ts +1 -0
  27. package/dist/modal/hooks/index.js +1 -0
  28. package/dist/modal/hooks/useFarcasterLogin.js +1 -1
  29. package/dist/modal/hooks/useSendMutations.d.ts +51 -0
  30. package/dist/modal/hooks/useSendMutations.js +170 -0
  31. package/dist/modal/hooks/useTelegramLogin.js +1 -1
  32. package/dist/modal/hooks/useTransactionMonitoring.d.ts +1 -0
  33. package/dist/modal/hooks/useTransactionMonitoring.js +175 -0
  34. package/dist/modal/index.d.ts +1 -1
  35. package/dist/modal/index.js +1 -1
  36. package/dist/modal/stores/index.d.ts +1 -0
  37. package/dist/modal/stores/index.js +1 -0
  38. package/dist/modal/stores/modal/actions.js +0 -1
  39. package/dist/modal/stores/modal/useModalSessionStore.d.ts +28 -0
  40. package/dist/modal/stores/modal/useModalSessionStore.js +26 -0
  41. package/dist/modal/stores/modal/useModalStore.d.ts +2 -3
  42. package/dist/modal/stores/modal/useModalStore.js +2 -2
  43. package/dist/modal/utils/onramps.d.ts +61 -0
  44. package/dist/modal/utils/onramps.js +112 -0
  45. package/dist/modal/utils/steps.d.ts +4 -2
  46. package/dist/modal/utils/steps.js +6 -2
  47. package/dist/provider/hooks/mutations/utils.js +1 -1
  48. package/dist/provider/hooks/utils/useAutoSessionKeepAlive.js +1 -1
  49. package/dist/provider/hooks/utils/useEventListeners.js +2 -2
  50. package/dist/provider/hooks/utils/useModal.d.ts +2 -1
  51. package/dist/provider/hooks/utils/useModal.js +10 -3
  52. package/dist/provider/providers/ExternalWalletProvider.js +2 -2
  53. package/package.json +9 -8
  54. package/dist/modal/utils/validateOnRampConfig.d.ts +0 -5
  55. package/dist/modal/utils/validateOnRampConfig.js +0 -32
@@ -6,17 +6,17 @@ import {
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
7
  import { useMemo, useState } from "react";
8
8
  import { useAddFunds } from "./AddFundsContext.js";
9
+ import { isAmountWithinProviderLimits, PROVIDER_LIMITS } from "../../utils/onramps.js";
9
10
  import { CpslButton, CpslIcon, CpslRow, CpslText } from "@getpara/react-components";
10
11
  import { AssetIcon, contentMotionProps } from "../common.js";
11
12
  import { QuantityInput } from "../QuantityInput.js";
12
- import { formatAssetQuantity } from "@getpara/web-sdk";
13
+ import { formatAssetQuantity, OnRampPurchaseType, EnabledFlow } from "@getpara/web-sdk";
13
14
  import { OnRampStep, useModalStore } from "../../stores/index.js";
14
15
  import { safeStyled, getAssetCode, getNetworkName } from "@getpara/react-common";
15
16
  import { AnimatePresence, motion, useIsPresent } from "framer-motion";
16
17
  import { AddFundsAsset } from "./AddFundsAsset.js";
17
18
  import { WalletSelectOld } from "../WalletSelectOld/WalletSelectOld.js";
18
19
  import { useAccount } from "../../../provider/index.js";
19
- import { useDebounce } from "../../hooks/useDebounce.js";
20
20
  import { useAssetInfo } from "../../../provider/hooks/utils/useAssetInfo.js";
21
21
  import { AddFundsNetwork } from "./AddFundsNetwork.js";
22
22
  import { useStore } from "../../../provider/stores/useStore.js";
@@ -31,6 +31,7 @@ function AddFundsSettings() {
31
31
  const { embedded } = useAccount();
32
32
  const {
33
33
  assets,
34
+ networks,
34
35
  narrowedNetworks,
35
36
  asset,
36
37
  setAsset,
@@ -40,25 +41,90 @@ function AddFundsSettings() {
40
41
  setFiatQuantity,
41
42
  isProviderAllowed,
42
43
  settingsStep,
43
- TestModeAlert
44
+ TestModeAlert,
45
+ onRampConfig,
46
+ activeWallet,
47
+ tab
44
48
  } = useAddFunds();
45
- const [value, setValue] = useState(parseFloat(fiatQuantity || "25.00").toFixed(2));
46
- const dbValue = useDebounce(value, 200);
49
+ const [value, setValue] = useState(parseFloat(String(fiatQuantity || "25.00")).toFixed(2));
47
50
  const assetQuantity = useMemo(() => {
48
51
  var _a, _b, _c;
49
52
  if (!asset) {
50
53
  return -1;
51
54
  }
52
55
  const assetValue = (_c = (_b = (_a = assetInfo.data) == null ? void 0 : _a[asset]) == null ? void 0 : _b.price) == null ? void 0 : _c.value;
53
- const dbValueFloat = !dbValue || isNaN(parseFloat(dbValue)) ? null : parseFloat(dbValue);
54
- if (!assetValue || !asset || !dbValueFloat) {
56
+ const valueFloat = !value || isNaN(parseFloat(value)) ? null : parseFloat(value);
57
+ if (!assetValue || !asset || !valueFloat) {
55
58
  return -1;
56
59
  }
57
60
  if (["TETHER", "USDC", "CUSD"].includes(asset)) {
58
- return dbValueFloat;
61
+ return valueFloat;
62
+ }
63
+ return valueFloat / assetValue;
64
+ }, [asset, assetInfo, value]);
65
+ const providerAvailability = useMemo(() => {
66
+ if (!value || value.trim() === "") {
67
+ return { hasProviders: false, reason: null, minAmount: null, maxAmount: null };
68
+ }
69
+ const hasBasicSupport = Object.values(isProviderAllowed).some((allowed) => allowed === true);
70
+ if (!hasBasicSupport) {
71
+ return { hasProviders: false, reason: "NO_SUPPORT", minAmount: null, maxAmount: null };
72
+ }
73
+ if (!onRampConfig || !(activeWallet == null ? void 0 : activeWallet.type) || !asset || !network) {
74
+ return { hasProviders: hasBasicSupport, reason: null, minAmount: null, maxAmount: null };
75
+ }
76
+ const amount = parseFloat(value);
77
+ if (isNaN(amount)) {
78
+ return { hasProviders: false, reason: "INVALID_AMOUNT", minAmount: null, maxAmount: null };
79
+ }
80
+ const purchaseType = tab === EnabledFlow.BUY ? OnRampPurchaseType.BUY : OnRampPurchaseType.SELL;
81
+ let hasAtLeastOne = false;
82
+ let allBelowMin = true;
83
+ let allAboveMax = true;
84
+ const mins = [];
85
+ const maxes = [];
86
+ onRampConfig.providers.forEach((id) => {
87
+ if (!isProviderAllowed[id]) return;
88
+ const withinLimits = isAmountWithinProviderLimits(amount, id, purchaseType);
89
+ if (withinLimits) {
90
+ hasAtLeastOne = true;
91
+ allBelowMin = false;
92
+ allAboveMax = false;
93
+ } else {
94
+ const limits = PROVIDER_LIMITS[id][purchaseType];
95
+ if (limits.min !== null) mins.push(limits.min);
96
+ if (limits.max !== null) maxes.push(limits.max);
97
+ if (limits.min !== null && amount >= limits.min) allBelowMin = false;
98
+ if (limits.max !== null && amount <= limits.max) allAboveMax = false;
99
+ }
100
+ });
101
+ if (hasAtLeastOne) {
102
+ return { hasProviders: true, reason: null, minAmount: null, maxAmount: null };
103
+ }
104
+ if (allBelowMin && mins.length > 0) {
105
+ return {
106
+ hasProviders: false,
107
+ reason: "BELOW_MIN",
108
+ minAmount: Math.min(...mins),
109
+ maxAmount: null
110
+ };
111
+ }
112
+ if (allAboveMax && maxes.length > 0) {
113
+ return {
114
+ hasProviders: false,
115
+ reason: "ABOVE_MAX",
116
+ minAmount: null,
117
+ maxAmount: Math.max(...maxes)
118
+ };
59
119
  }
60
- return dbValueFloat / assetValue;
61
- }, [asset, assetInfo, dbValue]);
120
+ return {
121
+ hasProviders: false,
122
+ reason: "NO_PROVIDERS",
123
+ minAmount: null,
124
+ maxAmount: null
125
+ };
126
+ }, [isProviderAllowed, value, onRampConfig, activeWallet == null ? void 0 : activeWallet.type, asset, network, tab]);
127
+ const hasAvailableProviders = providerAvailability.hasProviders;
62
128
  const { key, Content } = useMemo(() => {
63
129
  switch (settingsStep) {
64
130
  case "NO_PROVIDERS":
@@ -70,6 +136,7 @@ function AddFundsSettings() {
70
136
  ] })
71
137
  };
72
138
  case "FORM": {
139
+ const isClickable = !!network && (assets.length > 1 || networks.length > 1);
73
140
  return {
74
141
  key: "form",
75
142
  Content: /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -79,7 +146,9 @@ function AddFundsSettings() {
79
146
  AssetButton,
80
147
  {
81
148
  variant: "tertiary",
82
- onClick: network && (assets.length > 1 || narrowedNetworks.length > 1) ? () => {
149
+ $isClickable: isClickable,
150
+ cursor: isClickable ? "pointer" : "auto",
151
+ onClick: isClickable ? () => {
83
152
  switch (true) {
84
153
  case assets.length === 1:
85
154
  setNetwork(null);
@@ -92,7 +161,7 @@ function AddFundsSettings() {
92
161
  children: [
93
162
  /* @__PURE__ */ jsx(AssetIcon, { asset, size: "24px" }),
94
163
  /* @__PURE__ */ jsx(CpslText, { variant: "bodyS", color: "contrast", children: assetQuantity > 0 ? formatAssetQuantity({ quantity: assetQuantity, symbol: getAssetCode(asset) }) : getAssetCode(asset) }),
95
- /* @__PURE__ */ jsx(CpslIcon, { icon: "chevronRight", size: "24px", color: "var(--cpsl-color-text-contrast)" })
164
+ isClickable && /* @__PURE__ */ jsx(CpslIcon, { icon: "chevronRight", size: "24px", color: "var(--cpsl-color-text-contrast)" })
96
165
  ]
97
166
  }
98
167
  ),
@@ -101,21 +170,37 @@ function AddFundsSettings() {
101
170
  getNetworkName(network)
102
171
  ] })
103
172
  ] }),
104
- /* @__PURE__ */ jsxs(
105
- CpslButton,
106
- {
107
- fullWidth: true,
108
- disabled: value === "",
109
- onClick: () => {
110
- setFiatQuantity(value != null ? value : void 0);
111
- setOnRampStep(OnRampStep.PROVIDER);
112
- },
113
- children: [
114
- "Continue",
115
- /* @__PURE__ */ jsx(CpslIcon, { icon: "arrow" })
116
- ]
117
- }
118
- )
173
+ /* @__PURE__ */ jsxs(CpslRow, { col: true, gap: "8px", children: [
174
+ /* @__PURE__ */ jsxs(
175
+ CpslButton,
176
+ {
177
+ fullWidth: true,
178
+ disabled: !hasAvailableProviders,
179
+ onClick: () => {
180
+ setFiatQuantity(value != null ? value : void 0);
181
+ setOnRampStep(OnRampStep.PROVIDER);
182
+ },
183
+ children: [
184
+ "Continue",
185
+ /* @__PURE__ */ jsx(CpslIcon, { icon: "arrow" })
186
+ ]
187
+ }
188
+ ),
189
+ !hasAvailableProviders && value !== "" && asset && network && (() => {
190
+ const { reason, minAmount, maxAmount } = providerAvailability;
191
+ let message = "No providers available for this transaction";
192
+ if (reason === "INVALID_AMOUNT") {
193
+ message = "Please enter a valid amount";
194
+ } else if (reason === "BELOW_MIN" && minAmount !== null) {
195
+ message = `Amount too low, must be $${minAmount.toFixed(2)} or greater`;
196
+ } else if (reason === "ABOVE_MAX" && maxAmount !== null) {
197
+ message = `Amount too high, must be $${maxAmount.toFixed(2)} or less`;
198
+ } else if (reason) {
199
+ message = "No providers available for this transaction";
200
+ }
201
+ return /* @__PURE__ */ jsx(CpslText, { variant: "bodyXS", color: "error", align: "center", children: message });
202
+ })()
203
+ ] })
119
204
  ] })
120
205
  };
121
206
  }
@@ -136,7 +221,18 @@ function AddFundsSettings() {
136
221
  };
137
222
  }
138
223
  }
139
- }, [asset, network, assets, narrowedNetworks, isProviderAllowed, assetQuantity, isPresent, value, hideWallets]);
224
+ }, [
225
+ asset,
226
+ network,
227
+ assets,
228
+ narrowedNetworks,
229
+ isProviderAllowed,
230
+ assetQuantity,
231
+ isPresent,
232
+ value,
233
+ hideWallets,
234
+ providerAvailability
235
+ ]);
140
236
  const isWalletSelectVisible = useMemo(() => {
141
237
  return settingsStep && ["FORM", "NO_PROVIDERS"].includes(settingsStep) && (embedded == null ? void 0 : embedded.wallets) && embedded.wallets.length > 1;
142
238
  }, [embedded, settingsStep]);
@@ -171,8 +267,17 @@ const AssetButton = safeStyled(CpslButton)`
171
267
  --button-padding-top: 8px;
172
268
  --button-padding-bottom: 8px;
173
269
  --button-padding-start: 8px;
174
- --button-padding-end: 8px;
270
+ --button-padding-end: ${({ $isClickable }) => $isClickable ? "8px" : "16px"};
175
271
  --button-gap: 4px;
272
+
273
+ ${({ $isClickable }) => !$isClickable && `
274
+ &:hover {
275
+ --button-tertiary-hover-background-color: var(--button-tertiary-background-color);
276
+ --button-tertiary-hover-border-color: var(--button-tertiary-border-color);
277
+ --button-tertiary-active-background-color: var(--button-tertiary-background-color);
278
+ --button-tertiary-active-border-color: var(--button-tertiary-border-color);
279
+ }
280
+ `}
176
281
  `;
177
282
  export {
178
283
  AddFundsSettings
@@ -2,6 +2,6 @@ import { MutableRefObject } from 'react';
2
2
  export declare const useDropdownPosition: (inputRef: MutableRefObject<HTMLCpslInputElement | HTMLDivElement | null>) => {
3
3
  dropdownMaxHeight: number | undefined;
4
4
  dropdownWidth: number | undefined;
5
- mobileAnchor: number | undefined;
5
+ mobileAnchor: number | null;
6
6
  resize: () => void;
7
7
  };
@@ -1,31 +1,39 @@
1
1
  "use client";
2
2
  import "../../../../chunk-MMUBH76A.js";
3
- import { useEffect, useState } from "react";
3
+ import { useCallback, useEffect, useState } from "react";
4
+ import { useModalStore } from "../../../stores/index.js";
4
5
  const useDropdownPosition = (inputRef) => {
5
6
  const [dropdownMaxHeight, setDropdownMaxHeight] = useState();
6
7
  const [dropdownWidth, setDropdownWidth] = useState();
7
- const [mobileAnchor, setMobileAnchor] = useState();
8
- const resize = () => {
9
- var _a, _b, _c, _d;
10
- if (typeof window !== "undefined") {
11
- const newMaxHeight = Math.max(
12
- window.innerHeight - ((_b = (_a = inputRef == null ? void 0 : inputRef.current) == null ? void 0 : _a.getBoundingClientRect().bottom) != null ? _b : 0) - 20,
13
- window.innerHeight * 0.25
14
- );
15
- setDropdownMaxHeight(newMaxHeight);
16
- setDropdownWidth((_c = inputRef == null ? void 0 : inputRef.current) == null ? void 0 : _c.getBoundingClientRect().width);
17
- setMobileAnchor((_d = inputRef == null ? void 0 : inputRef.current) == null ? void 0 : _d.getBoundingClientRect().height);
8
+ const [mobileAnchor, setMobileAnchor] = useState(null);
9
+ const modalContainerRef = useModalStore((state) => state.refs.modalContainer);
10
+ const resize = useCallback(() => {
11
+ if (typeof window !== "undefined" && inputRef.current) {
12
+ const rect = inputRef.current.getBoundingClientRect();
13
+ const newMaxHeight = Math.max(window.innerHeight - rect.bottom - 20, window.innerHeight * 0.25);
14
+ setDropdownMaxHeight((prev) => prev !== newMaxHeight ? newMaxHeight : prev);
15
+ setDropdownWidth((prev) => prev !== rect.width ? rect.width : prev);
16
+ const isMobile = window.innerWidth <= 480;
17
+ if (isMobile) {
18
+ const modalContainer = modalContainerRef.current;
19
+ if (modalContainer) {
20
+ const modalRect = modalContainer.getBoundingClientRect();
21
+ const topFromModal = rect.top - modalRect.top;
22
+ const bottomFromModal = topFromModal + rect.height;
23
+ setMobileAnchor((prev) => prev !== bottomFromModal ? bottomFromModal : prev);
24
+ }
25
+ } else {
26
+ setMobileAnchor(null);
27
+ }
18
28
  }
19
- };
20
- if (inputRef.current && !dropdownMaxHeight) {
21
- resize();
22
- }
29
+ }, [inputRef, modalContainerRef]);
23
30
  useEffect(() => {
31
+ resize();
24
32
  typeof window !== "undefined" && window.addEventListener("resize", resize);
25
33
  return () => {
26
34
  typeof window !== "undefined" && window.removeEventListener("resize", resize);
27
35
  };
28
- }, []);
36
+ }, [resize]);
29
37
  return { dropdownMaxHeight, dropdownWidth, mobileAnchor, resize };
30
38
  };
31
39
  export {
@@ -50,7 +50,7 @@ const AuthOptions = ({
50
50
  );
51
51
  }
52
52
  return /* @__PURE__ */ jsx(Fragment, { children: Methods });
53
- }, [oAuthMethods, disableEmailLogin, disablePhoneLogin, isGuestModeEnabled, wallets]);
53
+ }, [oAuthMethods, disableEmailLogin, disablePhoneLogin, isGuestModeEnabled, wallets, defaultAuth]);
54
54
  return /* @__PURE__ */ jsxs(Container, { children: [
55
55
  guestAddFundsTab && /* @__PURE__ */ jsxs(CompleteAccountSetup, { children: [
56
56
  /* @__PURE__ */ jsx(CompleteAccountIcon, { icon: "stars02", size: "16px" }),
@@ -46,6 +46,7 @@ import { Footer } from "../Footer/Footer.js";
46
46
  import { renderTextWithLinks } from "../../utils/renderTextWithLinks.js";
47
47
  import { AccountWallet } from "../Account/AccountWallet.js";
48
48
  import { AccountSend } from "../Account/AccountSend/index.js";
49
+ import { AccountMonitorTx } from "../Account/AccountMonitorTx.js";
49
50
  const MIN_HEIGHT = {
50
51
  [ModalStep.ADD_FUNDS_AWAITING]: "680px"
51
52
  };
@@ -219,6 +220,9 @@ const Body = ({
219
220
  case ModalStep.ACCOUNT_SEND_NETWORK: {
220
221
  return /* @__PURE__ */ jsx(AccountSend, { step: "SEND_NETWORK" });
221
222
  }
223
+ case ModalStep.ACCOUNT_MONITOR_TX: {
224
+ return /* @__PURE__ */ jsx(AccountMonitorTx, {});
225
+ }
222
226
  default: {
223
227
  if (IFrameSteps.includes(currentStep)) {
224
228
  return null;
@@ -48,7 +48,7 @@ const ChainSelect = () => {
48
48
  return null;
49
49
  }
50
50
  const chainIdToUse = chainIdSwitchingTo != null ? chainIdSwitchingTo : chainId;
51
- return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(HeaderSelectContainer, { ref: containerRef, id: "inputContainer", children: /* @__PURE__ */ jsxs(
51
+ return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(HeaderSelectContainer, { ref: containerRef, children: /* @__PURE__ */ jsxs(
52
52
  HeaderSelect,
53
53
  {
54
54
  selectedValue: (_a = chainIdToUse == null ? void 0 : chainIdToUse.toString()) != null ? _a : "",
@@ -57,10 +57,9 @@ const ChainSelect = () => {
57
57
  },
58
58
  showFormattedSelectedItem: true,
59
59
  placeholder: "Choose chain...",
60
- anchorElId: "inputContainer",
61
60
  dropdownMaxHeight,
62
61
  $width: dropdownWidth != null ? dropdownWidth : 0,
63
- $top: (mobileAnchor != null ? mobileAnchor : 0) + 16 + 1,
62
+ $top: mobileAnchor != null ? mobileAnchor : void 0,
64
63
  autoWidth: true,
65
64
  alignCenter: true,
66
65
  selectedItemVariant: "bodyXS",
@@ -0,0 +1,20 @@
1
+ import { Component, ErrorInfo, ReactNode } from 'react';
2
+ interface Props {
3
+ children: ReactNode;
4
+ fallback?: ReactNode;
5
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
6
+ }
7
+ interface State {
8
+ hasError: boolean;
9
+ }
10
+ /**
11
+ * Error boundary component that catches JavaScript errors in child components
12
+ * and displays a fallback UI instead of crashing the entire component tree.
13
+ */
14
+ export declare class ErrorBoundary extends Component<Props, State> {
15
+ constructor(props: Props);
16
+ static getDerivedStateFromError(): State;
17
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
18
+ render(): ReactNode;
19
+ }
20
+ export {};
@@ -0,0 +1,27 @@
1
+ "use client";
2
+ import "../../chunk-MMUBH76A.js";
3
+ import { Component } from "react";
4
+ class ErrorBoundary extends Component {
5
+ constructor(props) {
6
+ super(props);
7
+ this.state = { hasError: false };
8
+ }
9
+ static getDerivedStateFromError() {
10
+ return { hasError: true };
11
+ }
12
+ componentDidCatch(error, errorInfo) {
13
+ var _a, _b;
14
+ console.error("[ErrorBoundary] Caught error:", error, errorInfo);
15
+ (_b = (_a = this.props).onError) == null ? void 0 : _b.call(_a, error, errorInfo);
16
+ }
17
+ render() {
18
+ var _a;
19
+ if (this.state.hasError) {
20
+ return (_a = this.props.fallback) != null ? _a : null;
21
+ }
22
+ return this.props.children;
23
+ }
24
+ }
25
+ export {
26
+ ErrorBoundary
27
+ };
@@ -49,7 +49,7 @@ const ExternalWalletMobileConnect = ({
49
49
  if (isError && onRetryClick) {
50
50
  yield onRetryClick();
51
51
  } else {
52
- yield openMobileUrl(qrUri);
52
+ openMobileUrl(qrUri);
53
53
  }
54
54
  });
55
55
  if (wallet.type === "SOLANA" || isMobile() && !isTablet()) {
@@ -16,10 +16,10 @@ const OnRampProviderButton = ({ config, index, onClick: _onClick }) => {
16
16
  return /* @__PURE__ */ jsx(StyledButton, { variant: "tertiary", fullWidth: true, onClick, children: /* @__PURE__ */ jsxs(Container, { children: [
17
17
  /* @__PURE__ */ jsx(IconContainer, { children: /* @__PURE__ */ jsx(CpslIcon, { icon, color: backgroundColors[0] }) }),
18
18
  /* @__PURE__ */ jsxs(ProviderInfoContainer, { children: [
19
- /* @__PURE__ */ jsx(Text, { variant: "bodyL", weight: "medium", children: name }),
19
+ /* @__PURE__ */ jsx(CpslText, { variant: "bodyL", weight: "medium", children: name }),
20
20
  /* @__PURE__ */ jsxs(ProviderInfoInnerContainer, { children: [
21
- /* @__PURE__ */ jsx(Text, { variant: "bodyXS", weight: "medium", children: methods.join(", ") }),
22
- /* @__PURE__ */ jsx(Text, { variant: "bodyXS", weight: "medium", children: feeString })
21
+ /* @__PURE__ */ jsx(CpslText, { variant: "bodyXS", weight: "medium", children: methods.join(", ") }),
22
+ /* @__PURE__ */ jsx(CpslText, { variant: "bodyXS", weight: "medium", children: feeString })
23
23
  ] })
24
24
  ] })
25
25
  ] }) });
@@ -57,11 +57,6 @@ const IconContainer = safeStyled.span`
57
57
  width: 48px;
58
58
  flex-shrink: 0;
59
59
  `;
60
- const Text = safeStyled(CpslText)`
61
- &::part(text-element) {
62
- color: #fff;
63
- }
64
- `;
65
60
  export {
66
61
  OnRampProviderButton
67
62
  };
@@ -4,9 +4,10 @@ import { jsx, jsxs } from "react/jsx-runtime";
4
4
  import { useEffect, useMemo, useRef } from "react";
5
5
  import { useInternalClient } from "../../../provider/hooks/utils/useInternalClient.js";
6
6
  import { useDropdownPosition } from "../AuthInput/hooks/useDropdownPosition.js";
7
- import { MOBILE_SIZE, safeStyled, useCopyToClipboard, WalletTypeIcon as WalletTypeIconBase } from "@getpara/react-common";
7
+ import { safeStyled, useCopyToClipboard, WalletTypeIcon as WalletTypeIconBase } from "@getpara/react-common";
8
8
  import { useAccount, useWallet, useWalletState } from "../../../provider/index.js";
9
9
  import { CpslButton, CpslIcon, CpslSelect, CpslSelectItem, CpslText } from "@getpara/react-components";
10
+ import { getMobilePopoverPositionCSS } from "../common.js";
10
11
  const getValue = (id, type) => {
11
12
  return id && type ? `${id}~${type}` : void 0;
12
13
  };
@@ -69,7 +70,7 @@ const WalletSelectOld = ({
69
70
  }, [activeWallet, availableWallets, dropdownMaxHeight]);
70
71
  return /* @__PURE__ */ jsxs(Container, { style, children: [
71
72
  isMultiWallet && !noTitle && /* @__PURE__ */ jsx(CpslText, { variant: "bodyM", color: "secondary", weight: "semiBold", children: "Select Wallet" }),
72
- /* @__PURE__ */ jsx(SelectContainer, { ref: containerRef, id: "addressInputContainerOld", style: { width: "100%" }, children: /* @__PURE__ */ jsxs(
73
+ /* @__PURE__ */ jsx(SelectContainer, { ref: containerRef, style: { width: "100%" }, children: /* @__PURE__ */ jsxs(
73
74
  Select,
74
75
  {
75
76
  selectedValue: getValue(activeWallet == null ? void 0 : activeWallet.id, activeWallet == null ? void 0 : activeWallet.type),
@@ -79,10 +80,9 @@ const WalletSelectOld = ({
79
80
  },
80
81
  showFormattedSelectedItem: true,
81
82
  placeholder: "Choose wallet...",
82
- anchorElId: "addressInputContainerOld",
83
83
  dropdownMaxHeight,
84
84
  $width: dropdownWidth != null ? dropdownWidth : 0,
85
- $top: (mobileAnchor != null ? mobileAnchor : 0) + 220 + 1,
85
+ $top: mobileAnchor != null ? mobileAnchor : void 0,
86
86
  selectedItemVariant: "bodyXS",
87
87
  icon: isMultiWallet ? "chevronUp" : null,
88
88
  disabled: !isMultiWallet,
@@ -127,15 +127,8 @@ const Select = safeStyled(CpslSelect)`
127
127
 
128
128
  &::part(popover) {
129
129
  /* Have to adjust the top of the popover here since we're using a transform on the modal which causes fixed position items to not be relative to the viewport */
130
- @media (max-width: ${MOBILE_SIZE}px) {
131
- top: ${({ $top }) => $top ? `${$top}px` : "0px"};
132
- bottom: 16px;
133
- }
134
- cpsl-auth-modal.force-mobile-media & {
135
- top: ${({ $top }) => $top ? `${$top}px` : "0px"};
136
- bottom: 16px;
137
- }
138
- }
130
+ ${({ $top }) => getMobilePopoverPositionCSS($top)}
131
+ }
139
132
 
140
133
 
141
134
  &::part(icon) {
@@ -1,6 +1,11 @@
1
1
  import { CpslInput, CpslText, CpslTileButton } from '@getpara/react-components';
2
2
  import { TLinkedAccountType, TNetwork, TOnRampAsset } from '@getpara/web-sdk';
3
- import { ComponentProps, PropsWithChildren } from 'react';
3
+ import { ComponentProps, PropsWithChildren, ReactNode } from 'react';
4
+ /**
5
+ * Generates CSS for mobile positioning of select dropdowns.
6
+ * Adjusts popover position when modal uses transform which affects fixed positioning.
7
+ */
8
+ export declare const getMobilePopoverPositionCSS: ($top?: number) => string;
4
9
  export declare const SpinnerContainer: import("styled-components/dist/types.js").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
5
10
  export declare const QRContainer: import("styled-components/dist/types.js").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
6
11
  export declare const InfoBoxContent: import("styled-components/dist/types.js").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
@@ -59,6 +64,10 @@ export declare function GradientScroll({ height, gap, children }: PropsWithChild
59
64
  export declare const HeroGenericIcon: ({ accountType }: {
60
65
  accountType: "EMAIL" | "PHONE";
61
66
  }) => import("react/jsx-runtime").JSX.Element;
67
+ export declare const ExplorerLink: ({ href, text }: {
68
+ href: string;
69
+ text: ReactNode;
70
+ }) => import("react/jsx-runtime").JSX.Element;
62
71
  export * from './SearchableButtonList.js';
63
72
  export * from './QuantityInput.js';
64
73
  export { AnimatedHeightWrapper } from './Body/AnimatedHeightWrapper.js';
@@ -4,11 +4,24 @@ import {
4
4
  __spreadProps,
5
5
  __spreadValues
6
6
  } from "../../chunk-MMUBH76A.js";
7
- import { jsx } from "react/jsx-runtime";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { CpslIcon, CpslInput, CpslSelect, CpslSelectItem, CpslText, CpslTileButton } from "@getpara/react-components";
9
9
  import { ACCOUNT_TYPES, safeStyled, MOBILE_SIZE, NETWORKS, ON_RAMP_ASSETS } from "@getpara/react-common";
10
10
  import { useStore } from "../../provider/stores/useStore.js";
11
11
  import { useEffect, useRef, useState } from "react";
12
+ const getMobilePopoverPositionCSS = ($top) => {
13
+ if ($top === void 0 || $top === null) return "";
14
+ return `
15
+ @media (max-width: ${MOBILE_SIZE}px) {
16
+ top: ${$top}px;
17
+ bottom: 16px;
18
+ }
19
+ cpsl-auth-modal.force-mobile-media & {
20
+ top: ${$top}px;
21
+ bottom: 16px;
22
+ }
23
+ `;
24
+ };
12
25
  const SpinnerContainer = safeStyled.div`
13
26
  display: flex;
14
27
  align-items: center;
@@ -99,16 +112,9 @@ const HeaderSelect = safeStyled(CpslSelect)`
99
112
  }
100
113
 
101
114
  &::part(popover) {
102
- /* Have to adjust the top of the popover here since we're using a transform on the modal which causes fixed position items to not be relative to the viewport */
103
- @media (max-width: ${MOBILE_SIZE}px) {
104
- top: ${({ $top }) => $top ? `${$top}px` : "0px"};
105
- bottom: 16px;
106
- }
107
- cpsl-auth-modal.force-mobile-media & {
108
- top: ${({ $top }) => $top ? `${$top}px` : "0px"};
109
- bottom: 16px;
115
+ /* Have to adjust the top of the popover here since we're using a transform on the modal which causes fixed position items to not be relative to the viewport */
116
+ ${({ $top }) => getMobilePopoverPositionCSS($top)}
110
117
  }
111
- }
112
118
 
113
119
  &::part(icon) {
114
120
  --icon-color: var(--cpsl-color-contrast);
@@ -276,6 +282,31 @@ const Avatar = safeStyled.div`
276
282
  justify-content: center;
277
283
  background-color: var(--cpsl-color-background-8);
278
284
  `;
285
+ const ExplorerLinkBase = safeStyled.a`
286
+ font-family: var(--cpsl-font-family);
287
+ font-size: 14px;
288
+ position: relative;
289
+ display: flex;
290
+ align-items: center;
291
+ justify-content: center;
292
+ width: 100%;
293
+ background: transparent;
294
+ border: none;
295
+ cursor: pointer;
296
+ color: var(--cpsl-color-text-primary);
297
+ --icon-color: var(--cpsl-color-text-primary);
298
+
299
+ &:hover {
300
+ color: var(--cpsl-color-text-contrast);
301
+ --icon-color: var(--cpsl-color-text-contrast);
302
+ }
303
+ `;
304
+ const ExplorerLink = ({ href, text }) => {
305
+ return /* @__PURE__ */ jsxs(ExplorerLinkBase, { target: "_blank", href, rel: "noopener noreferrer", children: [
306
+ /* @__PURE__ */ jsx("span", { children: text }),
307
+ /* @__PURE__ */ jsx(CpslIcon, { icon: "externalLink", size: "16px", style: { marginLeft: "6px" } })
308
+ ] });
309
+ };
279
310
  export * from "./SearchableButtonList.js";
280
311
  export * from "./QuantityInput.js";
281
312
  import { AnimatedHeightWrapper } from "./Body/AnimatedHeightWrapper.js";
@@ -286,6 +317,7 @@ export {
286
317
  CenteredText,
287
318
  ErrorContainer,
288
319
  ErrorIcon,
320
+ ExplorerLink,
289
321
  FilledDisabledInput,
290
322
  FullWidthFilledDisabledInput,
291
323
  GradientScroll,
@@ -304,5 +336,6 @@ export {
304
336
  QRContainer,
305
337
  SpinnerContainer,
306
338
  StepContainer,
307
- StyledCpslTileButton
339
+ StyledCpslTileButton,
340
+ getMobilePopoverPositionCSS
308
341
  };
@@ -1,4 +1,5 @@
1
1
  export * from './useDebounce.js';
2
2
  export * from './useFarcasterLogin.js';
3
3
  export * from './useGoBack.js';
4
+ export * from './useSendMutations.js';
4
5
  export * from './useTelegramLogin.js';
@@ -2,4 +2,5 @@
2
2
  export * from "./useDebounce.js";
3
3
  export * from "./useFarcasterLogin.js";
4
4
  export * from "./useGoBack.js";
5
+ export * from "./useSendMutations.js";
5
6
  export * from "./useTelegramLogin.js";
@@ -48,7 +48,7 @@ const useFarcasterLogin = ({
48
48
  if (!!event.data.payload) {
49
49
  const authObject = event.data.payload;
50
50
  try {
51
- yield verifyFarcaster(authObject);
51
+ verifyFarcaster(authObject);
52
52
  } catch (e) {
53
53
  (_b = (_a = refs.telegramIFrame.current) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.postMessage({ type: "FARCASTER_RETRY" }, "*");
54
54
  }