@rhinestone/deposit-modal 0.1.21 → 0.1.23

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.
@@ -0,0 +1,2346 @@
1
+ import {
2
+ Button,
3
+ ConnectStep,
4
+ Modal,
5
+ PoweredBy,
6
+ ProcessingStep,
7
+ Spinner,
8
+ accountFromPrivateKey,
9
+ applyTheme,
10
+ createDepositService,
11
+ createSessionOwnerKey,
12
+ createSmartAccount,
13
+ createViewOnlyAccount,
14
+ currencyFormatter,
15
+ formatUserError,
16
+ getAccountAddress,
17
+ getAccountInitData,
18
+ getAssetId,
19
+ getEventTxHash,
20
+ getPublicClient,
21
+ getSessionDetails,
22
+ isDepositEvent,
23
+ isNativeAsset,
24
+ loadSessionOwnerFromStorage,
25
+ portfolioToAssets,
26
+ saveSessionOwnerToStorage,
27
+ tokenFormatter
28
+ } from "./chunk-JBT2ZV3Q.mjs";
29
+ import {
30
+ CHAIN_BY_ID,
31
+ DEFAULT_BACKEND_URL,
32
+ DEFAULT_SIGNER_ADDRESS,
33
+ NATIVE_TOKEN_ADDRESS,
34
+ SOURCE_CHAINS,
35
+ getChainBadge,
36
+ getChainIcon,
37
+ getChainId,
38
+ getChainName,
39
+ getSupportedChainIds,
40
+ getSupportedTokenSymbolsForChain,
41
+ getTokenAddress,
42
+ getTokenIcon,
43
+ getTokenSymbol
44
+ } from "./chunk-A6QLADED.mjs";
45
+
46
+ // src/DepositModal.tsx
47
+ import {
48
+ useMemo as useMemo7,
49
+ useEffect as useEffect7,
50
+ useRef as useRef5,
51
+ useState as useState8,
52
+ useCallback as useCallback4,
53
+ lazy,
54
+ Suspense
55
+ } from "react";
56
+
57
+ // src/DepositFlow.tsx
58
+ import { useState as useState7, useCallback as useCallback3, useMemo as useMemo6, useEffect as useEffect6, useRef as useRef4 } from "react";
59
+
60
+ // src/components/steps/SetupStep.tsx
61
+ import { useState, useEffect, useRef, useCallback } from "react";
62
+ import { walletClientToAccount } from "@rhinestone/sdk";
63
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
64
+ async function resolveSessionOwner(eoaAddress) {
65
+ const localOwner = loadSessionOwnerFromStorage(eoaAddress);
66
+ if (localOwner) {
67
+ return {
68
+ account: accountFromPrivateKey(localOwner.privateKey),
69
+ address: localOwner.address
70
+ };
71
+ }
72
+ const created = createSessionOwnerKey();
73
+ saveSessionOwnerToStorage(eoaAddress, created.privateKey, created.address);
74
+ return {
75
+ account: created.account,
76
+ address: created.address
77
+ };
78
+ }
79
+ function SetupStep({
80
+ walletClient,
81
+ address,
82
+ targetChain,
83
+ targetChainObj,
84
+ targetToken,
85
+ rhinestoneApiKey,
86
+ signerAddress,
87
+ sessionChainIds,
88
+ recipient,
89
+ forceRegister,
90
+ service,
91
+ onSetupComplete,
92
+ onError,
93
+ onConnected
94
+ }) {
95
+ const [state, setState] = useState({ type: "idle" });
96
+ const setupInitiatedRef = useRef(false);
97
+ const runSetup = useCallback(async () => {
98
+ if (!address || !targetChainObj) {
99
+ return;
100
+ }
101
+ if (walletClient && !walletClient.account) {
102
+ return;
103
+ }
104
+ try {
105
+ setState({ type: "creating-account" });
106
+ const signerAccount = walletClient ? walletClientToAccount(walletClient) : createViewOnlyAccount(address);
107
+ const sessionOwner = await resolveSessionOwner(address);
108
+ const account = await createSmartAccount(
109
+ signerAccount,
110
+ sessionOwner.account,
111
+ rhinestoneApiKey
112
+ );
113
+ const smartAccount = getAccountAddress(account);
114
+ setState({ type: "checking" });
115
+ const checkResult = await service.checkAccount(smartAccount);
116
+ if (checkResult.isRegistered && !forceRegister) {
117
+ const targetMatches = checkResult.targetChain === targetChain && checkResult.targetToken?.toLowerCase() === targetToken.toLowerCase();
118
+ if (targetMatches) {
119
+ setState({ type: "ready", smartAccount });
120
+ onConnected?.(address, smartAccount);
121
+ onSetupComplete(smartAccount);
122
+ return;
123
+ }
124
+ }
125
+ setState({ type: "signing-session" });
126
+ const initData = getAccountInitData(account);
127
+ const sessionDetails = await getSessionDetails(
128
+ account,
129
+ targetChainObj,
130
+ signerAddress,
131
+ sessionOwner.account,
132
+ targetToken,
133
+ sessionChainIds
134
+ );
135
+ setState({ type: "registering" });
136
+ await service.registerAccount({
137
+ address: smartAccount,
138
+ accountParams: {
139
+ factory: initData.factory,
140
+ factoryData: initData.factoryData,
141
+ sessionDetails
142
+ },
143
+ eoaAddress: address,
144
+ sessionOwner: sessionOwner.address,
145
+ target: {
146
+ chain: targetChain,
147
+ token: targetToken,
148
+ ...recipient && { recipient }
149
+ }
150
+ });
151
+ setState({ type: "ready", smartAccount });
152
+ onConnected?.(address, smartAccount);
153
+ onSetupComplete(smartAccount);
154
+ } catch (error) {
155
+ const message = error instanceof Error ? error.message : "Setup failed";
156
+ setState({ type: "error", message });
157
+ onError?.(message, "SETUP_ERROR");
158
+ }
159
+ }, [
160
+ address,
161
+ walletClient,
162
+ targetChainObj,
163
+ targetChain,
164
+ targetToken,
165
+ rhinestoneApiKey,
166
+ signerAddress,
167
+ sessionChainIds,
168
+ recipient,
169
+ forceRegister,
170
+ service,
171
+ onSetupComplete,
172
+ onError,
173
+ onConnected
174
+ ]);
175
+ useEffect(() => {
176
+ const hasWallet = walletClient ? Boolean(walletClient.account) : true;
177
+ if (address && hasWallet && targetChainObj && !setupInitiatedRef.current && state.type === "idle") {
178
+ setupInitiatedRef.current = true;
179
+ runSetup();
180
+ }
181
+ }, [address, walletClient, targetChainObj, state.type, runSetup]);
182
+ const handleRetry = () => {
183
+ setupInitiatedRef.current = false;
184
+ setState({ type: "idle" });
185
+ };
186
+ const renderStateMessage = () => {
187
+ switch (state.type) {
188
+ case "idle":
189
+ return "Preparing...";
190
+ case "checking":
191
+ return "Verifying your account...";
192
+ case "creating-account":
193
+ return "Preparing your deposit account...";
194
+ case "signing-session":
195
+ return "Authorizing your deposit session...";
196
+ case "registering":
197
+ return "Finalizing setup...";
198
+ case "ready":
199
+ return "Account ready!";
200
+ case "error":
201
+ return state.message;
202
+ }
203
+ };
204
+ const isLoading = state.type === "idle" || state.type === "checking" || state.type === "creating-account" || state.type === "signing-session" || state.type === "registering";
205
+ const isError = state.type === "error";
206
+ return /* @__PURE__ */ jsxs("div", { className: "rs-step", children: [
207
+ /* @__PURE__ */ jsxs("div", { className: "rs-loading-state", children: [
208
+ isLoading && /* @__PURE__ */ jsxs(Fragment, { children: [
209
+ /* @__PURE__ */ jsx(Spinner, { className: "rs-spinner--lg rs-text-accent" }),
210
+ /* @__PURE__ */ jsxs("div", { className: "rs-loading-text", children: [
211
+ /* @__PURE__ */ jsx("div", { className: "rs-loading-title", children: renderStateMessage() }),
212
+ /* @__PURE__ */ jsx("div", { className: "rs-loading-subtitle", children: "This may take a moment" })
213
+ ] })
214
+ ] }),
215
+ isError && /* @__PURE__ */ jsxs(Fragment, { children: [
216
+ /* @__PURE__ */ jsx("div", { className: "rs-step-icon rs-step-icon--error", children: /* @__PURE__ */ jsx(
217
+ "svg",
218
+ {
219
+ viewBox: "0 0 24 24",
220
+ fill: "none",
221
+ stroke: "currentColor",
222
+ strokeWidth: "2",
223
+ children: /* @__PURE__ */ jsx(
224
+ "path",
225
+ {
226
+ strokeLinecap: "round",
227
+ strokeLinejoin: "round",
228
+ d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
229
+ }
230
+ )
231
+ }
232
+ ) }),
233
+ /* @__PURE__ */ jsxs("div", { className: "rs-loading-text", children: [
234
+ /* @__PURE__ */ jsx("div", { className: "rs-loading-title rs-text-error", children: "Setup failed" }),
235
+ /* @__PURE__ */ jsx(
236
+ "div",
237
+ {
238
+ className: "rs-loading-subtitle",
239
+ style: { maxWidth: 300, marginTop: 4 },
240
+ children: state.message
241
+ }
242
+ )
243
+ ] })
244
+ ] })
245
+ ] }),
246
+ isError && /* @__PURE__ */ jsx("div", { className: "rs-step-footer", children: /* @__PURE__ */ jsx(Button, { onClick: handleRetry, variant: "default", fullWidth: true, children: "Try Again" }) })
247
+ ] });
248
+ }
249
+
250
+ // src/components/steps/AssetSelectStep.tsx
251
+ import { useEffect as useEffect2, useMemo, useState as useState2 } from "react";
252
+ import { formatUnits } from "viem";
253
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
254
+ function AssetSelectStep({
255
+ address,
256
+ publicClient,
257
+ defaultSourceChain,
258
+ defaultSourceToken,
259
+ service,
260
+ onContinue,
261
+ onTotalBalanceComputed
262
+ }) {
263
+ const [assets, setAssets] = useState2([]);
264
+ const [selectedAssetId, setSelectedAssetId] = useState2(null);
265
+ const [loading, setLoading] = useState2(true);
266
+ const [error, setError] = useState2(null);
267
+ const defaultAssetId = useMemo(() => {
268
+ if (!defaultSourceChain || !defaultSourceToken) return null;
269
+ return getAssetId({
270
+ chainId: defaultSourceChain,
271
+ token: defaultSourceToken
272
+ });
273
+ }, [defaultSourceChain, defaultSourceToken]);
274
+ useEffect2(() => {
275
+ let active = true;
276
+ async function loadPortfolio() {
277
+ if (!address) {
278
+ setLoading(false);
279
+ return;
280
+ }
281
+ setLoading(true);
282
+ setError(null);
283
+ try {
284
+ const portfolio = await service.fetchPortfolio(address);
285
+ if (!active) return;
286
+ const portfolioAssets = portfolioToAssets(portfolio.tokens);
287
+ setAssets(portfolioAssets);
288
+ const hasNative = portfolioAssets.some(
289
+ (asset) => asset.token.toLowerCase() === NATIVE_TOKEN_ADDRESS
290
+ );
291
+ if (!hasNative) {
292
+ const nativeAssets = await fetchNativeAssets(
293
+ address,
294
+ publicClient,
295
+ portfolioAssets
296
+ );
297
+ if (!active) return;
298
+ if (nativeAssets.length > 0) {
299
+ setAssets((prev) => mergeAssets(prev, nativeAssets));
300
+ }
301
+ }
302
+ } catch (err) {
303
+ if (!active) return;
304
+ setError(
305
+ err instanceof Error ? err.message : "Failed to load portfolio"
306
+ );
307
+ } finally {
308
+ if (active) setLoading(false);
309
+ }
310
+ }
311
+ loadPortfolio();
312
+ return () => {
313
+ active = false;
314
+ };
315
+ }, [address, publicClient, service]);
316
+ useEffect2(() => {
317
+ if (!defaultAssetId || selectedAssetId) return;
318
+ if (assets.some((asset) => asset.id === defaultAssetId)) {
319
+ setSelectedAssetId(defaultAssetId);
320
+ }
321
+ }, [assets, defaultAssetId, selectedAssetId]);
322
+ useEffect2(() => {
323
+ const total = assets.reduce(
324
+ (sum, asset) => sum + (asset.balanceUsd ?? 0),
325
+ 0
326
+ );
327
+ onTotalBalanceComputed?.(total);
328
+ }, [assets, onTotalBalanceComputed]);
329
+ const rows = useMemo(() => {
330
+ return assets.filter((a) => {
331
+ try {
332
+ return BigInt(a.balance ?? "0") > BigInt(0);
333
+ } catch {
334
+ return false;
335
+ }
336
+ }).sort((a, b) => {
337
+ const usdA = a.balanceUsd ?? 0;
338
+ const usdB = b.balanceUsd ?? 0;
339
+ if (usdA !== usdB) return usdB - usdA;
340
+ const balA = BigInt(a.balance ?? "0");
341
+ const balB = BigInt(b.balance ?? "0");
342
+ if (balB > balA) return 1;
343
+ if (balB < balA) return -1;
344
+ return 0;
345
+ });
346
+ }, [assets]);
347
+ const selectedAsset = selectedAssetId && assets.find((asset) => asset.id === selectedAssetId);
348
+ const formatBalance = (asset) => {
349
+ if (!asset.balance) return "--";
350
+ try {
351
+ const raw = formatUnits(BigInt(asset.balance), asset.decimals);
352
+ const numeric = Number(raw);
353
+ if (!Number.isFinite(numeric)) return raw;
354
+ return tokenFormatter.format(numeric);
355
+ } catch {
356
+ return asset.balance;
357
+ }
358
+ };
359
+ return /* @__PURE__ */ jsxs2("div", { className: "rs-step", children: [
360
+ /* @__PURE__ */ jsx2("div", { style: { padding: "12px 12px 4px" }, children: /* @__PURE__ */ jsx2("div", { className: "rs-step-title", children: "Select source asset" }) }),
361
+ /* @__PURE__ */ jsxs2(
362
+ "div",
363
+ {
364
+ className: "rs-step-body",
365
+ style: { paddingTop: 4, overflow: "auto", maxHeight: 340 },
366
+ children: [
367
+ loading && /* @__PURE__ */ jsxs2("div", { className: "rs-loading-state", style: { padding: "40px 12px" }, children: [
368
+ /* @__PURE__ */ jsx2(Spinner, { className: "rs-text-tertiary" }),
369
+ /* @__PURE__ */ jsx2("span", { className: "rs-text-sm rs-text-tertiary", children: "Loading balances" })
370
+ ] }),
371
+ error && /* @__PURE__ */ jsx2("div", { className: "rs-alert rs-alert--error", children: /* @__PURE__ */ jsx2("span", { className: "rs-alert-text", children: error }) }),
372
+ !loading && !error && rows.length === 0 && /* @__PURE__ */ jsxs2("div", { className: "rs-empty-state", children: [
373
+ /* @__PURE__ */ jsx2(
374
+ "svg",
375
+ {
376
+ className: "rs-empty-icon",
377
+ viewBox: "0 0 24 24",
378
+ fill: "none",
379
+ stroke: "currentColor",
380
+ strokeWidth: "1.5",
381
+ children: /* @__PURE__ */ jsx2(
382
+ "path",
383
+ {
384
+ strokeLinecap: "round",
385
+ strokeLinejoin: "round",
386
+ d: "M21 12a2.25 2.25 0 00-2.25-2.25H15a3 3 0 11-6 0H5.25A2.25 2.25 0 003 12m18 0v6a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 18v-6m18 0V9M3 12V9m18 0a2.25 2.25 0 00-2.25-2.25H5.25A2.25 2.25 0 003 9m18 0V6a2.25 2.25 0 00-2.25-2.25H5.25A2.25 2.25 0 003 6v3"
387
+ }
388
+ )
389
+ }
390
+ ),
391
+ /* @__PURE__ */ jsx2("div", { className: "rs-empty-text", children: "No funds in connected wallet" }),
392
+ /* @__PURE__ */ jsxs2("div", { className: "rs-empty-address", children: [
393
+ address.slice(0, 6),
394
+ "...",
395
+ address.slice(-4)
396
+ ] })
397
+ ] }),
398
+ !loading && !error && rows.length > 0 && /* @__PURE__ */ jsx2("div", { className: "rs-asset-list", children: rows.map((asset) => {
399
+ const isSelected = selectedAssetId === asset.id;
400
+ const tokenAmount = formatBalance(asset);
401
+ const badge = getChainBadge(asset.chainId);
402
+ const tokenIcon = getTokenIcon(asset.symbol);
403
+ const chainIcon = getChainIcon(asset.chainId);
404
+ return /* @__PURE__ */ jsxs2(
405
+ "button",
406
+ {
407
+ type: "button",
408
+ onClick: () => setSelectedAssetId(asset.id),
409
+ className: `rs-asset-row ${isSelected ? "rs-asset-row--selected" : ""}`,
410
+ style: { textAlign: "left" },
411
+ children: [
412
+ /* @__PURE__ */ jsxs2("div", { className: "rs-asset-info", children: [
413
+ /* @__PURE__ */ jsxs2("div", { className: "rs-asset-icon-wrapper", children: [
414
+ tokenIcon ? /* @__PURE__ */ jsx2(
415
+ "img",
416
+ {
417
+ src: tokenIcon,
418
+ alt: asset.symbol,
419
+ className: "rs-asset-icon",
420
+ style: { background: "transparent" }
421
+ }
422
+ ) : /* @__PURE__ */ jsx2("div", { className: "rs-asset-icon", children: asset.symbol.slice(0, 4) }),
423
+ chainIcon ? /* @__PURE__ */ jsx2(
424
+ "img",
425
+ {
426
+ src: chainIcon,
427
+ alt: getChainName(asset.chainId),
428
+ className: "rs-asset-chain-badge"
429
+ }
430
+ ) : /* @__PURE__ */ jsx2(
431
+ "div",
432
+ {
433
+ className: "rs-asset-chain-badge",
434
+ style: {
435
+ backgroundColor: badge.bg,
436
+ color: badge.color
437
+ },
438
+ children: badge.shortLabel.charAt(0)
439
+ }
440
+ )
441
+ ] }),
442
+ /* @__PURE__ */ jsxs2("div", { children: [
443
+ /* @__PURE__ */ jsxs2("div", { className: "rs-asset-name", children: [
444
+ asset.symbol,
445
+ /* @__PURE__ */ jsxs2("span", { className: "rs-asset-chain", children: [
446
+ " ",
447
+ "on ",
448
+ getChainName(asset.chainId)
449
+ ] })
450
+ ] }),
451
+ /* @__PURE__ */ jsxs2("div", { className: "rs-asset-balance-small", children: [
452
+ tokenAmount,
453
+ " ",
454
+ asset.symbol
455
+ ] })
456
+ ] })
457
+ ] }),
458
+ /* @__PURE__ */ jsx2("div", { className: "rs-asset-balance", children: asset.balanceUsd !== void 0 ? currencyFormatter.format(asset.balanceUsd) : tokenAmount !== "--" ? `${tokenAmount} ${asset.symbol}` : "--" })
459
+ ]
460
+ },
461
+ asset.id
462
+ );
463
+ }) })
464
+ ]
465
+ }
466
+ ),
467
+ /* @__PURE__ */ jsx2("div", { className: "rs-step-footer", children: /* @__PURE__ */ jsx2(
468
+ Button,
469
+ {
470
+ onClick: () => selectedAsset && onContinue(selectedAsset),
471
+ disabled: !selectedAsset,
472
+ fullWidth: true,
473
+ children: "Continue"
474
+ }
475
+ ) }),
476
+ /* @__PURE__ */ jsx2(PoweredBy, {})
477
+ ] });
478
+ }
479
+ async function fetchNativeAssets(address, publicClient, existing) {
480
+ const existingIds = new Set(existing.map((asset) => asset.id));
481
+ const connectedChainId = publicClient.chain?.id;
482
+ if (!connectedChainId) return [];
483
+ if (!SOURCE_CHAINS.some((chain) => chain.id === connectedChainId)) return [];
484
+ const id = getAssetId({
485
+ chainId: connectedChainId,
486
+ token: NATIVE_TOKEN_ADDRESS
487
+ });
488
+ if (existingIds.has(id)) return [];
489
+ try {
490
+ const balance = await publicClient.getBalance({ address });
491
+ return [
492
+ {
493
+ id,
494
+ chainId: connectedChainId,
495
+ token: NATIVE_TOKEN_ADDRESS,
496
+ symbol: "ETH",
497
+ name: "Ethereum",
498
+ decimals: 18,
499
+ balance: balance.toString()
500
+ }
501
+ ];
502
+ } catch {
503
+ return [];
504
+ }
505
+ }
506
+ function mergeAssets(existing, incoming) {
507
+ if (incoming.length === 0) return existing;
508
+ const existingIds = new Set(existing.map((asset) => asset.id));
509
+ const merged = [...existing];
510
+ for (const asset of incoming) {
511
+ if (!existingIds.has(asset.id)) {
512
+ merged.push(asset);
513
+ }
514
+ }
515
+ return merged;
516
+ }
517
+
518
+ // src/components/steps/AmountStep.tsx
519
+ import { useEffect as useEffect3, useMemo as useMemo2, useState as useState3, useRef as useRef2 } from "react";
520
+ import { erc20Abi, formatUnits as formatUnits2, parseUnits } from "viem";
521
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
522
+ function AmountStep({
523
+ walletClient,
524
+ publicClient,
525
+ address,
526
+ balanceAddress,
527
+ asset,
528
+ defaultAmount,
529
+ switchChain,
530
+ targetChain,
531
+ targetToken,
532
+ uiConfig,
533
+ tokenPriceUsdOverride,
534
+ onBalanceUsdChange,
535
+ onContinue
536
+ }) {
537
+ const [amountUsd, setAmountUsd] = useState3("");
538
+ const [balance, setBalance] = useState3(null);
539
+ const [error, setError] = useState3(null);
540
+ const [isSwitching, setIsSwitching] = useState3(false);
541
+ const hasAttemptedSwitch = useRef2(false);
542
+ const chainMismatch = Boolean(
543
+ walletClient?.chain?.id && walletClient.chain.id !== asset.chainId
544
+ );
545
+ const tokenPriceUsd = useMemo2(() => {
546
+ if (tokenPriceUsdOverride !== void 0) return tokenPriceUsdOverride;
547
+ if (asset.balanceUsd === void 0 || !asset.balance) return null;
548
+ try {
549
+ const balanceUnits = Number(
550
+ formatUnits2(BigInt(asset.balance), asset.decimals)
551
+ );
552
+ if (!Number.isFinite(balanceUnits) || balanceUnits <= 0) return null;
553
+ return asset.balanceUsd / balanceUnits;
554
+ } catch {
555
+ return null;
556
+ }
557
+ }, [tokenPriceUsdOverride, asset.balanceUsd, asset.balance, asset.decimals]);
558
+ useEffect3(() => {
559
+ let active = true;
560
+ async function fetchBalance() {
561
+ const balanceTarget = balanceAddress ?? address;
562
+ if (!balanceTarget || !publicClient) return;
563
+ try {
564
+ const bal = isNativeAsset(asset) ? await publicClient.getBalance({ address: balanceTarget }) : await publicClient.readContract({
565
+ address: asset.token,
566
+ abi: erc20Abi,
567
+ functionName: "balanceOf",
568
+ args: [balanceTarget]
569
+ });
570
+ if (active) {
571
+ setBalance(bal);
572
+ }
573
+ } catch {
574
+ if (active) {
575
+ setBalance(null);
576
+ }
577
+ }
578
+ }
579
+ fetchBalance();
580
+ return () => {
581
+ active = false;
582
+ };
583
+ }, [address, balanceAddress, publicClient, asset]);
584
+ useEffect3(() => {
585
+ if (chainMismatch && switchChain && !hasAttemptedSwitch.current) {
586
+ hasAttemptedSwitch.current = true;
587
+ setIsSwitching(true);
588
+ switchChain(asset.chainId).catch((err) => {
589
+ const message = err instanceof Error ? err.message : "Failed to switch chain";
590
+ setError(message);
591
+ }).finally(() => {
592
+ setIsSwitching(false);
593
+ });
594
+ }
595
+ }, [chainMismatch, switchChain, asset.chainId]);
596
+ useEffect3(() => {
597
+ if (defaultAmount && tokenPriceUsd !== null && !amountUsd) {
598
+ const parsed = Number(defaultAmount);
599
+ if (Number.isFinite(parsed) && parsed > 0) {
600
+ const usdValue = parsed * tokenPriceUsd;
601
+ setAmountUsd(usdValue.toFixed(2));
602
+ }
603
+ }
604
+ }, [defaultAmount, tokenPriceUsd, amountUsd]);
605
+ const balanceUsd = useMemo2(() => {
606
+ if (balance === null || tokenPriceUsd === null) return null;
607
+ try {
608
+ const balanceUnits = Number(formatUnits2(balance, asset.decimals));
609
+ if (!Number.isFinite(balanceUnits)) return null;
610
+ return balanceUnits * tokenPriceUsd;
611
+ } catch {
612
+ return null;
613
+ }
614
+ }, [balance, tokenPriceUsd, asset.decimals]);
615
+ useEffect3(() => {
616
+ if (balanceUsd === null) return;
617
+ onBalanceUsdChange?.(balanceUsd);
618
+ }, [balanceUsd, onBalanceUsdChange]);
619
+ const formattedBalance = useMemo2(() => {
620
+ if (balance === null) return "...";
621
+ try {
622
+ const raw = formatUnits2(balance, asset.decimals);
623
+ const numeric = Number(raw);
624
+ if (!Number.isFinite(numeric)) return raw;
625
+ return tokenFormatter.format(numeric);
626
+ } catch {
627
+ return "...";
628
+ }
629
+ }, [balance, asset.decimals]);
630
+ const tokenAmount = useMemo2(() => {
631
+ if (!amountUsd || tokenPriceUsd === null || tokenPriceUsd === 0)
632
+ return null;
633
+ const usd = Number(amountUsd);
634
+ if (!Number.isFinite(usd) || usd <= 0) return null;
635
+ return usd / tokenPriceUsd;
636
+ }, [amountUsd, tokenPriceUsd]);
637
+ const formattedTokenAmount = useMemo2(() => {
638
+ if (tokenAmount === null) return "0.00";
639
+ return tokenFormatter.format(tokenAmount);
640
+ }, [tokenAmount]);
641
+ const targetSymbol = getTokenSymbol(targetToken, targetChain);
642
+ const handlePresetClick = (percentage) => {
643
+ if (balanceUsd === null) return;
644
+ const value = balanceUsd * percentage / 100;
645
+ setAmountUsd(value.toFixed(2));
646
+ if (error) setError(null);
647
+ };
648
+ const handleContinue = () => {
649
+ const usdValue = parseFloat(amountUsd);
650
+ if (isNaN(usdValue) || usdValue <= 0) {
651
+ setError("Please enter a valid amount");
652
+ return;
653
+ }
654
+ if (uiConfig?.maxDepositUsd && usdValue > uiConfig.maxDepositUsd) {
655
+ setError(
656
+ `Maximum deposit is ${currencyFormatter.format(uiConfig.maxDepositUsd)}`
657
+ );
658
+ return;
659
+ }
660
+ if (uiConfig?.minDepositUsd && usdValue < uiConfig.minDepositUsd) {
661
+ setError(
662
+ `Minimum deposit is ${currencyFormatter.format(uiConfig.minDepositUsd)}`
663
+ );
664
+ return;
665
+ }
666
+ if (tokenPriceUsd === null || tokenPriceUsd === 0) {
667
+ setError("Unable to determine token price");
668
+ return;
669
+ }
670
+ const tokenAmountValue = usdValue / tokenPriceUsd;
671
+ let tokenAmountStr = tokenAmountValue.toString();
672
+ let amountInUnits;
673
+ try {
674
+ amountInUnits = parseUnits(tokenAmountStr, asset.decimals);
675
+ } catch {
676
+ setError("Please enter a valid amount");
677
+ return;
678
+ }
679
+ if (balance !== null && amountInUnits > balance) {
680
+ amountInUnits = balance;
681
+ tokenAmountStr = formatUnits2(balance, asset.decimals);
682
+ }
683
+ setError(null);
684
+ onContinue(tokenAmountStr, balance ?? void 0);
685
+ };
686
+ const handleSwitch = async () => {
687
+ if (!asset.chainId || !switchChain) return;
688
+ setIsSwitching(true);
689
+ try {
690
+ await switchChain(asset.chainId);
691
+ } catch (err) {
692
+ const message = err instanceof Error ? err.message : "Failed to switch chain";
693
+ setError(message);
694
+ } finally {
695
+ setIsSwitching(false);
696
+ }
697
+ };
698
+ return /* @__PURE__ */ jsxs3("div", { className: "rs-step", children: [
699
+ /* @__PURE__ */ jsxs3("div", { className: "rs-step-body", style: { paddingTop: 0 }, children: [
700
+ /* @__PURE__ */ jsxs3("div", { className: "rs-amount-display", children: [
701
+ /* @__PURE__ */ jsx3("div", { className: "rs-amount-input-wrapper", children: /* @__PURE__ */ jsx3(
702
+ "input",
703
+ {
704
+ type: "text",
705
+ inputMode: "decimal",
706
+ className: "rs-amount-input-large",
707
+ placeholder: "$0.00",
708
+ value: amountUsd ? `$${amountUsd}` : "",
709
+ onChange: (e) => {
710
+ const raw = e.target.value.replace(/[^0-9.]/g, "");
711
+ const parts = raw.split(".");
712
+ if (parts.length > 2) return;
713
+ setAmountUsd(raw);
714
+ if (error) setError(null);
715
+ },
716
+ autoFocus: true
717
+ }
718
+ ) }),
719
+ /* @__PURE__ */ jsxs3("div", { className: "rs-amount-token-value", children: [
720
+ formattedTokenAmount,
721
+ " ",
722
+ asset.symbol
723
+ ] }),
724
+ /* @__PURE__ */ jsx3("div", { className: "rs-amount-available", children: /* @__PURE__ */ jsxs3("span", { className: "rs-amount-available-value", children: [
725
+ formattedBalance,
726
+ " ",
727
+ asset.symbol,
728
+ " available",
729
+ balanceUsd !== null && /* @__PURE__ */ jsxs3("span", { style: { color: "var(--rs-muted-foreground)" }, children: [
730
+ " ",
731
+ "(",
732
+ currencyFormatter.format(balanceUsd),
733
+ ")"
734
+ ] })
735
+ ] }) })
736
+ ] }),
737
+ /* @__PURE__ */ jsx3(
738
+ "div",
739
+ {
740
+ style: { display: "flex", justifyContent: "center", marginTop: 16 },
741
+ children: /* @__PURE__ */ jsxs3("div", { className: "rs-flow-pill", children: [
742
+ /* @__PURE__ */ jsxs3("div", { className: "rs-flow-pill-side", children: [
743
+ /* @__PURE__ */ jsx3("span", { className: "rs-flow-pill-label", children: "You send" }),
744
+ /* @__PURE__ */ jsxs3("div", { className: "rs-flow-pill-token", children: [
745
+ /* @__PURE__ */ jsxs3("div", { className: "rs-flow-pill-token-icon-wrapper", children: [
746
+ /* @__PURE__ */ jsx3("div", { className: "rs-flow-pill-token-icon", children: getTokenIcon(asset.symbol) ? /* @__PURE__ */ jsx3(
747
+ "img",
748
+ {
749
+ src: getTokenIcon(asset.symbol),
750
+ alt: asset.symbol
751
+ }
752
+ ) : asset.symbol.slice(0, 2) }),
753
+ (() => {
754
+ const chainIcon = getChainIcon(asset.chainId);
755
+ if (chainIcon) {
756
+ return /* @__PURE__ */ jsx3(
757
+ "img",
758
+ {
759
+ src: chainIcon,
760
+ alt: getChainName(asset.chainId),
761
+ className: "rs-flow-pill-chain-badge"
762
+ }
763
+ );
764
+ }
765
+ const badge = getChainBadge(asset.chainId);
766
+ return /* @__PURE__ */ jsx3(
767
+ "div",
768
+ {
769
+ className: "rs-flow-pill-chain-badge",
770
+ style: {
771
+ backgroundColor: badge.bg,
772
+ color: badge.color
773
+ },
774
+ children: badge.shortLabel.charAt(0)
775
+ }
776
+ );
777
+ })()
778
+ ] }),
779
+ /* @__PURE__ */ jsx3("span", { className: "rs-flow-pill-token-symbol", children: asset.symbol })
780
+ ] })
781
+ ] }),
782
+ /* @__PURE__ */ jsx3("div", { className: "rs-flow-pill-arrow", children: /* @__PURE__ */ jsx3(
783
+ "svg",
784
+ {
785
+ viewBox: "0 0 24 24",
786
+ fill: "none",
787
+ stroke: "currentColor",
788
+ strokeWidth: "2",
789
+ children: /* @__PURE__ */ jsx3(
790
+ "path",
791
+ {
792
+ strokeLinecap: "round",
793
+ strokeLinejoin: "round",
794
+ d: "M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"
795
+ }
796
+ )
797
+ }
798
+ ) }),
799
+ /* @__PURE__ */ jsxs3("div", { className: "rs-flow-pill-side", children: [
800
+ /* @__PURE__ */ jsx3("span", { className: "rs-flow-pill-label", children: "You receive" }),
801
+ /* @__PURE__ */ jsxs3("div", { className: "rs-flow-pill-token", children: [
802
+ /* @__PURE__ */ jsxs3("div", { className: "rs-flow-pill-token-icon-wrapper", children: [
803
+ /* @__PURE__ */ jsx3("div", { className: "rs-flow-pill-token-icon", children: getTokenIcon(targetSymbol) ? /* @__PURE__ */ jsx3(
804
+ "img",
805
+ {
806
+ src: getTokenIcon(targetSymbol),
807
+ alt: targetSymbol
808
+ }
809
+ ) : targetSymbol.slice(0, 2) }),
810
+ (() => {
811
+ const chainIcon = getChainIcon(targetChain);
812
+ if (chainIcon) {
813
+ return /* @__PURE__ */ jsx3(
814
+ "img",
815
+ {
816
+ src: chainIcon,
817
+ alt: getChainName(targetChain),
818
+ className: "rs-flow-pill-chain-badge"
819
+ }
820
+ );
821
+ }
822
+ const badge = getChainBadge(targetChain);
823
+ return /* @__PURE__ */ jsx3(
824
+ "div",
825
+ {
826
+ className: "rs-flow-pill-chain-badge",
827
+ style: {
828
+ backgroundColor: badge.bg,
829
+ color: badge.color
830
+ },
831
+ children: badge.shortLabel.charAt(0)
832
+ }
833
+ );
834
+ })()
835
+ ] }),
836
+ /* @__PURE__ */ jsx3("span", { className: "rs-flow-pill-token-symbol", children: targetSymbol })
837
+ ] })
838
+ ] })
839
+ ] })
840
+ }
841
+ ),
842
+ /* @__PURE__ */ jsxs3("div", { className: "rs-amount-presets", children: [
843
+ [25, 50, 75].map((pct) => /* @__PURE__ */ jsxs3(
844
+ "button",
845
+ {
846
+ type: "button",
847
+ className: "rs-amount-preset-btn",
848
+ onClick: () => handlePresetClick(pct),
849
+ disabled: balanceUsd === null,
850
+ children: [
851
+ pct,
852
+ "%"
853
+ ]
854
+ },
855
+ pct
856
+ )),
857
+ /* @__PURE__ */ jsx3(
858
+ "button",
859
+ {
860
+ type: "button",
861
+ className: "rs-amount-preset-btn",
862
+ onClick: () => handlePresetClick(100),
863
+ disabled: balanceUsd === null,
864
+ children: "Max"
865
+ }
866
+ )
867
+ ] }),
868
+ chainMismatch && /* @__PURE__ */ jsxs3("div", { className: "rs-chain-switch", style: { marginTop: 16 }, children: [
869
+ /* @__PURE__ */ jsxs3("div", { className: "rs-chain-switch-text", children: [
870
+ "Switch your wallet to ",
871
+ getChainName(asset.chainId),
872
+ " to continue."
873
+ ] }),
874
+ switchChain && /* @__PURE__ */ jsx3(
875
+ Button,
876
+ {
877
+ variant: "outline",
878
+ size: "small",
879
+ loading: isSwitching,
880
+ onClick: handleSwitch,
881
+ children: "Switch"
882
+ }
883
+ )
884
+ ] }),
885
+ error && /* @__PURE__ */ jsxs3("div", { className: "rs-amount-error", children: [
886
+ /* @__PURE__ */ jsx3(
887
+ "svg",
888
+ {
889
+ viewBox: "0 0 24 24",
890
+ fill: "none",
891
+ stroke: "currentColor",
892
+ strokeWidth: "2",
893
+ style: { width: 16, height: 16, flexShrink: 0 },
894
+ children: /* @__PURE__ */ jsx3(
895
+ "path",
896
+ {
897
+ strokeLinecap: "round",
898
+ strokeLinejoin: "round",
899
+ d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
900
+ }
901
+ )
902
+ }
903
+ ),
904
+ /* @__PURE__ */ jsx3("span", { children: error })
905
+ ] })
906
+ ] }),
907
+ /* @__PURE__ */ jsx3("div", { className: "rs-step-footer", children: /* @__PURE__ */ jsx3(
908
+ Button,
909
+ {
910
+ onClick: handleContinue,
911
+ fullWidth: true,
912
+ disabled: !amountUsd || chainMismatch,
913
+ children: "Continue"
914
+ }
915
+ ) }),
916
+ /* @__PURE__ */ jsx3(PoweredBy, {})
917
+ ] });
918
+ }
919
+
920
+ // src/components/steps/ConfirmStep.tsx
921
+ import { useMemo as useMemo3, useState as useState4 } from "react";
922
+ import { erc20Abi as erc20Abi2, formatUnits as formatUnits3, parseUnits as parseUnits2 } from "viem";
923
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
924
+ var STABLECOIN_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USDT", "DAI"]);
925
+ function ConfirmStep({
926
+ walletClient,
927
+ address,
928
+ smartAccount,
929
+ recipient,
930
+ asset,
931
+ amount,
932
+ balance,
933
+ targetChain,
934
+ targetToken,
935
+ switchChain,
936
+ onConfirm,
937
+ onError,
938
+ onDepositSubmitted
939
+ }) {
940
+ const [isSubmitting, setIsSubmitting] = useState4(false);
941
+ const [error, setError] = useState4(null);
942
+ const [isSwitching, setIsSwitching] = useState4(false);
943
+ const chainMismatch = walletClient?.chain?.id && walletClient.chain.id !== asset.chainId;
944
+ const sameRoute = targetChain === asset.chainId && targetToken.toLowerCase() === asset.token.toLowerCase();
945
+ const targetSymbol = sameRoute ? asset.symbol : getTokenSymbol(targetToken, targetChain);
946
+ const formattedAmount = amount && !Number.isNaN(Number(amount)) ? Number(amount).toLocaleString("en-US", { maximumFractionDigits: 6 }) : "0";
947
+ const tokenPriceUsd = useMemo3(() => {
948
+ if (asset.balanceUsd === void 0 || !asset.balance) return null;
949
+ try {
950
+ const balanceUnits = Number(
951
+ formatUnits3(BigInt(asset.balance), asset.decimals)
952
+ );
953
+ if (!Number.isFinite(balanceUnits) || balanceUnits <= 0) return null;
954
+ return asset.balanceUsd / balanceUnits;
955
+ } catch {
956
+ return null;
957
+ }
958
+ }, [asset.balanceUsd, asset.balance, asset.decimals]);
959
+ const amountUsd = useMemo3(() => {
960
+ if (!amount || tokenPriceUsd === null) return null;
961
+ const parsed = Number(amount);
962
+ if (!Number.isFinite(parsed) || parsed <= 0) return null;
963
+ return parsed * tokenPriceUsd;
964
+ }, [amount, tokenPriceUsd]);
965
+ const targetTokenPriceUsd = useMemo3(() => {
966
+ const targetSym = targetSymbol.toUpperCase();
967
+ const sourceSym = asset.symbol.toUpperCase();
968
+ if (STABLECOIN_SYMBOLS.has(targetSym)) return 1;
969
+ if (targetSym === sourceSym && tokenPriceUsd !== null) return tokenPriceUsd;
970
+ return null;
971
+ }, [targetSymbol, asset.symbol, tokenPriceUsd]);
972
+ const receiveAmountUsd = useMemo3(() => {
973
+ if (amountUsd === null) return null;
974
+ return sameRoute ? amountUsd : amountUsd * 0.99;
975
+ }, [amountUsd, sameRoute]);
976
+ const receiveTokenAmount = useMemo3(() => {
977
+ if (sameRoute) {
978
+ const parsed = Number(amount);
979
+ return Number.isFinite(parsed) ? parsed : null;
980
+ }
981
+ if (receiveAmountUsd === null || targetTokenPriceUsd === null || targetTokenPriceUsd === 0)
982
+ return null;
983
+ return receiveAmountUsd / targetTokenPriceUsd;
984
+ }, [sameRoute, amount, receiveAmountUsd, targetTokenPriceUsd]);
985
+ const formattedReceiveAmount = useMemo3(() => {
986
+ if (receiveTokenAmount === null) return `~ ${formattedAmount}`;
987
+ return receiveTokenAmount.toLocaleString("en-US", {
988
+ maximumFractionDigits: 6
989
+ });
990
+ }, [receiveTokenAmount, formattedAmount]);
991
+ const receiveAmount = sameRoute ? formattedReceiveAmount : `~ ${formattedReceiveAmount}`;
992
+ const handleConfirm = async () => {
993
+ if (!address || !walletClient) {
994
+ setError("Wallet not connected");
995
+ return;
996
+ }
997
+ if (chainMismatch) {
998
+ setError(`Switch to ${getChainName(asset.chainId)} to sign`);
999
+ return;
1000
+ }
1001
+ const parsedAmount = parseFloat(amount);
1002
+ if (isNaN(parsedAmount) || parsedAmount <= 0) {
1003
+ setError("Please enter a valid amount");
1004
+ return;
1005
+ }
1006
+ let amountUnits;
1007
+ try {
1008
+ amountUnits = parseUnits2(amount, asset.decimals);
1009
+ } catch {
1010
+ setError("Please enter a valid amount");
1011
+ return;
1012
+ }
1013
+ if (balance !== void 0 && amountUnits > balance) {
1014
+ setError("Insufficient balance");
1015
+ return;
1016
+ }
1017
+ setError(null);
1018
+ setIsSubmitting(true);
1019
+ try {
1020
+ const account = walletClient.account;
1021
+ const chain = walletClient.chain;
1022
+ if (!account || !chain) {
1023
+ throw new Error("Wallet not properly connected");
1024
+ }
1025
+ const transferTo = sameRoute ? recipient : smartAccount;
1026
+ const hash = isNativeAsset(asset) ? await walletClient.sendTransaction({
1027
+ account,
1028
+ chain,
1029
+ to: transferTo,
1030
+ value: amountUnits
1031
+ }) : await walletClient.writeContract({
1032
+ account,
1033
+ chain,
1034
+ address: asset.token,
1035
+ abi: erc20Abi2,
1036
+ functionName: "transfer",
1037
+ args: [transferTo, amountUnits]
1038
+ });
1039
+ onDepositSubmitted?.(hash, asset.chainId, amountUnits.toString());
1040
+ onConfirm(hash, asset.chainId, amountUnits.toString(), asset.token);
1041
+ } catch (err) {
1042
+ const raw = err instanceof Error ? err.message : "Transfer failed";
1043
+ const message = formatUserError(raw);
1044
+ setError(message);
1045
+ onError?.(message, "TRANSFER_ERROR");
1046
+ } finally {
1047
+ setIsSubmitting(false);
1048
+ }
1049
+ };
1050
+ const handleSwitch = async () => {
1051
+ if (!switchChain) return;
1052
+ setIsSwitching(true);
1053
+ try {
1054
+ await switchChain(asset.chainId);
1055
+ } catch (err) {
1056
+ const raw = err instanceof Error ? err.message : "Failed to switch chain";
1057
+ setError(formatUserError(raw));
1058
+ } finally {
1059
+ setIsSwitching(false);
1060
+ }
1061
+ };
1062
+ return /* @__PURE__ */ jsxs4("div", { className: "rs-step", children: [
1063
+ /* @__PURE__ */ jsx4("div", { style: { padding: "12px 12px 10px" }, children: /* @__PURE__ */ jsx4("div", { className: "rs-step-title", children: "Review order" }) }),
1064
+ /* @__PURE__ */ jsxs4("div", { className: "rs-step-body rs-space-y-3", style: { paddingTop: 0 }, children: [
1065
+ /* @__PURE__ */ jsxs4("div", { className: "rs-card", children: [
1066
+ /* @__PURE__ */ jsxs4("div", { className: "rs-card-row", children: [
1067
+ /* @__PURE__ */ jsx4("span", { className: "rs-card-label", children: "Source" }),
1068
+ /* @__PURE__ */ jsxs4(
1069
+ "span",
1070
+ {
1071
+ className: "rs-card-value",
1072
+ style: { display: "flex", alignItems: "center", gap: 8 },
1073
+ children: [
1074
+ getChainIcon(asset.chainId) && /* @__PURE__ */ jsx4(
1075
+ "img",
1076
+ {
1077
+ src: getChainIcon(asset.chainId),
1078
+ alt: "",
1079
+ style: { width: 16, height: 16, borderRadius: "50%" }
1080
+ }
1081
+ ),
1082
+ getChainName(asset.chainId)
1083
+ ]
1084
+ }
1085
+ )
1086
+ ] }),
1087
+ /* @__PURE__ */ jsxs4("div", { className: "rs-card-row", children: [
1088
+ /* @__PURE__ */ jsx4("span", { className: "rs-card-label", children: "Destination" }),
1089
+ /* @__PURE__ */ jsxs4(
1090
+ "span",
1091
+ {
1092
+ className: "rs-card-value",
1093
+ style: { display: "flex", alignItems: "center", gap: 8 },
1094
+ children: [
1095
+ getChainIcon(targetChain) && /* @__PURE__ */ jsx4(
1096
+ "img",
1097
+ {
1098
+ src: getChainIcon(targetChain),
1099
+ alt: "",
1100
+ style: { width: 16, height: 16, borderRadius: "50%" }
1101
+ }
1102
+ ),
1103
+ getChainName(targetChain)
1104
+ ]
1105
+ }
1106
+ )
1107
+ ] }),
1108
+ /* @__PURE__ */ jsxs4("div", { className: "rs-card-row", children: [
1109
+ /* @__PURE__ */ jsx4("span", { className: "rs-card-label", children: "Estimated time" }),
1110
+ /* @__PURE__ */ jsx4("span", { className: "rs-card-value", children: "< 1 min" })
1111
+ ] })
1112
+ ] }),
1113
+ /* @__PURE__ */ jsxs4("div", { className: "rs-card", children: [
1114
+ /* @__PURE__ */ jsxs4("div", { className: "rs-card-row", children: [
1115
+ /* @__PURE__ */ jsx4("span", { className: "rs-card-label", children: "You send" }),
1116
+ /* @__PURE__ */ jsxs4(
1117
+ "span",
1118
+ {
1119
+ className: "rs-card-value",
1120
+ style: { display: "flex", alignItems: "center", gap: 6 },
1121
+ children: [
1122
+ getTokenIcon(asset.symbol) && /* @__PURE__ */ jsx4(
1123
+ "img",
1124
+ {
1125
+ src: getTokenIcon(asset.symbol),
1126
+ alt: "",
1127
+ style: { width: 16, height: 16, borderRadius: "50%" }
1128
+ }
1129
+ ),
1130
+ formattedAmount,
1131
+ " ",
1132
+ asset.symbol
1133
+ ]
1134
+ }
1135
+ )
1136
+ ] }),
1137
+ /* @__PURE__ */ jsxs4("div", { className: "rs-card-row", children: [
1138
+ /* @__PURE__ */ jsx4("span", { className: "rs-card-label", children: "You receive" }),
1139
+ /* @__PURE__ */ jsxs4(
1140
+ "span",
1141
+ {
1142
+ className: "rs-card-value",
1143
+ style: { display: "flex", alignItems: "center", gap: 6 },
1144
+ children: [
1145
+ getTokenIcon(targetSymbol) && /* @__PURE__ */ jsx4(
1146
+ "img",
1147
+ {
1148
+ src: getTokenIcon(targetSymbol),
1149
+ alt: "",
1150
+ style: { width: 16, height: 16, borderRadius: "50%" }
1151
+ }
1152
+ ),
1153
+ receiveAmount,
1154
+ " ",
1155
+ targetSymbol
1156
+ ]
1157
+ }
1158
+ )
1159
+ ] }),
1160
+ receiveAmountUsd !== null && /* @__PURE__ */ jsxs4("div", { className: "rs-card-row", children: [
1161
+ /* @__PURE__ */ jsx4("span", { className: "rs-card-label", children: "Value" }),
1162
+ /* @__PURE__ */ jsx4("span", { className: "rs-card-value", children: currencyFormatter.format(receiveAmountUsd) })
1163
+ ] })
1164
+ ] }),
1165
+ chainMismatch && /* @__PURE__ */ jsxs4("div", { className: "rs-chain-switch", children: [
1166
+ /* @__PURE__ */ jsxs4("div", { className: "rs-chain-switch-text", children: [
1167
+ "Switch your wallet to ",
1168
+ getChainName(asset.chainId),
1169
+ " to sign."
1170
+ ] }),
1171
+ switchChain && /* @__PURE__ */ jsx4(
1172
+ Button,
1173
+ {
1174
+ variant: "outline",
1175
+ size: "small",
1176
+ loading: isSwitching,
1177
+ onClick: handleSwitch,
1178
+ children: "Switch"
1179
+ }
1180
+ )
1181
+ ] }),
1182
+ error && /* @__PURE__ */ jsxs4("div", { className: "rs-alert rs-alert--error", children: [
1183
+ /* @__PURE__ */ jsx4(
1184
+ "svg",
1185
+ {
1186
+ className: "rs-alert-icon",
1187
+ viewBox: "0 0 24 24",
1188
+ fill: "none",
1189
+ stroke: "currentColor",
1190
+ strokeWidth: "2",
1191
+ children: /* @__PURE__ */ jsx4(
1192
+ "path",
1193
+ {
1194
+ strokeLinecap: "round",
1195
+ strokeLinejoin: "round",
1196
+ d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
1197
+ }
1198
+ )
1199
+ }
1200
+ ),
1201
+ /* @__PURE__ */ jsx4("span", { className: "rs-alert-text", children: error })
1202
+ ] })
1203
+ ] }),
1204
+ /* @__PURE__ */ jsx4("div", { className: "rs-step-footer", children: /* @__PURE__ */ jsx4(
1205
+ Button,
1206
+ {
1207
+ onClick: handleConfirm,
1208
+ loading: isSubmitting,
1209
+ disabled: chainMismatch || !amount || Number(amount) <= 0,
1210
+ fullWidth: true,
1211
+ children: "Confirm Order"
1212
+ }
1213
+ ) }),
1214
+ /* @__PURE__ */ jsx4(PoweredBy, {})
1215
+ ] });
1216
+ }
1217
+
1218
+ // src/components/steps/DepositAddressStep.tsx
1219
+ import { useState as useState6, useEffect as useEffect5, useCallback as useCallback2, useRef as useRef3, useMemo as useMemo5 } from "react";
1220
+
1221
+ // src/components/ui/QRCode.tsx
1222
+ import { useEffect as useEffect4, useMemo as useMemo4, useState as useState5 } from "react";
1223
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1224
+ function QRCode({ value, size = 200, iconSrc, className }) {
1225
+ const [createQrCode, setCreateQrCode] = useState5(null);
1226
+ useEffect4(() => {
1227
+ let mounted = true;
1228
+ void import("qrcode-generator").then((mod) => {
1229
+ if (mounted) {
1230
+ setCreateQrCode(() => mod.default);
1231
+ }
1232
+ }).catch(() => {
1233
+ if (mounted) {
1234
+ setCreateQrCode(null);
1235
+ }
1236
+ });
1237
+ return () => {
1238
+ mounted = false;
1239
+ };
1240
+ }, []);
1241
+ const svgContent = useMemo4(() => {
1242
+ if (!createQrCode) {
1243
+ return null;
1244
+ }
1245
+ const qr = createQrCode(0, "M");
1246
+ qr.addData(value);
1247
+ qr.make();
1248
+ const moduleCount = qr.getModuleCount();
1249
+ const cellSize = size / moduleCount;
1250
+ const paths = [];
1251
+ const iconCenterSize = iconSrc ? moduleCount * 0.22 : 0;
1252
+ const iconStart = (moduleCount - iconCenterSize) / 2;
1253
+ const iconEnd = (moduleCount + iconCenterSize) / 2;
1254
+ for (let row = 0; row < moduleCount; row++) {
1255
+ for (let col = 0; col < moduleCount; col++) {
1256
+ if (!qr.isDark(row, col)) continue;
1257
+ if (iconSrc && row >= iconStart && row < iconEnd && col >= iconStart && col < iconEnd) {
1258
+ continue;
1259
+ }
1260
+ const x = col * cellSize;
1261
+ const y = row * cellSize;
1262
+ paths.push(`M${x},${y}h${cellSize}v${cellSize}h${-cellSize}z`);
1263
+ }
1264
+ }
1265
+ return { paths: paths.join(""), moduleCount, cellSize };
1266
+ }, [createQrCode, value, size, iconSrc]);
1267
+ const iconSize = size * 0.22;
1268
+ const iconOffset = (size - iconSize) / 2;
1269
+ return /* @__PURE__ */ jsxs5(
1270
+ "svg",
1271
+ {
1272
+ viewBox: `0 0 ${size} ${size}`,
1273
+ width: size,
1274
+ height: size,
1275
+ className,
1276
+ role: "img",
1277
+ "aria-label": "QR Code",
1278
+ children: [
1279
+ /* @__PURE__ */ jsx5("rect", { width: size, height: size, fill: "white", rx: 4 }),
1280
+ svgContent ? /* @__PURE__ */ jsx5("path", { d: svgContent.paths, fill: "black" }) : /* @__PURE__ */ jsx5("rect", { x: 8, y: 8, width: size - 16, height: size - 16, fill: "#f1f5f9" }),
1281
+ iconSrc && /* @__PURE__ */ jsxs5(Fragment2, { children: [
1282
+ /* @__PURE__ */ jsx5(
1283
+ "rect",
1284
+ {
1285
+ x: iconOffset - 4,
1286
+ y: iconOffset - 4,
1287
+ width: iconSize + 8,
1288
+ height: iconSize + 8,
1289
+ fill: "white",
1290
+ rx: 8
1291
+ }
1292
+ ),
1293
+ /* @__PURE__ */ jsx5(
1294
+ "image",
1295
+ {
1296
+ href: iconSrc,
1297
+ x: iconOffset,
1298
+ y: iconOffset,
1299
+ width: iconSize,
1300
+ height: iconSize
1301
+ }
1302
+ )
1303
+ ] })
1304
+ ]
1305
+ }
1306
+ );
1307
+ }
1308
+ QRCode.displayName = "QRCode";
1309
+
1310
+ // src/components/steps/DepositAddressStep.tsx
1311
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1312
+ var POLL_INTERVAL_MS = 4e3;
1313
+ function isRecord(value) {
1314
+ return typeof value === "object" && value !== null;
1315
+ }
1316
+ function asNumber(value) {
1317
+ if (typeof value === "number" && Number.isFinite(value)) return value;
1318
+ if (typeof value === "string" && value.trim() !== "") {
1319
+ const parsed = Number(value);
1320
+ return Number.isFinite(parsed) ? parsed : void 0;
1321
+ }
1322
+ return void 0;
1323
+ }
1324
+ function asAmount(value) {
1325
+ if (typeof value === "string") return value;
1326
+ if (typeof value === "number" && Number.isFinite(value)) {
1327
+ return value.toString();
1328
+ }
1329
+ return void 0;
1330
+ }
1331
+ function asAddress(value) {
1332
+ if (typeof value !== "string") return void 0;
1333
+ return /^0x[a-fA-F0-9]{40}$/.test(value) ? value : void 0;
1334
+ }
1335
+ function getDepositEventDetails(event) {
1336
+ if (!event?.type || !isRecord(event.data)) return {};
1337
+ if (event.type === "deposit-received") {
1338
+ return {
1339
+ chainId: asNumber(event.data.chain),
1340
+ amount: asAmount(event.data.amount),
1341
+ token: asAddress(event.data.token)
1342
+ };
1343
+ }
1344
+ if (event.type === "bridge-started") {
1345
+ const source = isRecord(event.data.source) ? event.data.source : void 0;
1346
+ return {
1347
+ chainId: asNumber(source?.chain),
1348
+ token: asAddress(source?.asset)
1349
+ };
1350
+ }
1351
+ return {};
1352
+ }
1353
+ function DepositAddressStep({
1354
+ smartAccount,
1355
+ service,
1356
+ onDepositDetected,
1357
+ onError
1358
+ }) {
1359
+ const supportedChainIds = useMemo5(() => getSupportedChainIds(), []);
1360
+ const BASE_CHAIN_ID = 8453;
1361
+ const defaultChainId = supportedChainIds.includes(BASE_CHAIN_ID) ? BASE_CHAIN_ID : supportedChainIds[0];
1362
+ const [sourceChainId, setSourceChainId] = useState6(defaultChainId);
1363
+ const tokensForChain = useMemo5(
1364
+ () => getSupportedTokenSymbolsForChain(sourceChainId),
1365
+ [sourceChainId]
1366
+ );
1367
+ const defaultToken = tokensForChain.includes("USDC") ? "USDC" : tokensForChain[0] ?? "USDC";
1368
+ const [sourceTokenSymbol, setSourceTokenSymbol] = useState6(defaultToken);
1369
+ useEffect5(() => {
1370
+ if (!tokensForChain.includes(sourceTokenSymbol)) {
1371
+ setSourceTokenSymbol(tokensForChain[0] ?? "USDC");
1372
+ }
1373
+ }, [tokensForChain, sourceTokenSymbol]);
1374
+ const [copied, setCopied] = useState6(false);
1375
+ const [pollingError, setPollingError] = useState6(null);
1376
+ const [chainDropdownOpen, setChainDropdownOpen] = useState6(false);
1377
+ const [tokenDropdownOpen, setTokenDropdownOpen] = useState6(false);
1378
+ const depositHandledRef = useRef3(false);
1379
+ const sourceSelectionRef = useRef3({
1380
+ chainId: defaultChainId,
1381
+ tokenSymbol: defaultToken
1382
+ });
1383
+ useEffect5(() => {
1384
+ sourceSelectionRef.current = {
1385
+ chainId: sourceChainId,
1386
+ tokenSymbol: sourceTokenSymbol
1387
+ };
1388
+ }, [sourceChainId, sourceTokenSymbol]);
1389
+ const handleCopy = useCallback2(async () => {
1390
+ try {
1391
+ await navigator.clipboard.writeText(smartAccount);
1392
+ setCopied(true);
1393
+ setTimeout(() => setCopied(false), 2e3);
1394
+ } catch {
1395
+ const textarea = document.createElement("textarea");
1396
+ textarea.value = smartAccount;
1397
+ textarea.style.position = "fixed";
1398
+ textarea.style.opacity = "0";
1399
+ document.body.appendChild(textarea);
1400
+ textarea.select();
1401
+ document.execCommand("copy");
1402
+ document.body.removeChild(textarea);
1403
+ setCopied(true);
1404
+ setTimeout(() => setCopied(false), 2e3);
1405
+ }
1406
+ }, [smartAccount]);
1407
+ useEffect5(() => {
1408
+ depositHandledRef.current = false;
1409
+ setPollingError(null);
1410
+ let timeoutId;
1411
+ let cancelled = false;
1412
+ let baselineTxHash = void 0;
1413
+ async function poll() {
1414
+ if (cancelled || depositHandledRef.current) return;
1415
+ try {
1416
+ const status = await service.fetchLatestStatus(smartAccount);
1417
+ if (cancelled || depositHandledRef.current) return;
1418
+ const event = status.lastEvent;
1419
+ const eventTxHash = isDepositEvent(event) ? getEventTxHash(event)?.toLowerCase() ?? null : null;
1420
+ if (baselineTxHash === void 0) {
1421
+ baselineTxHash = eventTxHash;
1422
+ } else if (eventTxHash && eventTxHash !== baselineTxHash) {
1423
+ const details = getDepositEventDetails(event);
1424
+ const fallback = sourceSelectionRef.current;
1425
+ const chainId = details.chainId ?? fallback.chainId;
1426
+ const amount = details.amount ?? "0";
1427
+ const token = details.token ?? getTokenAddress(fallback.tokenSymbol, fallback.chainId);
1428
+ if (token) {
1429
+ depositHandledRef.current = true;
1430
+ onDepositDetected(eventTxHash, chainId, amount, token);
1431
+ return;
1432
+ }
1433
+ }
1434
+ setPollingError(null);
1435
+ } catch (err) {
1436
+ if (!cancelled) {
1437
+ const msg = err instanceof Error ? err.message : "Failed to check status";
1438
+ setPollingError(msg);
1439
+ onError?.(msg, "STATUS_POLL_ERROR");
1440
+ }
1441
+ }
1442
+ if (!cancelled && !depositHandledRef.current) {
1443
+ timeoutId = setTimeout(poll, POLL_INTERVAL_MS);
1444
+ }
1445
+ }
1446
+ poll();
1447
+ return () => {
1448
+ cancelled = true;
1449
+ clearTimeout(timeoutId);
1450
+ };
1451
+ }, [smartAccount, service, onDepositDetected, onError]);
1452
+ const chainIconSrc = getChainIcon(sourceChainId);
1453
+ return /* @__PURE__ */ jsxs6("div", { className: "rs-step", children: [
1454
+ /* @__PURE__ */ jsx6("div", { className: "rs-step-body", children: /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address", children: [
1455
+ /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-selectors", children: [
1456
+ /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-dropdown", children: [
1457
+ /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-label", children: "Supported token" }),
1458
+ /* @__PURE__ */ jsxs6(
1459
+ "button",
1460
+ {
1461
+ type: "button",
1462
+ className: "rs-deposit-address-dropdown-trigger",
1463
+ onClick: () => {
1464
+ setTokenDropdownOpen(!tokenDropdownOpen);
1465
+ setChainDropdownOpen(false);
1466
+ },
1467
+ children: [
1468
+ getTokenIcon(sourceTokenSymbol) && /* @__PURE__ */ jsx6(
1469
+ "img",
1470
+ {
1471
+ src: getTokenIcon(sourceTokenSymbol),
1472
+ alt: "",
1473
+ className: "rs-deposit-address-dropdown-icon"
1474
+ }
1475
+ ),
1476
+ /* @__PURE__ */ jsx6("span", { children: sourceTokenSymbol }),
1477
+ /* @__PURE__ */ jsx6(
1478
+ "svg",
1479
+ {
1480
+ className: "rs-deposit-address-dropdown-chevron",
1481
+ viewBox: "0 0 24 24",
1482
+ fill: "none",
1483
+ stroke: "currentColor",
1484
+ strokeWidth: "2",
1485
+ children: /* @__PURE__ */ jsx6(
1486
+ "path",
1487
+ {
1488
+ strokeLinecap: "round",
1489
+ strokeLinejoin: "round",
1490
+ d: "M19.5 8.25l-7.5 7.5-7.5-7.5"
1491
+ }
1492
+ )
1493
+ }
1494
+ )
1495
+ ]
1496
+ }
1497
+ ),
1498
+ tokenDropdownOpen && /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-menu", children: tokensForChain.map((symbol) => /* @__PURE__ */ jsxs6(
1499
+ "button",
1500
+ {
1501
+ type: "button",
1502
+ className: `rs-deposit-address-dropdown-item ${symbol === sourceTokenSymbol ? "rs-deposit-address-dropdown-item--active" : ""}`,
1503
+ onClick: () => {
1504
+ setSourceTokenSymbol(symbol);
1505
+ setTokenDropdownOpen(false);
1506
+ },
1507
+ children: [
1508
+ getTokenIcon(symbol) && /* @__PURE__ */ jsx6(
1509
+ "img",
1510
+ {
1511
+ src: getTokenIcon(symbol),
1512
+ alt: "",
1513
+ className: "rs-deposit-address-dropdown-icon"
1514
+ }
1515
+ ),
1516
+ /* @__PURE__ */ jsx6("span", { children: symbol })
1517
+ ]
1518
+ },
1519
+ symbol
1520
+ )) })
1521
+ ] }),
1522
+ /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-dropdown", children: [
1523
+ /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-label", children: "Supported chain" }),
1524
+ /* @__PURE__ */ jsxs6(
1525
+ "button",
1526
+ {
1527
+ type: "button",
1528
+ className: "rs-deposit-address-dropdown-trigger",
1529
+ onClick: () => {
1530
+ setChainDropdownOpen(!chainDropdownOpen);
1531
+ setTokenDropdownOpen(false);
1532
+ },
1533
+ children: [
1534
+ getChainIcon(sourceChainId) && /* @__PURE__ */ jsx6(
1535
+ "img",
1536
+ {
1537
+ src: getChainIcon(sourceChainId),
1538
+ alt: "",
1539
+ className: "rs-deposit-address-dropdown-icon"
1540
+ }
1541
+ ),
1542
+ /* @__PURE__ */ jsx6("span", { children: getChainName(sourceChainId) }),
1543
+ /* @__PURE__ */ jsx6(
1544
+ "svg",
1545
+ {
1546
+ className: "rs-deposit-address-dropdown-chevron",
1547
+ viewBox: "0 0 24 24",
1548
+ fill: "none",
1549
+ stroke: "currentColor",
1550
+ strokeWidth: "2",
1551
+ children: /* @__PURE__ */ jsx6(
1552
+ "path",
1553
+ {
1554
+ strokeLinecap: "round",
1555
+ strokeLinejoin: "round",
1556
+ d: "M19.5 8.25l-7.5 7.5-7.5-7.5"
1557
+ }
1558
+ )
1559
+ }
1560
+ )
1561
+ ]
1562
+ }
1563
+ ),
1564
+ chainDropdownOpen && /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-dropdown-menu", children: supportedChainIds.map((chainId) => /* @__PURE__ */ jsxs6(
1565
+ "button",
1566
+ {
1567
+ type: "button",
1568
+ className: `rs-deposit-address-dropdown-item ${chainId === sourceChainId ? "rs-deposit-address-dropdown-item--active" : ""}`,
1569
+ onClick: () => {
1570
+ setSourceChainId(chainId);
1571
+ setChainDropdownOpen(false);
1572
+ },
1573
+ children: [
1574
+ getChainIcon(chainId) && /* @__PURE__ */ jsx6(
1575
+ "img",
1576
+ {
1577
+ src: getChainIcon(chainId),
1578
+ alt: "",
1579
+ className: "rs-deposit-address-dropdown-icon"
1580
+ }
1581
+ ),
1582
+ /* @__PURE__ */ jsx6("span", { children: getChainName(chainId) })
1583
+ ]
1584
+ },
1585
+ chainId
1586
+ )) })
1587
+ ] })
1588
+ ] }),
1589
+ /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-qr", children: /* @__PURE__ */ jsx6(QRCode, { value: smartAccount, size: 200, iconSrc: chainIconSrc }) }),
1590
+ /* @__PURE__ */ jsxs6("div", { className: "rs-deposit-address-info", children: [
1591
+ /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-label", children: "Your deposit address" }),
1592
+ /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-value", children: smartAccount }),
1593
+ /* @__PURE__ */ jsxs6(
1594
+ "button",
1595
+ {
1596
+ type: "button",
1597
+ className: "rs-deposit-address-copy",
1598
+ onClick: handleCopy,
1599
+ children: [
1600
+ /* @__PURE__ */ jsx6(
1601
+ "svg",
1602
+ {
1603
+ viewBox: "0 0 24 24",
1604
+ fill: "none",
1605
+ stroke: "currentColor",
1606
+ strokeWidth: "2",
1607
+ style: { width: 14, height: 14 },
1608
+ children: copied ? /* @__PURE__ */ jsx6(
1609
+ "path",
1610
+ {
1611
+ strokeLinecap: "round",
1612
+ strokeLinejoin: "round",
1613
+ d: "M5 12l5 5L20 7"
1614
+ }
1615
+ ) : /* @__PURE__ */ jsx6(
1616
+ "path",
1617
+ {
1618
+ strokeLinecap: "round",
1619
+ strokeLinejoin: "round",
1620
+ d: "M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9.75a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184"
1621
+ }
1622
+ )
1623
+ }
1624
+ ),
1625
+ copied ? "Copied!" : "Copy address"
1626
+ ]
1627
+ }
1628
+ )
1629
+ ] }),
1630
+ pollingError && /* @__PURE__ */ jsx6("div", { className: "rs-deposit-address-error", children: pollingError })
1631
+ ] }) }),
1632
+ /* @__PURE__ */ jsx6(PoweredBy, {})
1633
+ ] });
1634
+ }
1635
+ DepositAddressStep.displayName = "DepositAddressStep";
1636
+
1637
+ // src/DepositFlow.tsx
1638
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1639
+ function isSameRoute(sourceChain, sourceToken, targetChain, targetToken) {
1640
+ return sourceChain === targetChain && sourceToken.toLowerCase() === targetToken.toLowerCase();
1641
+ }
1642
+ function DepositFlow({
1643
+ dappWalletClient,
1644
+ dappPublicClient,
1645
+ dappAddress,
1646
+ targetChain,
1647
+ targetToken,
1648
+ service,
1649
+ sourceChain: defaultSourceChain,
1650
+ sourceToken: defaultSourceToken,
1651
+ amount: defaultAmount,
1652
+ recipient,
1653
+ rhinestoneApiKey,
1654
+ signerAddress = DEFAULT_SIGNER_ADDRESS,
1655
+ sessionChainIds,
1656
+ forceRegister = false,
1657
+ waitForFinalTx = true,
1658
+ reownWallet,
1659
+ onConnect,
1660
+ onRequestConnect,
1661
+ connectButtonLabel,
1662
+ uiConfig,
1663
+ onStepChange,
1664
+ onTotalBalanceChange,
1665
+ onClose,
1666
+ onConnected,
1667
+ onDepositSubmitted,
1668
+ onDepositComplete,
1669
+ onDepositFailed,
1670
+ onError,
1671
+ debug
1672
+ }) {
1673
+ const [step, setStep] = useState7({ type: "setup" });
1674
+ const [flowMode, setFlowMode] = useState7(null);
1675
+ const [totalBalanceUsd, setTotalBalanceUsd] = useState7(0);
1676
+ const [isConnectSelectionConfirmed, setIsConnectSelectionConfirmed] = useState7(false);
1677
+ const [selectedConnectAddress, setSelectedConnectAddress] = useState7(null);
1678
+ const targetChainObj = useMemo6(() => CHAIN_BY_ID[targetChain], [targetChain]);
1679
+ const dappSwitchChain = useMemo6(() => {
1680
+ if (!dappWalletClient?.switchChain) return void 0;
1681
+ return async (chainId) => {
1682
+ await dappWalletClient.switchChain?.({ id: chainId });
1683
+ };
1684
+ }, [dappWalletClient]);
1685
+ const walletOptions = useMemo6(() => {
1686
+ const options = [];
1687
+ const seen = /* @__PURE__ */ new Set();
1688
+ if (dappWalletClient?.account && dappAddress) {
1689
+ options.push({
1690
+ address: dappWalletClient.account.address,
1691
+ label: "Connected Wallet",
1692
+ kind: "connected"
1693
+ });
1694
+ seen.add(dappWalletClient.account.address.toLowerCase());
1695
+ }
1696
+ if (reownWallet?.address && reownWallet.isConnected && !seen.has(reownWallet.address.toLowerCase())) {
1697
+ options.push({
1698
+ address: reownWallet.address,
1699
+ label: "External Wallet",
1700
+ kind: "external"
1701
+ });
1702
+ }
1703
+ return options;
1704
+ }, [
1705
+ dappWalletClient,
1706
+ dappAddress,
1707
+ reownWallet?.address,
1708
+ reownWallet?.isConnected
1709
+ ]);
1710
+ const canAutoLock = dappWalletClient?.account && dappAddress && !reownWallet;
1711
+ const hasWalletOptions = walletOptions.length > 0;
1712
+ const showConnectStep = !canAutoLock && !isConnectSelectionConfirmed;
1713
+ const signerContext = useMemo6(() => {
1714
+ if (flowMode === "deposit-address") {
1715
+ if (!dappAddress) return null;
1716
+ return {
1717
+ ownerAddress: dappAddress,
1718
+ walletClient: void 0,
1719
+ publicClient: dappPublicClient ?? getPublicClient(targetChain),
1720
+ switchChain: void 0
1721
+ };
1722
+ }
1723
+ if (canAutoLock) {
1724
+ const fallbackChainId = dappWalletClient?.chain?.id ?? targetChain;
1725
+ return {
1726
+ ownerAddress: dappWalletClient.account.address,
1727
+ walletClient: dappWalletClient,
1728
+ publicClient: dappPublicClient ?? getPublicClient(fallbackChainId),
1729
+ switchChain: dappSwitchChain
1730
+ };
1731
+ }
1732
+ if (!isConnectSelectionConfirmed || !selectedConnectAddress) return null;
1733
+ if (dappWalletClient?.account && dappWalletClient.account.address.toLowerCase() === selectedConnectAddress.toLowerCase()) {
1734
+ const fallbackChainId = dappWalletClient?.chain?.id ?? targetChain;
1735
+ return {
1736
+ ownerAddress: dappWalletClient.account.address,
1737
+ walletClient: dappWalletClient,
1738
+ publicClient: dappPublicClient ?? getPublicClient(fallbackChainId),
1739
+ switchChain: dappSwitchChain
1740
+ };
1741
+ }
1742
+ if (reownWallet?.address?.toLowerCase() === selectedConnectAddress.toLowerCase() && reownWallet.walletClient && reownWallet.publicClient) {
1743
+ return {
1744
+ ownerAddress: reownWallet.address,
1745
+ walletClient: reownWallet.walletClient,
1746
+ publicClient: reownWallet.publicClient,
1747
+ switchChain: reownWallet.switchChain
1748
+ };
1749
+ }
1750
+ return null;
1751
+ }, [
1752
+ flowMode,
1753
+ canAutoLock,
1754
+ isConnectSelectionConfirmed,
1755
+ selectedConnectAddress,
1756
+ dappWalletClient,
1757
+ dappPublicClient,
1758
+ dappSwitchChain,
1759
+ dappAddress,
1760
+ reownWallet,
1761
+ targetChain
1762
+ ]);
1763
+ const sessionKeyAddress = dappAddress ?? signerContext?.ownerAddress ?? null;
1764
+ const lastTargetRef = useRef4(null);
1765
+ useEffect6(() => {
1766
+ const prev = lastTargetRef.current;
1767
+ if (prev && (prev.chain !== targetChain || prev.token.toLowerCase() !== targetToken.toLowerCase())) {
1768
+ if (step.type !== "processing") {
1769
+ setStep({ type: "setup" });
1770
+ }
1771
+ }
1772
+ lastTargetRef.current = { chain: targetChain, token: targetToken };
1773
+ }, [targetChain, targetToken, step.type]);
1774
+ const handleBackFromAmount = useCallback3(() => {
1775
+ setStep((prev) => {
1776
+ if (prev.type !== "amount") return prev;
1777
+ return { type: "select-asset", smartAccount: prev.smartAccount };
1778
+ });
1779
+ }, []);
1780
+ const handleBackFromSelectAsset = useCallback3(() => {
1781
+ if (hasWalletOptions || reownWallet) {
1782
+ setIsConnectSelectionConfirmed(false);
1783
+ }
1784
+ }, [hasWalletOptions, reownWallet]);
1785
+ const handleBackFromDepositAddress = useCallback3(() => {
1786
+ setFlowMode(null);
1787
+ setStep({ type: "setup" });
1788
+ if (hasWalletOptions || reownWallet) {
1789
+ setIsConnectSelectionConfirmed(false);
1790
+ }
1791
+ }, [hasWalletOptions, reownWallet]);
1792
+ const handleBackFromConfirm = useCallback3(() => {
1793
+ setStep((prev) => {
1794
+ if (prev.type !== "confirm") return prev;
1795
+ return {
1796
+ type: "amount",
1797
+ smartAccount: prev.smartAccount,
1798
+ asset: prev.asset,
1799
+ amount: prev.amount
1800
+ };
1801
+ });
1802
+ }, []);
1803
+ const stepIndex = step.type === "setup" ? 0 : step.type === "deposit-address" ? 1 : step.type === "select-asset" ? 1 : step.type === "amount" ? 2 : step.type === "confirm" ? 3 : 4;
1804
+ const currentBackHandler = step.type === "deposit-address" ? handleBackFromDepositAddress : step.type === "select-asset" && signerContext && !canAutoLock ? handleBackFromSelectAsset : step.type === "amount" ? handleBackFromAmount : step.type === "confirm" ? handleBackFromConfirm : void 0;
1805
+ useEffect6(() => {
1806
+ onStepChange?.(stepIndex, currentBackHandler);
1807
+ }, [stepIndex, currentBackHandler, onStepChange]);
1808
+ useEffect6(() => {
1809
+ onTotalBalanceChange?.(totalBalanceUsd);
1810
+ }, [totalBalanceUsd, onTotalBalanceChange]);
1811
+ const isDepositAddressMode = flowMode === "deposit-address";
1812
+ const handleSelectProvider = useCallback3(() => {
1813
+ setFlowMode("wallet");
1814
+ }, []);
1815
+ const handleSelectTransferCrypto = useCallback3(() => {
1816
+ setFlowMode("deposit-address");
1817
+ setStep({ type: "setup" });
1818
+ }, []);
1819
+ const handleNewDeposit = useCallback3(() => {
1820
+ setFlowMode(null);
1821
+ setStep({ type: "setup" });
1822
+ }, []);
1823
+ const handleSetupComplete = useCallback3(
1824
+ (smartAccount) => {
1825
+ if (isDepositAddressMode) {
1826
+ setStep({ type: "deposit-address", smartAccount });
1827
+ } else {
1828
+ setStep({ type: "select-asset", smartAccount });
1829
+ }
1830
+ },
1831
+ [isDepositAddressMode]
1832
+ );
1833
+ const handleDepositAddressDetected = useCallback3(
1834
+ (txHash, chainId, amount, token) => {
1835
+ setStep((prev) => {
1836
+ if (prev.type !== "deposit-address") return prev;
1837
+ return {
1838
+ type: "processing",
1839
+ smartAccount: prev.smartAccount,
1840
+ txHash,
1841
+ sourceChain: chainId,
1842
+ sourceToken: token,
1843
+ amount,
1844
+ directTransfer: isSameRoute(chainId, token, targetChain, targetToken)
1845
+ };
1846
+ });
1847
+ onDepositSubmitted?.({ txHash, sourceChain: chainId, amount });
1848
+ },
1849
+ [onDepositSubmitted, targetChain, targetToken]
1850
+ );
1851
+ const handleConnected = useCallback3(
1852
+ (addr, smartAccount) => {
1853
+ onConnected?.({ address: addr, smartAccount });
1854
+ },
1855
+ [onConnected]
1856
+ );
1857
+ const handleAssetContinue = useCallback3(
1858
+ (asset) => {
1859
+ setStep((prev) => {
1860
+ if (prev.type !== "select-asset") return prev;
1861
+ return {
1862
+ type: "amount",
1863
+ smartAccount: prev.smartAccount,
1864
+ asset,
1865
+ amount: defaultAmount
1866
+ };
1867
+ });
1868
+ },
1869
+ [defaultAmount]
1870
+ );
1871
+ const handleAmountContinue = useCallback3(
1872
+ (amount, balance) => {
1873
+ setStep((prev) => {
1874
+ if (prev.type !== "amount") return prev;
1875
+ return {
1876
+ type: "confirm",
1877
+ smartAccount: prev.smartAccount,
1878
+ asset: prev.asset,
1879
+ amount,
1880
+ balance
1881
+ };
1882
+ });
1883
+ },
1884
+ []
1885
+ );
1886
+ const handleDepositSubmitted = useCallback3(
1887
+ (txHash, chainId, amount, token) => {
1888
+ setStep((prev) => {
1889
+ if (prev.type !== "confirm") return prev;
1890
+ return {
1891
+ type: "processing",
1892
+ smartAccount: prev.smartAccount,
1893
+ txHash,
1894
+ sourceChain: chainId,
1895
+ sourceToken: token,
1896
+ amount,
1897
+ directTransfer: isSameRoute(chainId, token, targetChain, targetToken)
1898
+ };
1899
+ });
1900
+ },
1901
+ [targetChain, targetToken]
1902
+ );
1903
+ const handleDepositSubmittedCallback = useCallback3(
1904
+ (txHash, sourceChain, amount) => {
1905
+ onDepositSubmitted?.({ txHash, sourceChain, amount });
1906
+ },
1907
+ [onDepositSubmitted]
1908
+ );
1909
+ const handleDepositComplete = useCallback3(
1910
+ (txHash, destinationTxHash) => {
1911
+ onDepositComplete?.({ txHash, destinationTxHash });
1912
+ },
1913
+ [onDepositComplete]
1914
+ );
1915
+ const handleDepositFailed = useCallback3(
1916
+ (txHash, error) => {
1917
+ onDepositFailed?.({ txHash, error });
1918
+ },
1919
+ [onDepositFailed]
1920
+ );
1921
+ const handleError = useCallback3(
1922
+ (message, code) => {
1923
+ onError?.({ message, code });
1924
+ },
1925
+ [onError]
1926
+ );
1927
+ const handleTotalBalanceComputed = useCallback3((total) => {
1928
+ setTotalBalanceUsd(total);
1929
+ }, []);
1930
+ const selectedConnectAddressEffective = useMemo6(() => {
1931
+ if (selectedConnectAddress) return selectedConnectAddress;
1932
+ if (walletOptions.length === 1) {
1933
+ return walletOptions[0].address;
1934
+ }
1935
+ return null;
1936
+ }, [selectedConnectAddress, walletOptions]);
1937
+ const walletOptionsKey = useMemo6(
1938
+ () => walletOptions.map((option) => option.address.toLowerCase()).join(","),
1939
+ [walletOptions]
1940
+ );
1941
+ useEffect6(() => {
1942
+ setIsConnectSelectionConfirmed(false);
1943
+ }, [walletOptionsKey, selectedConnectAddressEffective]);
1944
+ if (showConnectStep) {
1945
+ return /* @__PURE__ */ jsx7("div", { className: "rs-modal-body", children: /* @__PURE__ */ jsx7(
1946
+ ConnectStep,
1947
+ {
1948
+ walletOptions,
1949
+ selectedAddress: selectedConnectAddressEffective,
1950
+ onSelectAddress: setSelectedConnectAddress,
1951
+ onSelectTransferCrypto: dappAddress ? () => {
1952
+ handleSelectTransferCrypto();
1953
+ setIsConnectSelectionConfirmed(true);
1954
+ } : void 0,
1955
+ onRequestConnect,
1956
+ onConnect,
1957
+ onContinue: () => {
1958
+ if (selectedConnectAddressEffective) {
1959
+ setSelectedConnectAddress(selectedConnectAddressEffective);
1960
+ }
1961
+ handleSelectProvider();
1962
+ setIsConnectSelectionConfirmed(true);
1963
+ },
1964
+ connectButtonLabel
1965
+ }
1966
+ ) });
1967
+ }
1968
+ if (isDepositAddressMode) {
1969
+ if (!dappAddress || !sessionKeyAddress) return null;
1970
+ return /* @__PURE__ */ jsxs7("div", { className: "rs-modal-body", children: [
1971
+ step.type === "setup" && targetChainObj && /* @__PURE__ */ jsx7(
1972
+ SetupStep,
1973
+ {
1974
+ address: sessionKeyAddress,
1975
+ targetChain,
1976
+ targetChainObj,
1977
+ targetToken,
1978
+ rhinestoneApiKey,
1979
+ signerAddress,
1980
+ sessionChainIds,
1981
+ recipient,
1982
+ forceRegister,
1983
+ service,
1984
+ onSetupComplete: handleSetupComplete,
1985
+ onConnected: handleConnected,
1986
+ onError: handleError
1987
+ }
1988
+ ),
1989
+ step.type === "deposit-address" && /* @__PURE__ */ jsx7(
1990
+ DepositAddressStep,
1991
+ {
1992
+ smartAccount: step.smartAccount,
1993
+ service,
1994
+ onDepositDetected: handleDepositAddressDetected,
1995
+ onError: handleError
1996
+ }
1997
+ ),
1998
+ step.type === "processing" && /* @__PURE__ */ jsx7(
1999
+ ProcessingStep,
2000
+ {
2001
+ smartAccount: step.smartAccount,
2002
+ txHash: step.txHash,
2003
+ sourceChain: step.sourceChain,
2004
+ sourceToken: step.sourceToken,
2005
+ targetChain,
2006
+ targetToken,
2007
+ amount: step.amount,
2008
+ waitForFinalTx,
2009
+ service,
2010
+ directTransfer: step.directTransfer,
2011
+ onClose,
2012
+ onNewDeposit: handleNewDeposit,
2013
+ onDepositComplete: handleDepositComplete,
2014
+ onDepositFailed: handleDepositFailed,
2015
+ onError: handleError,
2016
+ debug
2017
+ }
2018
+ )
2019
+ ] });
2020
+ }
2021
+ if (!signerContext?.walletClient || !signerContext?.publicClient) {
2022
+ return null;
2023
+ }
2024
+ const ownerAddress = signerContext.ownerAddress;
2025
+ const ownerChainId = signerContext.walletClient?.chain?.id ?? signerContext.publicClient.chain?.id ?? targetChain;
2026
+ const getReadClientForChain = (chainId) => {
2027
+ if (signerContext.publicClient.chain?.id === chainId) {
2028
+ return signerContext.publicClient;
2029
+ }
2030
+ return getPublicClient(chainId);
2031
+ };
2032
+ return /* @__PURE__ */ jsxs7("div", { className: "rs-modal-body", children: [
2033
+ step.type === "setup" && targetChainObj && /* @__PURE__ */ jsx7(
2034
+ SetupStep,
2035
+ {
2036
+ walletClient: signerContext.walletClient,
2037
+ address: ownerAddress,
2038
+ targetChain,
2039
+ targetChainObj,
2040
+ targetToken,
2041
+ rhinestoneApiKey,
2042
+ signerAddress,
2043
+ sessionChainIds,
2044
+ recipient,
2045
+ forceRegister,
2046
+ service,
2047
+ onSetupComplete: handleSetupComplete,
2048
+ onConnected: handleConnected,
2049
+ onError: handleError
2050
+ }
2051
+ ),
2052
+ step.type === "select-asset" && /* @__PURE__ */ jsx7(
2053
+ AssetSelectStep,
2054
+ {
2055
+ address: ownerAddress,
2056
+ publicClient: getReadClientForChain(ownerChainId),
2057
+ defaultSourceChain,
2058
+ defaultSourceToken,
2059
+ service,
2060
+ onContinue: handleAssetContinue,
2061
+ onTotalBalanceComputed: handleTotalBalanceComputed
2062
+ }
2063
+ ),
2064
+ step.type === "amount" && /* @__PURE__ */ jsx7(
2065
+ AmountStep,
2066
+ {
2067
+ walletClient: signerContext.walletClient,
2068
+ publicClient: getReadClientForChain(step.asset.chainId),
2069
+ address: ownerAddress,
2070
+ asset: step.asset,
2071
+ defaultAmount: step.amount ?? defaultAmount,
2072
+ switchChain: signerContext.switchChain,
2073
+ targetChain,
2074
+ targetToken,
2075
+ uiConfig,
2076
+ onContinue: handleAmountContinue
2077
+ }
2078
+ ),
2079
+ step.type === "confirm" && /* @__PURE__ */ jsx7(
2080
+ ConfirmStep,
2081
+ {
2082
+ walletClient: signerContext.walletClient,
2083
+ address: ownerAddress,
2084
+ smartAccount: step.smartAccount,
2085
+ recipient,
2086
+ asset: step.asset,
2087
+ amount: step.amount,
2088
+ balance: step.balance,
2089
+ targetChain,
2090
+ targetToken,
2091
+ switchChain: signerContext.switchChain,
2092
+ onConfirm: handleDepositSubmitted,
2093
+ onDepositSubmitted: handleDepositSubmittedCallback,
2094
+ onError: handleError
2095
+ }
2096
+ ),
2097
+ step.type === "processing" && /* @__PURE__ */ jsx7(
2098
+ ProcessingStep,
2099
+ {
2100
+ smartAccount: step.smartAccount,
2101
+ txHash: step.txHash,
2102
+ sourceChain: step.sourceChain,
2103
+ sourceToken: step.sourceToken,
2104
+ targetChain,
2105
+ targetToken,
2106
+ amount: step.amount,
2107
+ waitForFinalTx,
2108
+ service,
2109
+ directTransfer: step.directTransfer,
2110
+ onClose,
2111
+ onNewDeposit: handleNewDeposit,
2112
+ onDepositComplete: handleDepositComplete,
2113
+ onDepositFailed: handleDepositFailed,
2114
+ onError: handleError
2115
+ }
2116
+ )
2117
+ ] });
2118
+ }
2119
+
2120
+ // src/DepositModal.tsx
2121
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
2122
+ var ReownDepositInner = lazy(
2123
+ () => import("./DepositModalReown-YTWIR7A4.mjs").then((m) => ({ default: m.DepositModalReown }))
2124
+ );
2125
+ function DepositModal(props) {
2126
+ const needsReown = !!props.reownAppId;
2127
+ if (needsReown) {
2128
+ return /* @__PURE__ */ jsx8(Suspense, { fallback: null, children: /* @__PURE__ */ jsx8(ReownDepositInner, { ...props }) });
2129
+ }
2130
+ return /* @__PURE__ */ jsx8(DepositModalInner, { ...props });
2131
+ }
2132
+ DepositModal.displayName = "DepositModal";
2133
+ function DepositModalInner({
2134
+ dappWalletClient,
2135
+ dappPublicClient,
2136
+ dappAddress,
2137
+ targetChain: targetChainProp,
2138
+ targetToken,
2139
+ isOpen,
2140
+ onClose,
2141
+ inline,
2142
+ sourceChain: sourceChainProp,
2143
+ sourceToken,
2144
+ defaultAmount,
2145
+ recipient,
2146
+ backendUrl = DEFAULT_BACKEND_URL,
2147
+ rhinestoneApiKey,
2148
+ signerAddress = DEFAULT_SIGNER_ADDRESS,
2149
+ sessionChainIds,
2150
+ forceRegister = false,
2151
+ waitForFinalTx = true,
2152
+ reownWallet,
2153
+ onConnect,
2154
+ onRequestConnect,
2155
+ connectButtonLabel,
2156
+ theme,
2157
+ branding,
2158
+ uiConfig,
2159
+ className,
2160
+ onReady,
2161
+ onConnected,
2162
+ onDepositSubmitted,
2163
+ onDepositComplete,
2164
+ onDepositFailed,
2165
+ onError,
2166
+ debug
2167
+ }) {
2168
+ const modalRef = useRef5(null);
2169
+ const [currentStepIndex, setCurrentStepIndex] = useState8(0);
2170
+ const [totalBalanceUsd, setTotalBalanceUsd] = useState8(null);
2171
+ const backHandlerRef = useRef5(void 0);
2172
+ const targetChain = getChainId(targetChainProp);
2173
+ const sourceChain = sourceChainProp ? getChainId(sourceChainProp) : void 0;
2174
+ const service = useMemo7(() => createDepositService(backendUrl), [backendUrl]);
2175
+ useEffect7(() => {
2176
+ if (isOpen && modalRef.current) {
2177
+ applyTheme(modalRef.current, theme);
2178
+ }
2179
+ }, [isOpen, theme]);
2180
+ const hasCalledReady = useRef5(false);
2181
+ useEffect7(() => {
2182
+ if (isOpen && !hasCalledReady.current) {
2183
+ hasCalledReady.current = true;
2184
+ onReady?.();
2185
+ }
2186
+ }, [isOpen, onReady]);
2187
+ useEffect7(() => {
2188
+ if (!isOpen) {
2189
+ setCurrentStepIndex(0);
2190
+ }
2191
+ }, [isOpen]);
2192
+ const handleStepChange = useCallback4(
2193
+ (stepIndex, onBack) => {
2194
+ setCurrentStepIndex(stepIndex);
2195
+ backHandlerRef.current = onBack;
2196
+ },
2197
+ []
2198
+ );
2199
+ const handleTotalBalanceChange = useCallback4((balance) => {
2200
+ setTotalBalanceUsd(balance);
2201
+ }, []);
2202
+ const handleBack = useCallback4(() => {
2203
+ backHandlerRef.current?.();
2204
+ }, []);
2205
+ const showLogo = uiConfig?.showLogo ?? false;
2206
+ const showStepper = uiConfig?.showStepper ?? false;
2207
+ const showBackButton = uiConfig?.showBackButton ?? true;
2208
+ const balanceTitle = uiConfig?.balanceTitle;
2209
+ const logoUrl = branding?.logoUrl ?? "https://github.com/rhinestonewtf.png";
2210
+ const title = branding?.title ?? "Deposit";
2211
+ const canGoBack = currentStepIndex > 0 && currentStepIndex < 4 && backHandlerRef.current !== void 0;
2212
+ return /* @__PURE__ */ jsx8(
2213
+ Modal,
2214
+ {
2215
+ isOpen,
2216
+ onClose,
2217
+ className,
2218
+ inline,
2219
+ children: /* @__PURE__ */ jsxs8("div", { ref: modalRef, className: "rs-modal", children: [
2220
+ /* @__PURE__ */ jsxs8("div", { className: "rs-modal-header--redesigned", children: [
2221
+ /* @__PURE__ */ jsx8("div", { className: "rs-modal-header-nav-left", children: showBackButton && canGoBack && /* @__PURE__ */ jsx8(
2222
+ "button",
2223
+ {
2224
+ type: "button",
2225
+ className: "rs-modal-header-back",
2226
+ "aria-label": "Go back",
2227
+ onClick: handleBack,
2228
+ children: /* @__PURE__ */ jsx8(
2229
+ "svg",
2230
+ {
2231
+ viewBox: "0 0 24 24",
2232
+ fill: "none",
2233
+ stroke: "currentColor",
2234
+ strokeWidth: "2",
2235
+ children: /* @__PURE__ */ jsx8(
2236
+ "path",
2237
+ {
2238
+ strokeLinecap: "round",
2239
+ strokeLinejoin: "round",
2240
+ d: "M15.75 19.5L8.25 12l7.5-7.5"
2241
+ }
2242
+ )
2243
+ }
2244
+ )
2245
+ }
2246
+ ) }),
2247
+ /* @__PURE__ */ jsxs8("div", { className: "rs-modal-header-nav-center", children: [
2248
+ /* @__PURE__ */ jsxs8("div", { className: "rs-modal-header-title-row", children: [
2249
+ showLogo && logoUrl && /* @__PURE__ */ jsx8(
2250
+ "img",
2251
+ {
2252
+ src: logoUrl,
2253
+ alt: "",
2254
+ className: "rs-modal-logo",
2255
+ onError: (e) => {
2256
+ e.target.style.display = "none";
2257
+ }
2258
+ }
2259
+ ),
2260
+ /* @__PURE__ */ jsx8("span", { className: "rs-modal-header-title", children: title }),
2261
+ showStepper && /* @__PURE__ */ jsx8("div", { className: "rs-modal-progress", style: { marginLeft: 8 }, children: [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx8(
2262
+ "div",
2263
+ {
2264
+ className: `rs-modal-progress-dot ${i <= currentStepIndex ? "rs-modal-progress-dot--active" : "rs-modal-progress-dot--inactive"}`
2265
+ },
2266
+ i
2267
+ )) })
2268
+ ] }),
2269
+ balanceTitle && totalBalanceUsd !== null && /* @__PURE__ */ jsxs8("div", { className: "rs-modal-header-balance", children: [
2270
+ /* @__PURE__ */ jsxs8("span", { children: [
2271
+ balanceTitle,
2272
+ ":"
2273
+ ] }),
2274
+ /* @__PURE__ */ jsx8("span", { className: "rs-modal-header-balance-value", children: currencyFormatter.format(totalBalanceUsd) })
2275
+ ] })
2276
+ ] }),
2277
+ /* @__PURE__ */ jsx8("div", { className: "rs-modal-header-nav-right", children: /* @__PURE__ */ jsx8(
2278
+ "button",
2279
+ {
2280
+ type: "button",
2281
+ onClick: onClose,
2282
+ className: "rs-modal-close",
2283
+ "aria-label": "Close",
2284
+ children: /* @__PURE__ */ jsx8(
2285
+ "svg",
2286
+ {
2287
+ viewBox: "0 0 24 24",
2288
+ fill: "none",
2289
+ stroke: "currentColor",
2290
+ strokeWidth: "2",
2291
+ children: /* @__PURE__ */ jsx8(
2292
+ "path",
2293
+ {
2294
+ strokeLinecap: "round",
2295
+ strokeLinejoin: "round",
2296
+ d: "M6 18L18 6M6 6l12 12"
2297
+ }
2298
+ )
2299
+ }
2300
+ )
2301
+ }
2302
+ ) })
2303
+ ] }),
2304
+ /* @__PURE__ */ jsx8(
2305
+ DepositFlow,
2306
+ {
2307
+ dappWalletClient,
2308
+ dappPublicClient,
2309
+ dappAddress,
2310
+ targetChain,
2311
+ targetToken,
2312
+ service,
2313
+ sourceChain,
2314
+ sourceToken,
2315
+ amount: defaultAmount,
2316
+ recipient,
2317
+ rhinestoneApiKey,
2318
+ signerAddress,
2319
+ sessionChainIds,
2320
+ forceRegister,
2321
+ waitForFinalTx,
2322
+ reownWallet,
2323
+ onConnect,
2324
+ onRequestConnect,
2325
+ connectButtonLabel,
2326
+ uiConfig,
2327
+ onStepChange: handleStepChange,
2328
+ onTotalBalanceChange: handleTotalBalanceChange,
2329
+ onClose,
2330
+ onConnected,
2331
+ onDepositSubmitted,
2332
+ onDepositComplete,
2333
+ onDepositFailed,
2334
+ onError,
2335
+ debug
2336
+ }
2337
+ )
2338
+ ] })
2339
+ }
2340
+ );
2341
+ }
2342
+
2343
+ export {
2344
+ DepositModal,
2345
+ DepositModalInner
2346
+ };