@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
@@ -1,6 +1,5 @@
1
1
  "use client";
2
2
  import {
3
- __async,
4
3
  __spreadProps,
5
4
  __spreadValues
6
5
  } from "../../../../chunk-MMUBH76A.js";
@@ -14,12 +13,9 @@ import {
14
13
  useRef,
15
14
  useState
16
15
  } from "react";
17
- import { useMutation, useQueryClient } from "@tanstack/react-query";
18
16
  import { useInternalClient } from "../../../../provider/hooks/utils/useInternalClient.js";
19
- import { useProfileBalance, useSignMessage, useSignTransaction, useWalletState } from "../../../../provider/index.js";
20
- import { hexStringToBase64 } from "@getpara/web-sdk";
21
- import { useModalStore } from "../../../stores/index.js";
22
- import { ModalStep } from "../../../utils/steps.js";
17
+ import { useProfileBalance, useWalletState } from "../../../../provider/index.js";
18
+ import { useSendMutations } from "../../../hooks/index.js";
23
19
  import { useStore } from "../../../../provider/stores/useStore.js";
24
20
  const getDefaultSendMetadata = (balances, wallet) => {
25
21
  if (!balances || !(wallet == null ? void 0 : wallet.type) || !(wallet == null ? void 0 : wallet.address) || (wallet == null ? void 0 : wallet.type) === "COSMOS") {
@@ -65,11 +61,7 @@ function AccountSendProvider({ children, step }) {
65
61
  var _a2;
66
62
  return (_a2 = state.modalConfig) == null ? void 0 : _a2.balances;
67
63
  });
68
- const setStep = useModalStore((state) => state.setStep);
69
- const setSendTx = useModalStore((state) => state.setSendTx);
70
64
  const { data: balances } = useProfileBalance({ isComprehensive: true });
71
- const { signTransactionAsync } = useSignTransaction();
72
- const { signMessageAsync } = useSignMessage();
73
65
  const { selectedWallet, setSelectedWallet } = useWalletState();
74
66
  const [estimate, setEstimate] = useState(null);
75
67
  const [broadcast, setBroadcast] = useState(null);
@@ -78,6 +70,7 @@ function AccountSendProvider({ children, step }) {
78
70
  const [transferValue, setTransferValue] = useState(0);
79
71
  const [transferAmount, setTransferAmount] = useState(getTransferAmount(sendMetadata, transferValue));
80
72
  const [isMax, setIsMax] = useState(false);
73
+ const [simulateFailure, setSimulateFailure] = useState(false);
81
74
  const optionsType = useMemo(() => {
82
75
  const walletBalance = balances == null ? void 0 : balances.wallets.find(({ address }) => address === (selectedWallet == null ? void 0 : selectedWallet.address));
83
76
  if (!walletBalance || walletBalance.assets.length === 0) {
@@ -88,106 +81,26 @@ function AccountSendProvider({ children, step }) {
88
81
  }
89
82
  return "MULTIPLE";
90
83
  }, [balances, selectedWallet == null ? void 0 : selectedWallet.address]);
91
- const {
92
- mutate: estimateMutate,
93
- isPending: estimateIsPending,
94
- isError: estimateIsError
95
- } = useMutation({
96
- mutationKey: ["estimate-tx"],
97
- mutationFn: (_0) => __async(this, [_0], function* ({ userId, walletId, opts }) {
98
- if (!para.userId || !selectedWallet.id) {
99
- return null;
100
- }
101
- const result = yield para.ctx.client.estimateSendTransaction({
102
- userId,
103
- walletId,
104
- opts
105
- });
106
- return result;
107
- }),
108
- onSuccess: (data) => {
109
- setEstimate(data);
110
- },
111
- onError: (error) => {
112
- console.error(error);
84
+ const estimateOnSuccess = useCallback((estimateResult) => {
85
+ setEstimate(estimateResult);
86
+ }, []);
87
+ const broadcastOnSuccess = useCallback((data) => {
88
+ if (!!(data == null ? void 0 : data.error)) {
89
+ setBroadcast(data);
113
90
  }
114
- });
115
- const queryClient = useQueryClient();
116
- const refs = useStore((state) => state.refs);
117
- const {
118
- mutate: broadcastMutate,
119
- isPending: broadcastIsPending,
120
- isError: broadcastIsError
121
- } = useMutation({
122
- mutationKey: ["broadcast-tx"],
123
- mutationFn: (_0) => __async(this, [_0], function* ({
124
- userId,
125
- walletId,
126
- walletAddress,
127
- walletType,
128
- txSerialized,
129
- message,
130
- evmChainId,
131
- isDevnet
132
- }) {
133
- var _a2, _b2, _c2, _d2, _e2;
134
- if (!para.userId || !selectedWallet.id) {
135
- return null;
136
- }
137
- let signature;
138
- switch (walletType) {
139
- case "SOLANA":
140
- signature = (_a2 = yield signMessageAsync({
141
- walletId,
142
- messageBase64: message
143
- })) == null ? void 0 : _a2.signature;
144
- break;
145
- case "EVM":
146
- default:
147
- signature = (_b2 = yield signTransactionAsync({
148
- walletId,
149
- rlpEncodedTxBase64: hexStringToBase64(txSerialized),
150
- chainId: evmChainId
151
- })) == null ? void 0 : _b2.signature;
152
- if (!!signature) {
153
- signature = `0x${signature}`;
154
- }
155
- break;
156
- }
157
- const result = yield para.ctx.client.broadcastSendTransaction({
158
- userId,
159
- walletId,
160
- opts: {
161
- type: walletType,
162
- evmChainId,
163
- isDevnet,
164
- tx: txSerialized,
165
- signature,
166
- sourceAddress: walletAddress,
167
- txUrlFormat: (_e2 = (_d2 = (_c2 = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _c2.metadata) == null ? void 0 : _d2.explorer) == null ? void 0 : _e2.txUrlFormat
168
- }
169
- });
170
- return result;
171
- }),
172
- onSuccess: (data) => {
173
- if (!!(data == null ? void 0 : data.error)) {
174
- setBroadcast(data);
175
- } else if (!!data) {
176
- setSendTx(data);
177
- setStep(ModalStep.ACCOUNT_MAIN);
178
- refs.balancesInvalidationTime.current = Date.now();
179
- queryClient.invalidateQueries({
180
- queryKey: ["useProfileBalance"],
181
- refetchType: "active"
182
- });
183
- }
91
+ }, []);
92
+ const { estimateMutate, broadcastMutate, estimateIsPending, estimateIsError, broadcastIsPending, broadcastIsError } = useSendMutations({
93
+ estimateOnSuccess,
94
+ estimateOnError: (e) => {
95
+ console.error(e);
184
96
  },
185
- onError: (error) => {
186
- console.error(error);
97
+ broadcastOnSuccess,
98
+ broadcastOnError: (e) => {
99
+ console.error(e);
187
100
  }
188
101
  });
189
102
  const onSubmit = useCallback(() => {
190
- var _a2, _b2, _c2, _d2, _e2, _f2;
103
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
191
104
  broadcastMutate({
192
105
  userId: para.userId,
193
106
  walletId: selectedWallet.id,
@@ -196,7 +109,15 @@ function AccountSendProvider({ children, step }) {
196
109
  txSerialized: (_a2 = estimate == null ? void 0 : estimate.result) == null ? void 0 : _a2.txSerialized,
197
110
  message: (_b2 = estimate == null ? void 0 : estimate.result) == null ? void 0 : _b2.message,
198
111
  evmChainId: (_d2 = (_c2 = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _c2.metadata) == null ? void 0 : _d2.evmChainId,
199
- isDevnet: ((_f2 = (_e2 = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _e2.metadata) == null ? void 0 : _f2.internalId) === "SOLANA_DEVNET"
112
+ isDevnet: ((_f2 = (_e2 = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _e2.metadata) == null ? void 0 : _f2.internalId) === "SOLANA_DEVNET",
113
+ txUrlFormat: (_i = (_h = (_g = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _g.metadata) == null ? void 0 : _h.explorer) == null ? void 0 : _i.txUrlFormat,
114
+ rpc: ((_k = (_j = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _j.metadata) == null ? void 0 : _k.rpcUrl) ? {
115
+ httpUrls: [(_m = (_l = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _l.metadata) == null ? void 0 : _m.rpcUrl],
116
+ wsUrls: [
117
+ (_o = (_n = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _n.metadata) == null ? void 0 : _o.rpcUrl.replace(/^https:\/\//, "wss://").replace(/^http:\/\//, "ws://")
118
+ ]
119
+ } : (_q = (_p = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _p.metadata) == null ? void 0 : _q.rpc,
120
+ simulateFailure
200
121
  });
201
122
  }, [
202
123
  para.userId,
@@ -206,7 +127,9 @@ function AccountSendProvider({ children, step }) {
206
127
  (_a = estimate == null ? void 0 : estimate.result) == null ? void 0 : _a.txSerialized,
207
128
  (_b = estimate == null ? void 0 : estimate.result) == null ? void 0 : _b.message,
208
129
  (_d = (_c = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _c.metadata) == null ? void 0 : _d.evmChainId,
209
- (_f = (_e = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _e.metadata) == null ? void 0 : _f.internalId
130
+ (_f = (_e = sendMetadata == null ? void 0 : sendMetadata.network) == null ? void 0 : _e.metadata) == null ? void 0 : _f.internalId,
131
+ simulateFailure,
132
+ broadcastMutate
210
133
  ]);
211
134
  const availableWallets = useMemo(() => {
212
135
  return para.availableWallets.filter(({ type }) => type !== "COSMOS");
@@ -391,7 +314,9 @@ function AccountSendProvider({ children, step }) {
391
314
  broadcast,
392
315
  broadcastIsPending,
393
316
  broadcastIsError,
394
- optionsType
317
+ optionsType,
318
+ simulateFailure,
319
+ setSimulateFailure
395
320
  };
396
321
  }, [
397
322
  step,
@@ -415,7 +340,9 @@ function AccountSendProvider({ children, step }) {
415
340
  broadcast,
416
341
  broadcastIsPending,
417
342
  broadcastIsError,
418
- optionsType
343
+ optionsType,
344
+ simulateFailure,
345
+ setSimulateFailure
419
346
  ]);
420
347
  return /* @__PURE__ */ jsx(AccountSendContext.Provider, { value, children });
421
348
  }
@@ -9,6 +9,7 @@ import {
9
9
  useContext,
10
10
  useEffect,
11
11
  useMemo,
12
+ useRef,
12
13
  useState
13
14
  } from "react";
14
15
  import { OnRampStep, useModalStore } from "../../stores/index.js";
@@ -24,6 +25,7 @@ import {
24
25
  import { getNetworkFromChainId, getNetworkOrMainNetEquivalent, safeStyled } from "@getpara/react-common";
25
26
  import { CpslAlert, CpslIcon } from "@getpara/react-components";
26
27
  import { useStore } from "../../../provider/stores/useStore.js";
28
+ import { getDefaultAssetAndNetwork, isAmountWithinProviderLimits } from "../../utils/onramps.js";
27
29
  const TABS = [
28
30
  [EnabledFlow.BUY, "isBuyEnabled", "creditCard", "Buy"],
29
31
  [EnabledFlow.RECEIVE, "isReceiveEnabled", "qrCode", "Receive"],
@@ -56,7 +58,7 @@ function isValid(onRampConfig, walletType, network, asset) {
56
58
  }
57
59
  const AddFundsContext = createContext(DEFAULT);
58
60
  function AddFundsContextProvider({ tab, children }) {
59
- var _a, _b, _c, _d, _e;
61
+ var _a, _b, _c, _d, _e, _f;
60
62
  const appName = useStore((state) => state.appName);
61
63
  const client = useStore((state) => state.client);
62
64
  const onRampConfig = useModalStore((state) => state.onRampConfig);
@@ -67,7 +69,9 @@ function AddFundsContextProvider({ tab, children }) {
67
69
  const { chainId } = useExternalWallets();
68
70
  const isTestMode = ((_a = client == null ? void 0 : client.ctx) == null ? void 0 : _a.env) === Environment.PROD ? (_b = onRampConfig == null ? void 0 : onRampConfig.testMode) != null ? _b : false : true;
69
71
  const { data: activeWallet } = useWallet();
70
- const [fiatQuantity, setFiatQuantity] = useState((_d = (_c = onRampConfig == null ? void 0 : onRampConfig.defaultBuyAmount) == null ? void 0 : _c[0]) != null ? _d : "25.00");
72
+ const [fiatQuantity, setFiatQuantity] = useState(
73
+ (_e = (_d = (_c = onRampConfig == null ? void 0 : onRampConfig.defaultBuyAmount) == null ? void 0 : _c[0]) == null ? void 0 : _d.toString()) != null ? _e : "25.00"
74
+ );
71
75
  const networks = useMemo(() => {
72
76
  if (!onRampConfig) {
73
77
  return [];
@@ -118,16 +122,22 @@ function AddFundsContextProvider({ tab, children }) {
118
122
  });
119
123
  }, [networks, asset, activeWallet == null ? void 0 : activeWallet.type, onRampConfig, tab]);
120
124
  const isProviderAllowed = useMemo(
121
- () => onRampConfig && !!(activeWallet == null ? void 0 : activeWallet.type) ? onRampConfig.providers.reduce(
122
- (acc, id) => {
123
- var _a2, _b2, _c2, _d2, _e2;
124
- return __spreadProps(__spreadValues({}, acc), {
125
- [id]: !!network && !!asset && !!((_e2 = (_d2 = (_c2 = (_b2 = (_a2 = onRampConfig.assetInfo[activeWallet.type]) == null ? void 0 : _a2[network]) == null ? void 0 : _b2[asset]) == null ? void 0 : _c2[id]) == null ? void 0 : _d2[1]) == null ? void 0 : _e2[tab === EnabledFlow.BUY ? "BUY" : "SELL"])
126
- });
127
- },
128
- {}
129
- ) : {},
130
- [onRampConfig, network, asset, activeWallet, tab]
125
+ () => onRampConfig && !!(activeWallet == null ? void 0 : activeWallet.type) ? onRampConfig.providers.reduce((acc, id) => {
126
+ var _a2, _b2, _c2, _d2, _e2;
127
+ const purchaseType = tab === EnabledFlow.BUY ? OnRampPurchaseType.BUY : OnRampPurchaseType.SELL;
128
+ let isAllowed = !!network && !!asset && !!((_e2 = (_d2 = (_c2 = (_b2 = (_a2 = onRampConfig.assetInfo[activeWallet.type]) == null ? void 0 : _a2[network]) == null ? void 0 : _b2[asset]) == null ? void 0 : _c2[id]) == null ? void 0 : _d2[1]) == null ? void 0 : _e2[purchaseType]);
129
+ if (isAllowed && fiatQuantity) {
130
+ const fiatQtyString = String(fiatQuantity);
131
+ if (fiatQtyString.trim() !== "") {
132
+ const amount = parseFloat(fiatQtyString);
133
+ if (!isNaN(amount) && !isAmountWithinProviderLimits(amount, id, purchaseType)) {
134
+ isAllowed = false;
135
+ }
136
+ }
137
+ }
138
+ return __spreadProps(__spreadValues({}, acc), { [id]: isAllowed });
139
+ }, {}) : {},
140
+ [onRampConfig, network, asset, activeWallet, tab, fiatQuantity]
131
141
  );
132
142
  const settingsStep = useMemo(() => {
133
143
  switch (true) {
@@ -160,7 +170,7 @@ function AddFundsContextProvider({ tab, children }) {
160
170
  ] }) }),
161
171
  /* @__PURE__ */ jsx(CloseButton, { onClick: () => setIsTestModeAlertDismissed(true), children: /* @__PURE__ */ jsx(CloseX, { icon: "x" }) })
162
172
  ] }) }) : null;
163
- }, [isTestModeAlertDismissed, appName, isTestMode, setIsTestModeAlertDismissed, (_e = client == null ? void 0 : client.ctx) == null ? void 0 : _e.env]);
173
+ }, [isTestModeAlertDismissed, appName, isTestMode, setIsTestModeAlertDismissed, (_f = client == null ? void 0 : client.ctx) == null ? void 0 : _f.env]);
164
174
  useEffect(() => {
165
175
  if (!!asset && !network && narrowedNetworks.length === 1) {
166
176
  setNetwork(narrowedNetworks[0]);
@@ -197,27 +207,62 @@ function AddFundsContextProvider({ tab, children }) {
197
207
  asset,
198
208
  network,
199
209
  fiatQuantity,
200
- setFiatQuantity,
201
210
  activeWallet,
202
211
  onRampConfig,
203
212
  isTestMode,
204
213
  settingsStep,
205
214
  TestModeAlert
206
215
  ]);
216
+ const prevWalletTypeRef = useRef(activeWallet == null ? void 0 : activeWallet.type);
207
217
  useEffect(() => {
208
- const newNetwork = !!(activeWallet == null ? void 0 : activeWallet.type) && !!(onRampConfig == null ? void 0 : onRampConfig.defaultOnRampNetwork) && !!onRampConfig.assetInfo[activeWallet.type][onRampConfig.defaultOnRampNetwork] ? onRampConfig.defaultOnRampNetwork : networks.find(
209
- (network2) => (activeWallet == null ? void 0 : activeWallet.type) === "COSMOS" ? network2 === "COSMOS" : (activeWallet == null ? void 0 : activeWallet.type) === "SOLANA" ? network2 === "SOLANA" : network2 === "ETHEREUM"
210
- ) || networks[0] || null;
211
- const newAsset = !!network && !!(onRampConfig == null ? void 0 : onRampConfig.defaultOnRampAsset) && assets.includes(onRampConfig.defaultOnRampAsset) ? onRampConfig.defaultOnRampAsset : assets.find(
212
- (asset2) => (activeWallet == null ? void 0 : activeWallet.type) === "COSMOS" ? asset2 === "ATOM" : (activeWallet == null ? void 0 : activeWallet.type) === "SOLANA" ? asset2 === "SOLANA" : asset2 === "ETHEREUM"
213
- ) || assets[0] || null;
214
- if (newAsset !== asset) {
215
- setAsset(newAsset);
218
+ const walletTypeChanged = prevWalletTypeRef.current !== (activeWallet == null ? void 0 : activeWallet.type);
219
+ prevWalletTypeRef.current = activeWallet == null ? void 0 : activeWallet.type;
220
+ if (assets.length === 0 || networks.length === 0) {
221
+ return;
222
+ }
223
+ if (walletTypeChanged) {
224
+ const { asset: newAsset, network: newNetwork } = getDefaultAssetAndNetwork({
225
+ walletType: activeWallet == null ? void 0 : activeWallet.type,
226
+ onRampConfig,
227
+ networks,
228
+ assets
229
+ });
230
+ if (newAsset !== asset) {
231
+ setAsset(newAsset);
232
+ }
233
+ if (newNetwork !== network) {
234
+ setNetwork(newNetwork);
235
+ }
236
+ return;
237
+ }
238
+ if (asset && !network) {
239
+ const { network: newNetwork } = getDefaultAssetAndNetwork({
240
+ walletType: activeWallet == null ? void 0 : activeWallet.type,
241
+ onRampConfig,
242
+ networks,
243
+ assets,
244
+ preferredAsset: asset
245
+ });
246
+ if (newNetwork !== network) {
247
+ setNetwork(newNetwork);
248
+ }
249
+ return;
216
250
  }
217
- if (newNetwork !== network) {
218
- setNetwork(newNetwork);
251
+ if (!network && !asset) {
252
+ const { asset: newAsset, network: newNetwork } = getDefaultAssetAndNetwork({
253
+ walletType: activeWallet == null ? void 0 : activeWallet.type,
254
+ onRampConfig,
255
+ networks,
256
+ assets
257
+ });
258
+ if (newAsset !== asset) {
259
+ setAsset(newAsset);
260
+ }
261
+ if (newNetwork !== network) {
262
+ setNetwork(newNetwork);
263
+ }
219
264
  }
220
- }, [activeWallet == null ? void 0 : activeWallet.type, assets, networks]);
265
+ }, [activeWallet == null ? void 0 : activeWallet.type, assets, networks, onRampConfig]);
221
266
  useEffect(() => {
222
267
  if (!!activeWallet && onRampStep === OnRampStep.PROVIDER && !isValid(onRampConfig, activeWallet.type, network, asset)) {
223
268
  setOnRampStep(OnRampStep.SETTINGS);
@@ -27,7 +27,7 @@ function AddFundsReceive() {
27
27
  [para, activeWallet == null ? void 0 : activeWallet.id, activeWallet == null ? void 0 : activeWallet.type]
28
28
  );
29
29
  return /* @__PURE__ */ jsxs(Fragment, { children: [
30
- (embedded == null ? void 0 : embedded.wallets) && embedded.wallets.length > 1 && /* @__PURE__ */ jsx(WalletSelectOld, { noTitle: true, style: { width: "100%" } }),
30
+ (embedded == null ? void 0 : embedded.wallets) && /* @__PURE__ */ jsx(WalletSelectOld, { noTitle: true, style: { width: "100%" } }),
31
31
  !isMobile() && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(InnerStepContainer, { children: /* @__PURE__ */ jsx(QRContainer, { children: !address ? /* @__PURE__ */ jsx(CpslSpinner, { size: 100 }) : /* @__PURE__ */ jsx(CpslQrCode, { url: address }, address) }) }) }),
32
32
  (activeWallet == null ? void 0 : activeWallet.type) && /* @__PURE__ */ jsx(InnerStepContainer, { children: /* @__PURE__ */ jsxs(CenteredText, { variant: "bodyS", weight: "semiBold", children: [
33
33
  "Only send funds on",
@@ -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
@@ -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;
@@ -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 {};