@getpara/react-sdk-lite 2.10.0 → 2.11.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 (40) hide show
  1. package/dist/modal/ParaModal.js +3 -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 +36 -109
  9. package/dist/modal/components/AddFunds/AddFundsContext.js +70 -25
  10. package/dist/modal/components/AddFunds/AddFundsReceive.js +1 -1
  11. package/dist/modal/components/AddFunds/AddFundsSettings.js +134 -29
  12. package/dist/modal/components/Body/Body.js +4 -0
  13. package/dist/modal/components/ErrorBoundary.d.ts +20 -0
  14. package/dist/modal/components/ErrorBoundary.js +27 -0
  15. package/dist/modal/components/OnRampComponents/OnRampProviderButton.js +3 -8
  16. package/dist/modal/components/common.d.ts +5 -1
  17. package/dist/modal/components/common.js +27 -1
  18. package/dist/modal/hooks/index.d.ts +1 -0
  19. package/dist/modal/hooks/index.js +1 -0
  20. package/dist/modal/hooks/useSendMutations.d.ts +51 -0
  21. package/dist/modal/hooks/useSendMutations.js +170 -0
  22. package/dist/modal/hooks/useTransactionMonitoring.d.ts +1 -0
  23. package/dist/modal/hooks/useTransactionMonitoring.js +175 -0
  24. package/dist/modal/index.d.ts +1 -1
  25. package/dist/modal/index.js +1 -1
  26. package/dist/modal/stores/index.d.ts +1 -0
  27. package/dist/modal/stores/index.js +1 -0
  28. package/dist/modal/stores/modal/actions.js +0 -1
  29. package/dist/modal/stores/modal/useModalSessionStore.d.ts +28 -0
  30. package/dist/modal/stores/modal/useModalSessionStore.js +26 -0
  31. package/dist/modal/stores/modal/useModalStore.d.ts +1 -3
  32. package/dist/modal/stores/modal/useModalStore.js +0 -1
  33. package/dist/modal/utils/onramps.d.ts +61 -0
  34. package/dist/modal/utils/onramps.js +112 -0
  35. package/dist/modal/utils/steps.d.ts +4 -2
  36. package/dist/modal/utils/steps.js +6 -2
  37. package/dist/provider/hooks/utils/useEventListeners.js +2 -2
  38. package/package.json +9 -8
  39. package/dist/modal/utils/validateOnRampConfig.d.ts +0 -5
  40. package/dist/modal/utils/validateOnRampConfig.js +0 -32
@@ -23,6 +23,7 @@ import { useStore } from "../provider/stores/useStore.js";
23
23
  import parsePhoneNumberFromString from "libphonenumber-js";
24
24
  import { useAuthActions } from "../provider/providers/AuthProvider.js";
25
25
  import { validateInput } from "./utils/authInputHelpers.js";
26
+ import { useTransactionMonitoring } from "./hooks/useTransactionMonitoring.js";
26
27
  defineCustomElements();
27
28
  const ParaModal = forwardRef((props, ref) => {
28
29
  const storedModalConfig = useStore((state) => state.modalConfig);
@@ -110,7 +111,7 @@ const ParaModal = forwardRef((props, ref) => {
110
111
  onClose,
111
112
  defaultAuthIdentifier
112
113
  }), rest),
113
- reactSdkVersion: "2.10.0"
114
+ reactSdkVersion: "2.11.0"
114
115
  });
115
116
  } catch (e) {
116
117
  }
@@ -187,6 +188,7 @@ const ParaModal = forwardRef((props, ref) => {
187
188
  break;
188
189
  }
189
190
  });
191
+ useTransactionMonitoring();
190
192
  useEffect(() => {
191
193
  if (isReady && isOpen && !isAccountLoading && !isInitialized.current) {
192
194
  initModal(isOpen);
@@ -2,10 +2,10 @@
2
2
  import "../../../chunk-MMUBH76A.js";
3
3
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
4
  import { safeStyled } from "@getpara/react-common";
5
- import { InnerStepContainer, StepContainer } from "../common.js";
5
+ import { ExplorerLink, InnerStepContainer, StepContainer } from "../common.js";
6
6
  import { CpslButton, CpslIcon, CpslSpinner, CpslText, CpslTileButton } from "@getpara/react-components";
7
- import { OnRampStep, useModalStore } from "../../stores/index.js";
8
- import { useEffect } from "react";
7
+ import { OnRampStep, useModalStore, useModalSessionStore } from "../../stores/index.js";
8
+ import { useEffect, useMemo } from "react";
9
9
  import { ModalStep } from "../../utils/steps.js";
10
10
  import { useInternalClient } from "../../../provider/hooks/utils/useInternalClient.js";
11
11
  import { useAccount, useWalletState } from "../../../provider/index.js";
@@ -13,17 +13,101 @@ import { EnabledFlow } from "@getpara/web-sdk";
13
13
  import { useAccountLinking } from "../../../provider/providers/AccountLinkProvider.js";
14
14
  import { useAssets } from "../../../provider/providers/AssetsProvider.js";
15
15
  import { AccountHeader } from "./AccountHeader.js";
16
+ import { AnimatePresence, motion } from "framer-motion";
16
17
  const Account = () => {
17
18
  const onRampConfig = useModalStore((state) => state.onRampConfig);
18
19
  const setStep = useModalStore((state) => state.setStep);
19
20
  const setGuestAddFundsTab = useModalStore((state) => state.setGuestAddFundsTab);
20
21
  const setOnRampStep = useModalStore((state) => state.setOnRampStep);
21
- const sendTx = useModalStore((state) => state.sendTx);
22
+ const sendTx = useModalSessionStore((state) => state.sendTx);
23
+ const sendTxStatus = useModalSessionStore((state) => {
24
+ var _a, _b, _c;
25
+ return (_c = (_b = (_a = state.sendTx) == null ? void 0 : _a.result) == null ? void 0 : _b.status) == null ? void 0 : _c.status;
26
+ });
27
+ const sendTxResult = useModalSessionStore((state) => {
28
+ var _a;
29
+ return (_a = state.sendTx) == null ? void 0 : _a.result;
30
+ });
22
31
  const para = useInternalClient();
23
32
  const { embedded } = useAccount();
24
33
  const { selectedWallet, setSelectedWallet } = useWalletState();
25
34
  const { isEnabled } = useAccountLinking();
26
35
  const { profileBalance } = useAssets();
36
+ const transactionMonitorContent = useMemo(() => {
37
+ var _a, _b, _c, _d;
38
+ if (!sendTx) return null;
39
+ if ((_b = (_a = sendTx == null ? void 0 : sendTx.result) == null ? void 0 : _a.status) == null ? void 0 : _b.status) {
40
+ const status = sendTx.result.status.status;
41
+ const confirmations = (_c = sendTx.result.status.confirmations) != null ? _c : 0;
42
+ const isPending = status === "PENDING" || status === "CONFIRMED" && confirmations < 1;
43
+ const isConfirmed = status === "CONFIRMED" && confirmations >= 1;
44
+ const isFailed = status === "FAILED";
45
+ let color, text, icon, key;
46
+ switch (true) {
47
+ case isConfirmed:
48
+ color = "var(--cpsl-color-utility-green)";
49
+ text = "Transaction confirmed";
50
+ icon = /* @__PURE__ */ jsx(CpslIcon, { icon: "check", size: "16px", color });
51
+ key = "confirmed";
52
+ break;
53
+ case isFailed:
54
+ color = "var(--cpsl-color-utility-red)";
55
+ text = "Transaction failed";
56
+ icon = /* @__PURE__ */ jsx(CpslIcon, { icon: "alertTriangle", size: "16px", color });
57
+ key = "failed";
58
+ break;
59
+ case isPending:
60
+ default:
61
+ color = "var(--cpsl-color-text-secondary)";
62
+ text = "Transaction in progress";
63
+ icon = /* @__PURE__ */ jsx(CpslSpinner, { size: "16px", barColor: color });
64
+ key = "pending";
65
+ break;
66
+ }
67
+ return /* @__PURE__ */ jsx(
68
+ AnimatedMonitorContainer,
69
+ {
70
+ variants: fadeVariants,
71
+ initial: "enter",
72
+ animate: "center",
73
+ exit: "exit",
74
+ transition: fadeTransition,
75
+ children: /* @__PURE__ */ jsxs(
76
+ AnimatedMonitorButton,
77
+ {
78
+ onClick: () => {
79
+ setStep(ModalStep.ACCOUNT_MONITOR_TX);
80
+ },
81
+ children: [
82
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "4px", color }, children: [
83
+ icon,
84
+ /* @__PURE__ */ jsx("span", { children: text })
85
+ ] }),
86
+ /* @__PURE__ */ jsx(CpslIcon, { icon: "chevronRight", size: "16px" })
87
+ ]
88
+ }
89
+ )
90
+ },
91
+ key
92
+ );
93
+ }
94
+ if ((_d = sendTx == null ? void 0 : sendTx.result) == null ? void 0 : _d.explorerUrl) {
95
+ return /* @__PURE__ */ jsx(
96
+ AnimatedMonitorContainer,
97
+ {
98
+ variants: fadeVariants,
99
+ initial: "enter",
100
+ animate: "center",
101
+ exit: "exit",
102
+ transition: fadeTransition,
103
+ children: /* @__PURE__ */ jsx(ExplorerLink, { href: sendTx.result.explorerUrl, text: "Monitor Transaction" })
104
+ },
105
+ "explorer"
106
+ );
107
+ }
108
+ return null;
109
+ }, [sendTx, sendTxStatus, sendTxResult, setStep]);
110
+ const transactionMonitor = /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: transactionMonitorContent });
27
111
  const isGuestMode = embedded.isConnected && embedded.isGuestMode;
28
112
  const cantBuyAndWithdraw = (para.externalWalletConnectionType === "CONNECTION_ONLY" || para.externalWalletConnectionType === "VERIFICATION") && !para.userId;
29
113
  const isOnRampLoaded = !!onRampConfig;
@@ -90,10 +174,7 @@ const Account = () => {
90
174
  }
91
175
  )
92
176
  ] }),
93
- !!(sendTx == null ? void 0 : sendTx.explorerUrl) && /* @__PURE__ */ jsxs(MonitorLink, { target: "_blank", href: sendTx.explorerUrl, rel: "noopener noreferrer", "data-testid": "para-monitor-tx", children: [
94
- /* @__PURE__ */ jsx("span", { children: "Monitor Transaction" }),
95
- /* @__PURE__ */ jsx(CpslIcon, { icon: "externalLink", size: "16px", style: { marginLeft: "6px" } })
96
- ] }),
177
+ transactionMonitor,
97
178
  /* @__PURE__ */ jsx(ButtonContainer, { children: isOnRampLoaded ? /* @__PURE__ */ jsxs(Fragment, { children: [
98
179
  (onRampConfig.isBuyEnabled || onRampConfig.isReceiveEnabled) && !cantBuyAndWithdraw && /* @__PURE__ */ jsx(OptionButton, { icon: "plusCircle", onClick: handleBuyClick, "data-testid": "para-add-funds-tile", children: /* @__PURE__ */ jsx(CpslText, { variant: "bodyXS", color: "secondary", weight: "medium", children: "Add Funds" }) }),
99
180
  embedded.authType !== "externalWallet" && /* @__PURE__ */ jsx(
@@ -154,24 +235,35 @@ const LowerContainer = safeStyled.div`
154
235
  gap: 16px;
155
236
  width: 100%;
156
237
  `;
157
- const MonitorLink = safeStyled.a`
158
- font-family: var(--cpsl-font-family);
159
- font-size: 14px;
160
- position: relative;
161
- display: flex;
162
- align-items: center;
163
- justify-content: center;
238
+ const fadeVariants = {
239
+ enter: {
240
+ opacity: 0
241
+ },
242
+ center: {
243
+ opacity: 1
244
+ },
245
+ exit: {
246
+ opacity: 0
247
+ }
248
+ };
249
+ const fadeTransition = {
250
+ duration: 0.2
251
+ };
252
+ const AnimatedMonitorContainer = safeStyled(motion.div)`
253
+ width: 100%;
254
+ `;
255
+ const AnimatedMonitorButton = safeStyled.button`
164
256
  width: 100%;
165
257
  background: transparent;
166
258
  border: none;
167
259
  cursor: pointer;
168
- color: var(--cpsl-color-text-primary);
169
- --icon-color: var(--cpsl-color-text-primary);
170
-
171
- &:hover {
172
- color: var(--cpsl-color-text-contrast);
173
- --icon-color: var(--cpsl-color-text-contrast);
174
- }
260
+ display: flex;
261
+ align-items: center;
262
+ justify-content: center;
263
+ gap: 8px;
264
+ color: var(--cpsl-color-text-secondary);
265
+ font-family: var(--cpsl-font-family);
266
+ font-size: 14px;
175
267
  `;
176
268
  export {
177
269
  Account
@@ -0,0 +1 @@
1
+ export declare const AccountMonitorTx: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,256 @@
1
+ "use client";
2
+ import {
3
+ __async
4
+ } from "../../../chunk-MMUBH76A.js";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { useEffect, useMemo, useState } from "react";
7
+ import { useModalStore, useModalSessionStore } from "../../stores/index.js";
8
+ import { ModalStep } from "../../utils/steps.js";
9
+ import { StepContainer, InnerStepContainer, Heading, HeroIcon, SpinnerContainer, ExplorerLink } from "../common.js";
10
+ import { CpslButton, CpslSpinner, CpslText } from "@getpara/react-components";
11
+ import { useInternalClient } from "../../../provider/hooks/utils/useInternalClient.js";
12
+ import { useSendMutations } from "../../hooks/index.js";
13
+ import { useWalletState } from "../../../provider/index.js";
14
+ import { formatAssetQuantity } from "@getpara/shared";
15
+ import { truncateAddress } from "@getpara/web-sdk";
16
+ import { AnimatePresence, motion } from "framer-motion";
17
+ import { safeStyled } from "@getpara/react-common";
18
+ import { ErrorBoundary } from "../ErrorBoundary.js";
19
+ const ErrorFallback = () => {
20
+ var _a;
21
+ const setStep = useModalStore((state) => state.setStep);
22
+ const sendTx = useModalSessionStore((state) => state.sendTx);
23
+ return /* @__PURE__ */ jsxs(StepContainer, { children: [
24
+ /* @__PURE__ */ jsx(HeroIcon, { icon: "alertTriangle" }),
25
+ /* @__PURE__ */ jsxs(InnerStepContainer, { children: [
26
+ /* @__PURE__ */ jsx(Heading, { children: "Something went wrong" }),
27
+ /* @__PURE__ */ jsx(CpslText, { variant: "bodyS", color: "secondary", children: "Unable to display transaction status." }),
28
+ ((_a = sendTx == null ? void 0 : sendTx.result) == null ? void 0 : _a.explorerUrl) && /* @__PURE__ */ jsx(ExplorerLink, { href: sendTx.result.explorerUrl, text: "View on Explorer" })
29
+ ] }),
30
+ /* @__PURE__ */ jsx(
31
+ CpslButton,
32
+ {
33
+ fullWidth: true,
34
+ onClick: () => {
35
+ setStep(ModalStep.ACCOUNT_MAIN);
36
+ },
37
+ children: "Go Back"
38
+ }
39
+ )
40
+ ] });
41
+ };
42
+ const AccountMonitorTx = () => {
43
+ return /* @__PURE__ */ jsx(ErrorBoundary, { fallback: /* @__PURE__ */ jsx(ErrorFallback, {}), children: /* @__PURE__ */ jsx(AccountMonitorTxContent, {}) });
44
+ };
45
+ const AccountMonitorTxContent = () => {
46
+ var _a, _b, _c, _d, _e, _f;
47
+ const sendTx = useModalSessionStore((state) => state.sendTx);
48
+ const setSendTx = useModalSessionStore((state) => state.setSendTx);
49
+ const setStep = useModalStore((state) => state.setStep);
50
+ const para = useInternalClient();
51
+ const { selectedWallet, setSelectedWallet } = useWalletState();
52
+ const [isRetrying, setIsRetrying] = useState(false);
53
+ useEffect(() => {
54
+ if ((sendTx == null ? void 0 : sendTx.walletId) && (selectedWallet == null ? void 0 : selectedWallet.id) !== sendTx.walletId) {
55
+ const wallet = para.wallets[sendTx.walletId];
56
+ if (wallet && wallet.type) {
57
+ setSelectedWallet({ id: sendTx.walletId, type: wallet.type });
58
+ }
59
+ }
60
+ }, [sendTx == null ? void 0 : sendTx.walletId, selectedWallet == null ? void 0 : selectedWallet.id, para.wallets, setSelectedWallet]);
61
+ useEffect(() => {
62
+ var _a2;
63
+ if (!((_a2 = sendTx == null ? void 0 : sendTx.result) == null ? void 0 : _a2.status)) {
64
+ setStep(ModalStep.ACCOUNT_MAIN);
65
+ }
66
+ }, [sendTx, setStep]);
67
+ const { estimateMutateAsync, broadcastMutateAsync } = useSendMutations({
68
+ estimateOnSuccess: () => {
69
+ },
70
+ estimateOnError: () => {
71
+ },
72
+ broadcastOnError: () => {
73
+ }
74
+ });
75
+ const handleRetry = () => __async(void 0, null, function* () {
76
+ var _a2;
77
+ if (!(sendTx == null ? void 0 : sendTx.opts) || !(sendTx == null ? void 0 : sendTx.userId) || !(sendTx == null ? void 0 : sendTx.walletId) || !((_a2 = sendTx == null ? void 0 : sendTx.result) == null ? void 0 : _a2.network)) {
78
+ return;
79
+ }
80
+ setIsRetrying(true);
81
+ try {
82
+ const estimateResult = yield estimateMutateAsync({
83
+ userId: sendTx.userId,
84
+ walletId: sendTx.walletId,
85
+ opts: sendTx.opts
86
+ });
87
+ if (!(estimateResult == null ? void 0 : estimateResult.result)) {
88
+ setIsRetrying(false);
89
+ return;
90
+ }
91
+ if (!(selectedWallet == null ? void 0 : selectedWallet.id) || !(selectedWallet == null ? void 0 : selectedWallet.address) || !(selectedWallet == null ? void 0 : selectedWallet.type)) {
92
+ setIsRetrying(false);
93
+ return;
94
+ }
95
+ const walletAddress = selectedWallet.address;
96
+ const walletType = selectedWallet.type;
97
+ const network = sendTx.result.network;
98
+ yield broadcastMutateAsync({
99
+ userId: sendTx.userId,
100
+ walletId: sendTx.walletId,
101
+ walletAddress,
102
+ walletType,
103
+ txSerialized: estimateResult.result.txSerialized,
104
+ message: estimateResult.result.message,
105
+ evmChainId: network.type === "EVM" ? network.evmChainId : void 0,
106
+ isDevnet: network.type === "SOLANA" ? network.isDevnet : void 0
107
+ });
108
+ } catch (error) {
109
+ console.error("Retry failed:", error);
110
+ } finally {
111
+ setIsRetrying(false);
112
+ }
113
+ });
114
+ const explorerLink = useMemo(() => {
115
+ var _a2;
116
+ if ((_a2 = sendTx == null ? void 0 : sendTx.result) == null ? void 0 : _a2.explorerUrl) {
117
+ return /* @__PURE__ */ jsx(ExplorerLink, { href: sendTx.result.explorerUrl, text: "View Transaction" });
118
+ }
119
+ return null;
120
+ }, [(_a = sendTx == null ? void 0 : sendTx.result) == null ? void 0 : _a.explorerUrl]);
121
+ const content = useMemo(() => {
122
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g, _h;
123
+ if (!sendTx) {
124
+ return null;
125
+ }
126
+ const status = (_b2 = (_a2 = sendTx.result) == null ? void 0 : _a2.status) == null ? void 0 : _b2.status;
127
+ const confirmations = (_e2 = (_d2 = (_c2 = sendTx.result) == null ? void 0 : _c2.status) == null ? void 0 : _d2.confirmations) != null ? _e2 : 0;
128
+ const isPending = status === "PENDING" || status === "CONFIRMED" && confirmations < 1;
129
+ const isConfirmed = status === "CONFIRMED" && confirmations >= 1;
130
+ const isFailed = status === "FAILED";
131
+ switch (true) {
132
+ case isConfirmed:
133
+ return /* @__PURE__ */ jsx(
134
+ AnimatedContainer,
135
+ {
136
+ variants: fadeVariants,
137
+ initial: "enter",
138
+ animate: "center",
139
+ exit: "exit",
140
+ transition: fadeTransition,
141
+ children: /* @__PURE__ */ jsxs(StepContainer, { children: [
142
+ /* @__PURE__ */ jsx(HeroIcon, { icon: "checkCircleFilled" }),
143
+ /* @__PURE__ */ jsxs(InnerStepContainer, { children: [
144
+ /* @__PURE__ */ jsx(Heading, { children: "Success!" }),
145
+ /* @__PURE__ */ jsx(CpslText, { variant: "bodyS", color: "secondary", children: "Your funds have been sent." }),
146
+ explorerLink
147
+ ] }),
148
+ /* @__PURE__ */ jsx(
149
+ CpslButton,
150
+ {
151
+ fullWidth: true,
152
+ onClick: () => {
153
+ setSendTx(null);
154
+ },
155
+ children: "Done"
156
+ }
157
+ )
158
+ ] })
159
+ },
160
+ "confirmed"
161
+ );
162
+ case isFailed:
163
+ return /* @__PURE__ */ jsx(
164
+ AnimatedContainer,
165
+ {
166
+ variants: fadeVariants,
167
+ initial: "enter",
168
+ animate: "center",
169
+ exit: "exit",
170
+ transition: fadeTransition,
171
+ children: /* @__PURE__ */ jsxs(StepContainer, { children: [
172
+ /* @__PURE__ */ jsx(HeroIcon, { icon: "alertTriangle" }),
173
+ /* @__PURE__ */ jsxs(InnerStepContainer, { children: [
174
+ /* @__PURE__ */ jsx(Heading, { children: "Transaction failed" }),
175
+ /* @__PURE__ */ jsx(CpslText, { variant: "bodyS", color: "secondary", children: "Your transaction was not completed." })
176
+ ] }),
177
+ /* @__PURE__ */ jsx(CpslButton, { fullWidth: true, onClick: handleRetry, disabled: isRetrying, children: isRetrying ? "Retrying..." : "Retry" })
178
+ ] })
179
+ },
180
+ "failed"
181
+ );
182
+ case isPending:
183
+ default:
184
+ return /* @__PURE__ */ jsx(
185
+ AnimatedContainer,
186
+ {
187
+ variants: fadeVariants,
188
+ initial: "enter",
189
+ animate: "center",
190
+ exit: "exit",
191
+ transition: fadeTransition,
192
+ children: /* @__PURE__ */ jsxs(
193
+ StepContainer,
194
+ {
195
+ style: {
196
+ fontFamily: "var(--cpsl-font-family)",
197
+ color: "var(--cpsl-color-text-primary)"
198
+ },
199
+ children: [
200
+ /* @__PURE__ */ jsx(SpinnerContainer, { children: /* @__PURE__ */ jsx(CpslSpinner, { size: 100 }) }),
201
+ explorerLink,
202
+ ((_f2 = sendTx.opts) == null ? void 0 : _f2.destinationAddress) && /* @__PURE__ */ jsxs("div", { style: { width: "100%", fontSize: "14px", display: "flex", justifyContent: "space-between" }, children: [
203
+ /* @__PURE__ */ jsx("div", { style: { textAlign: "left" }, children: "To" }),
204
+ /* @__PURE__ */ jsx("div", { style: { textAlign: "right" }, children: truncateAddress(sendTx.opts.destinationAddress, sendTx.opts.type) })
205
+ ] }),
206
+ ((_g = sendTx.opts) == null ? void 0 : _g.tokenSymbol) && ((_h = sendTx.opts) == null ? void 0 : _h.transferAmount) && /* @__PURE__ */ jsxs("div", { style: { width: "100%", fontSize: "14px", display: "flex", justifyContent: "space-between" }, children: [
207
+ /* @__PURE__ */ jsx("div", { style: { textAlign: "left" }, children: "Amount" }),
208
+ /* @__PURE__ */ jsx("div", { style: { textAlign: "right" }, children: formatAssetQuantity({
209
+ quantity: sendTx.opts.transferAmount,
210
+ symbol: sendTx.opts.tokenSymbol
211
+ }) })
212
+ ] })
213
+ ]
214
+ }
215
+ )
216
+ },
217
+ "pending"
218
+ );
219
+ }
220
+ }, [
221
+ sendTx,
222
+ (_c = (_b = sendTx == null ? void 0 : sendTx.result) == null ? void 0 : _b.status) == null ? void 0 : _c.status,
223
+ (_e = (_d = sendTx == null ? void 0 : sendTx.result) == null ? void 0 : _d.status) == null ? void 0 : _e.confirmations,
224
+ explorerLink,
225
+ handleRetry,
226
+ isRetrying,
227
+ setSendTx
228
+ ]);
229
+ if (!((_f = sendTx == null ? void 0 : sendTx.result) == null ? void 0 : _f.status)) {
230
+ return null;
231
+ }
232
+ return /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: content });
233
+ };
234
+ const fadeVariants = {
235
+ enter: {
236
+ opacity: 0
237
+ },
238
+ center: {
239
+ opacity: 1
240
+ },
241
+ exit: {
242
+ opacity: 0
243
+ }
244
+ };
245
+ const fadeTransition = {
246
+ duration: 0.2
247
+ };
248
+ const AnimatedContainer = safeStyled(motion.div)`
249
+ position: relative;
250
+ display: flex;
251
+ flex-direction: column;
252
+ width: 100%;
253
+ `;
254
+ export {
255
+ AccountMonitorTx
256
+ };
@@ -44,7 +44,7 @@ function AccountSendAsset() {
44
44
  return (_b = (_a = profileBalance == null ? void 0 : profileBalance.wallets.find((wallet) => wallet.address === (selectedWallet == null ? void 0 : selectedWallet.address))) == null ? void 0 : _a.assets) != null ? _b : [];
45
45
  }, [profileBalance, selectedWallet == null ? void 0 : selectedWallet.address]);
46
46
  const transformItem = useCallback((item) => {
47
- var _a, _b;
47
+ var _a, _b, _c;
48
48
  const isValued = ((_a = item.value) == null ? void 0 : _a.value) && ((_b = item.value) == null ? void 0 : _b.value) >= 0.01;
49
49
  const quantity = formatAssetQuantity({ quantity: item.quantity, symbol: item.metadata.symbol });
50
50
  return {
@@ -53,7 +53,7 @@ function AccountSendAsset() {
53
53
  AssetNetwork,
54
54
  {
55
55
  assetSrc: item.metadata.logoUrl,
56
- networkSrc: item.networks.length === 1 ? item.networks[0].metadata.logoUrl : void 0,
56
+ networkSrc: item.networks.length === 1 ? (_c = item.networks[0].metadata) == null ? void 0 : _c.logoUrl : void 0,
57
57
  size: 48
58
58
  }
59
59
  ),
@@ -9,14 +9,19 @@ import { useSend } from "./context.js";
9
9
  import { useModalStore } from "../../../stores/index.js";
10
10
  import { ModalStep } from "../../../utils/steps.js";
11
11
  import { useEffect, useMemo, useRef, useState } from "react";
12
+ import { createPortal } from "react-dom";
12
13
  import { useDebounce } from "../../../hooks/useDebounce.js";
13
14
  import { AssetNetwork } from "./AssetNetwork.js";
14
15
  import { useWalletState } from "../../../../provider/index.js";
16
+ import { useInternalClient } from "../../../../provider/hooks/utils/useInternalClient.js";
17
+ import { Environment } from "@getpara/web-sdk";
18
+ import { safeStyled } from "@getpara/react-common";
15
19
  function AccountSendForm() {
16
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
20
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
17
21
  const { selectedWallet } = useWalletState();
18
22
  const setStep = useModalStore((state) => state.setStep);
19
23
  const onRampConfig = useModalStore((state) => state.onRampConfig);
24
+ const currentStep = useModalStore((state) => state.step);
20
25
  const {
21
26
  estimate,
22
27
  broadcast,
@@ -35,11 +40,16 @@ function AccountSendForm() {
35
40
  setIsMax,
36
41
  estimateIsPending,
37
42
  broadcastIsPending,
38
- optionsType
43
+ optionsType,
44
+ simulateFailure,
45
+ setSimulateFailure
39
46
  } = useSend();
47
+ const para = useInternalClient();
48
+ const isDevOrSandbox = ((_a = para.ctx) == null ? void 0 : _a.env) === Environment.DEV || ((_b = para.ctx) == null ? void 0 : _b.env) === Environment.SANDBOX;
49
+ const isSendFormStep = currentStep === ModalStep.ACCOUNT_SEND;
40
50
  const [inputDestinationAddress, setInputDestinationAddress] = useState(destinationAddress);
41
51
  const dbInputDestinationAddress = useDebounce(inputDestinationAddress, 500);
42
- const isTestnet = (_b = (_a = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _a.metadata) == null ? void 0 : _b.isTestnet;
52
+ const isTestnet = (_d = (_c = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _c.metadata) == null ? void 0 : _d.isTestnet;
43
53
  const shouldUseAmountMode = !assetPrice || !!assetPrice && isTestnet;
44
54
  const [inputMode, setInputMode] = useState(shouldUseAmountMode ? "AMOUNT" : "VALUE");
45
55
  const [inputValue, setInputValue] = useState(
@@ -101,7 +111,7 @@ function AccountSendForm() {
101
111
  estimateIsPending,
102
112
  broadcastIsPending,
103
113
  onRampConfig == null ? void 0 : onRampConfig.isBuyEnabled,
104
- (_d = (_c = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _c.metadata) == null ? void 0 : _d.nativeTokenSymbol,
114
+ (_f = (_e = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _e.metadata) == null ? void 0 : _f.nativeTokenSymbol,
105
115
  estimate == null ? void 0 : estimate.transferAmount
106
116
  ]);
107
117
  useEffect(() => {
@@ -109,7 +119,7 @@ function AccountSendForm() {
109
119
  const isTestnet2 = (_b2 = (_a2 = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _a2.metadata) == null ? void 0 : _b2.isTestnet;
110
120
  const shouldUseAmountMode2 = !assetPrice || !!assetPrice && isTestnet2;
111
121
  setInputMode(shouldUseAmountMode2 ? "AMOUNT" : "VALUE");
112
- }, [assetPrice, (_f = (_e = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _e.metadata) == null ? void 0 : _f.isTestnet]);
122
+ }, [assetPrice, (_h = (_g = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _g.metadata) == null ? void 0 : _h.isTestnet]);
113
123
  useEffect(() => {
114
124
  if (inputMode === "AMOUNT") {
115
125
  setTransferAmount(Number(dbInputValue));
@@ -195,7 +205,7 @@ function AccountSendForm() {
195
205
  children: [
196
206
  /* @__PURE__ */ jsx(CpslText, { variant: "bodyM", color: "secondary", children: inputMode === "VALUE" ? formatAssetQuantity({
197
207
  quantity: isMax && assetAmountOnNetwork ? assetAmountOnNetwork : transferAmount,
198
- symbol: (_g = sendMetadata.asset.metadata) == null ? void 0 : _g.symbol
208
+ symbol: (_i = sendMetadata.asset.metadata) == null ? void 0 : _i.symbol
199
209
  }) : formatCurrency({
200
210
  value: isMax && assetValueOnNetwork ? assetValueOnNetwork.value : Number(transferValue),
201
211
  currency: "USD"
@@ -238,7 +248,7 @@ function AccountSendForm() {
238
248
  AssetNetwork,
239
249
  {
240
250
  assetSrc: sendMetadata.asset.metadata.logoUrl,
241
- networkSrc: sendMetadata.network.metadata.logoUrl,
251
+ networkSrc: (_k = (_j = sendMetadata.network) == null ? void 0 : _j.metadata) == null ? void 0 : _k.logoUrl,
242
252
  size: 32
243
253
  }
244
254
  ),
@@ -318,7 +328,7 @@ function AccountSendForm() {
318
328
  }
319
329
  ),
320
330
  /* @__PURE__ */ jsx(
321
- CpslInput,
331
+ RecipientInput,
322
332
  {
323
333
  placeholder: "Enter recipient address",
324
334
  value: inputDestinationAddress,
@@ -330,7 +340,7 @@ function AccountSendForm() {
330
340
  ),
331
341
  ((estimate == null ? void 0 : estimate.feeValue) || (estimate == null ? void 0 : estimate.feeAmount) || estimateIsPending) && /* @__PURE__ */ jsxs("div", { style: { display: "flex", width: "100%", gap: "4px", alignItems: "center", justifyContent: "space-between" }, children: [
332
342
  /* @__PURE__ */ jsx(CpslText, { variant: "bodyXS", color: "secondary", children: "Network Fee" }),
333
- /* @__PURE__ */ jsx(CpslText, { variant: "bodyXS", color: "contrast", children: estimateIsPending ? "Estimating..." : (_k = (_j = ((_i = (_h = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _h.metadata) == null ? void 0 : _i.isTestnet) ? estimate == null ? void 0 : estimate.feeAmount : estimate == null ? void 0 : estimate.feeValue) != null ? _j : estimate == null ? void 0 : estimate.feeAmount) != null ? _k : "0" })
343
+ /* @__PURE__ */ jsx(CpslText, { variant: "bodyXS", color: "contrast", children: estimateIsPending ? "Estimating..." : (_o = (_n = ((_m = (_l = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _l.metadata) == null ? void 0 : _m.isTestnet) ? estimate == null ? void 0 : estimate.feeAmount : estimate == null ? void 0 : estimate.feeValue) != null ? _n : estimate == null ? void 0 : estimate.feeAmount) != null ? _o : "0" })
334
344
  ] }),
335
345
  error && /* @__PURE__ */ jsx("div", { style: { display: "flex", width: "100%", gap: "4px", alignItems: "center", justifyContent: "space-between" }, children: error }),
336
346
  /* @__PURE__ */ jsx(
@@ -339,14 +349,62 @@ function AccountSendForm() {
339
349
  variant: "primary",
340
350
  fullWidth: true,
341
351
  pending: estimateIsPending || broadcastIsPending,
342
- disabled: estimateIsPending || broadcastIsPending || !((_l = estimate == null ? void 0 : estimate.result) == null ? void 0 : _l.txSerialized) || !!(estimate == null ? void 0 : estimate.error),
352
+ disabled: estimateIsPending || broadcastIsPending || !((_p = estimate == null ? void 0 : estimate.result) == null ? void 0 : _p.txSerialized) || !!(estimate == null ? void 0 : estimate.error),
343
353
  onClick: onSubmit,
344
354
  "data-testid": "para-send-confirm",
345
355
  children: "Confirm Send"
346
356
  }
357
+ ),
358
+ isDevOrSandbox && isSendFormStep && typeof window !== "undefined" && createPortal(
359
+ /* @__PURE__ */ jsx(SimulateFailureContainer, { children: /* @__PURE__ */ jsxs(
360
+ "label",
361
+ {
362
+ style: {
363
+ display: "flex",
364
+ alignItems: "center",
365
+ gap: "8px",
366
+ cursor: "pointer",
367
+ width: "100%",
368
+ justifyContent: "center"
369
+ },
370
+ children: [
371
+ /* @__PURE__ */ jsx(
372
+ "input",
373
+ {
374
+ type: "checkbox",
375
+ checked: simulateFailure,
376
+ onChange: (e) => setSimulateFailure(e.target.checked),
377
+ style: { cursor: "pointer" }
378
+ }
379
+ ),
380
+ /* @__PURE__ */ jsx(CpslText, { variant: "bodyXS", color: "secondary", children: "Simulate failure" })
381
+ ]
382
+ }
383
+ ) }),
384
+ document.body
347
385
  )
348
386
  ] });
349
387
  }
388
+ const RecipientInput = safeStyled(CpslInput)`
389
+ --cpsl-color-input-surface-hover: var(--cpsl-color-input-surface-default);
390
+ `;
391
+ const SimulateFailureContainer = safeStyled.div`
392
+ position: fixed !important;
393
+ bottom: 0 !important;
394
+ left: 0 !important;
395
+ right: 0 !important;
396
+ width: 100% !important;
397
+ z-index: 100001 !important;
398
+ background: var(--cpsl-color-background-0) !important;
399
+ border-top: 1px solid var(--cpsl-color-background-16) !important;
400
+ padding: 16px !important;
401
+ display: flex !important;
402
+ justify-content: center !important;
403
+ align-items: center !important;
404
+ box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1) !important;
405
+ pointer-events: auto !important;
406
+ isolation: isolate;
407
+ `;
350
408
  export {
351
409
  AccountSendForm
352
410
  };
@@ -29,6 +29,8 @@ type Value = {
29
29
  broadcastIsPending: boolean;
30
30
  broadcastIsError: boolean;
31
31
  optionsType: OptionsType;
32
+ simulateFailure: boolean;
33
+ setSimulateFailure: Dispatch<SetStateAction<boolean>>;
32
34
  };
33
35
  export declare const AccountSendContext: import("react").Context<Value>;
34
36
  export declare function AccountSendProvider({ children, step }: PropsWithChildren<{