@rhinestone/deposit-modal 0.1.19 → 0.1.21

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.
package/README.md CHANGED
@@ -124,6 +124,28 @@ import "@rhinestone/deposit-modal/styles.css";
124
124
  />
125
125
  ```
126
126
 
127
+ ### Withdrawal flow
128
+
129
+ Prerequisites:
130
+ - A 1/1 Safe (single owner) with ERC20 token balance on a supported source chain
131
+ - The connected wallet must be the sole owner of the Safe
132
+
133
+ End-to-end steps:
134
+ 1. User connects wallet (must be the Safe owner)
135
+ 2. Modal creates a Rhinestone smart account and signs session authorization
136
+ 3. Modal registers the smart account with the backend (`/register`)
137
+ 4. User enters withdrawal amount
138
+ 5. User signs an EIP-712 `execTransaction` authorizing the ERC20 transfer from the Safe to the smart account
139
+ 6. Modal calls `/process/:address` to trigger the bridge intent
140
+ 7. Modal polls `/status/:address` for webhook events until the bridge completes on the destination chain
141
+
142
+ To test with the demo configurator:
143
+ 1. Switch flow to "Withdraw"
144
+ 2. Enter the Safe address
145
+ 3. Select the source chain/token matching the Safe's holdings
146
+ 4. Select the destination chain/token
147
+ 5. The connected wallet (Privy embedded or Reown) must be the Safe's sole owner
148
+
127
149
  ### Additional Props (beyond shared DepositModal props)
128
150
 
129
151
  | Prop | Type | Required | Description |
@@ -156,7 +178,7 @@ Also supports `onReady`, `onConnected`, and `onError` (same as DepositModal).
156
178
 
157
179
  **Branding**: `logoUrl`, `title`
158
180
 
159
- **UI Config**: `showLogo`, `showStepper`, `showBackButton`, `balanceTitle`, `maxDepositUsd`
181
+ **UI Config**: `showLogo`, `showStepper`, `showBackButton`, `balanceTitle`, `maxDepositUsd`, `minDepositUsd`
160
182
 
161
183
  ## Utility Exports
162
184
 
package/dist/index.cjs CHANGED
@@ -1937,6 +1937,12 @@ function AmountStep({
1937
1937
  );
1938
1938
  return;
1939
1939
  }
1940
+ if (uiConfig?.minDepositUsd && usdValue < uiConfig.minDepositUsd) {
1941
+ setError(
1942
+ `Minimum deposit is ${currencyFormatter.format(uiConfig.minDepositUsd)}`
1943
+ );
1944
+ return;
1945
+ }
1940
1946
  if (tokenPriceUsd === null || tokenPriceUsd === 0) {
1941
1947
  setError("Unable to determine token price");
1942
1948
  return;
@@ -2210,6 +2216,7 @@ function ConfirmStep({
2210
2216
  walletClient,
2211
2217
  address,
2212
2218
  smartAccount,
2219
+ recipient,
2213
2220
  asset,
2214
2221
  amount,
2215
2222
  balance,
@@ -2305,10 +2312,11 @@ function ConfirmStep({
2305
2312
  if (!account || !chain) {
2306
2313
  throw new Error("Wallet not properly connected");
2307
2314
  }
2315
+ const transferTo = sameRoute ? recipient : smartAccount;
2308
2316
  const hash = isNativeAsset(asset) ? await walletClient.sendTransaction({
2309
2317
  account,
2310
2318
  chain,
2311
- to: smartAccount,
2319
+ to: transferTo,
2312
2320
  value: amountUnits
2313
2321
  }) : await walletClient.writeContract({
2314
2322
  account,
@@ -2316,7 +2324,7 @@ function ConfirmStep({
2316
2324
  address: asset.token,
2317
2325
  abi: import_viem5.erc20Abi,
2318
2326
  functionName: "transfer",
2319
- args: [smartAccount, amountUnits]
2327
+ args: [transferTo, amountUnits]
2320
2328
  });
2321
2329
  onDepositSubmitted?.(hash, asset.chainId, amountUnits.toString());
2322
2330
  onConfirm(hash, asset.chainId, amountUnits.toString(), asset.token);
@@ -2525,8 +2533,8 @@ function getEventTxHash(event) {
2525
2533
  return asString(event.data?.transactionHash);
2526
2534
  }
2527
2535
  if (event.type === "bridge-started" || event.type === "bridge-complete") {
2528
- const source = isRecord(event.data?.source) ? event.data.source : void 0;
2529
- return asString(source?.transactionHash);
2536
+ const deposit = isRecord(event.data?.deposit) ? event.data.deposit : void 0;
2537
+ return asString(deposit?.transactionHash);
2530
2538
  }
2531
2539
  if (event.type === "bridge-failed" || event.type === "error") {
2532
2540
  const deposit = isRecord(event.data?.deposit) ? event.data.deposit : void 0;
@@ -2574,19 +2582,29 @@ function ProcessingStep({
2574
2582
  amount,
2575
2583
  waitForFinalTx,
2576
2584
  service,
2585
+ directTransfer,
2577
2586
  flowLabel = "deposit",
2587
+ debug,
2578
2588
  onClose,
2579
2589
  onNewDeposit,
2580
2590
  onDepositComplete,
2581
2591
  onDepositFailed,
2582
2592
  onError
2583
2593
  }) {
2584
- const [state, setState] = (0, import_react6.useState)({ type: "processing" });
2594
+ const [state, setState] = (0, import_react6.useState)(
2595
+ directTransfer ? { type: "complete" } : { type: "processing" }
2596
+ );
2585
2597
  const [elapsedSeconds, setElapsedSeconds] = (0, import_react6.useState)(0);
2586
2598
  const startTimeRef = (0, import_react6.useRef)(Date.now());
2587
2599
  const intervalRef = (0, import_react6.useRef)(null);
2588
- const sameChainAndToken = targetChain === sourceChain && targetToken.toLowerCase() === sourceToken.toLowerCase();
2589
2600
  (0, import_react6.useEffect)(() => {
2601
+ if (directTransfer) {
2602
+ onDepositComplete?.(txHash);
2603
+ return;
2604
+ }
2605
+ }, [directTransfer, txHash, onDepositComplete]);
2606
+ (0, import_react6.useEffect)(() => {
2607
+ if (directTransfer) return;
2590
2608
  startTimeRef.current = Date.now();
2591
2609
  intervalRef.current = setInterval(() => {
2592
2610
  setElapsedSeconds(Math.floor((Date.now() - startTimeRef.current) / 1e3));
@@ -2594,7 +2612,7 @@ function ProcessingStep({
2594
2612
  return () => {
2595
2613
  if (intervalRef.current) clearInterval(intervalRef.current);
2596
2614
  };
2597
- }, []);
2615
+ }, [directTransfer]);
2598
2616
  (0, import_react6.useEffect)(() => {
2599
2617
  if (state.type === "complete" || state.type === "failed" || state.type === "error") {
2600
2618
  if (intervalRef.current) {
@@ -2607,6 +2625,7 @@ function ProcessingStep({
2607
2625
  const pollTimeoutRef = (0, import_react6.useRef)(null);
2608
2626
  const processTimeoutRef = (0, import_react6.useRef)(null);
2609
2627
  (0, import_react6.useEffect)(() => {
2628
+ if (directTransfer) return;
2610
2629
  if (state.type !== "processing") {
2611
2630
  pollIntervalRef.current = INITIAL_POLL_INTERVAL;
2612
2631
  return;
@@ -2618,6 +2637,15 @@ function ProcessingStep({
2618
2637
  const lastEvent2 = data.lastEvent;
2619
2638
  const eventMatchesTx = isEventForTx(lastEvent2, txHash);
2620
2639
  const eventForCurrentTx = eventMatchesTx ? lastEvent2 : void 0;
2640
+ if (debug && lastEvent2) {
2641
+ const eventData = lastEvent2.data;
2642
+ console.log("[deposit-modal] status poll", {
2643
+ type: lastEvent2.type,
2644
+ matchesTx: eventMatchesTx,
2645
+ intentId: eventData?.intentId,
2646
+ data: eventData
2647
+ });
2648
+ }
2621
2649
  if (!isMounted) return;
2622
2650
  if (eventForCurrentTx?.type === "bridge-complete") {
2623
2651
  setState({ type: "complete", lastEvent: eventForCurrentTx });
@@ -2630,11 +2658,6 @@ function ProcessingStep({
2630
2658
  onDepositComplete?.(txHash);
2631
2659
  return;
2632
2660
  }
2633
- if (eventForCurrentTx?.type === "deposit-received" && sameChainAndToken) {
2634
- setState({ type: "complete", lastEvent: eventForCurrentTx });
2635
- onDepositComplete?.(txHash);
2636
- return;
2637
- }
2638
2661
  if (eventForCurrentTx?.type === "bridge-failed") {
2639
2662
  const formatted = formatBridgeFailedMessage(eventForCurrentTx);
2640
2663
  setState({
@@ -2679,16 +2702,17 @@ function ProcessingStep({
2679
2702
  }
2680
2703
  };
2681
2704
  }, [
2705
+ directTransfer,
2682
2706
  state.type,
2683
2707
  smartAccount,
2684
2708
  txHash,
2685
2709
  service,
2686
- sameChainAndToken,
2687
2710
  waitForFinalTx,
2688
2711
  onDepositComplete,
2689
2712
  onDepositFailed
2690
2713
  ]);
2691
2714
  (0, import_react6.useEffect)(() => {
2715
+ if (directTransfer) return;
2692
2716
  if (state.type !== "processing") {
2693
2717
  if (processTimeoutRef.current) {
2694
2718
  clearTimeout(processTimeoutRef.current);
@@ -2707,7 +2731,7 @@ function ProcessingStep({
2707
2731
  processTimeoutRef.current = null;
2708
2732
  }
2709
2733
  };
2710
- }, [state.type, onError]);
2734
+ }, [directTransfer, state.type, onError]);
2711
2735
  const isError = state.type === "error" || state.type === "failed";
2712
2736
  const isComplete = state.type === "complete";
2713
2737
  const isProcessing = state.type === "processing";
@@ -2761,7 +2785,7 @@ function ProcessingStep({
2761
2785
  }
2762
2786
  ) }),
2763
2787
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "rs-success-title", children: isEarlyComplete ? `${flowCapitalized} confirmed` : `${flowCapitalized} successful` }),
2764
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "rs-success-subtitle", children: isEarlyComplete ? "Your transfer has been confirmed and funds will arrive shortly." : `Your funds have been successfully bridged.` })
2788
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "rs-success-subtitle", children: directTransfer ? "Your transfer is complete." : isEarlyComplete ? "Your transfer has been confirmed and funds will arrive shortly." : "Your funds have been successfully bridged." })
2765
2789
  ] }),
2766
2790
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "rs-card", children: [
2767
2791
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "rs-card-row", children: [
@@ -3544,6 +3568,9 @@ var init_public_client = __esm({
3544
3568
  });
3545
3569
 
3546
3570
  // src/DepositFlow.tsx
3571
+ function isSameRoute(sourceChain, sourceToken, targetChain, targetToken) {
3572
+ return sourceChain === targetChain && sourceToken.toLowerCase() === targetToken.toLowerCase();
3573
+ }
3547
3574
  function DepositFlow({
3548
3575
  dappWalletClient,
3549
3576
  dappPublicClient,
@@ -3572,7 +3599,8 @@ function DepositFlow({
3572
3599
  onDepositSubmitted,
3573
3600
  onDepositComplete,
3574
3601
  onDepositFailed,
3575
- onError
3602
+ onError,
3603
+ debug
3576
3604
  }) {
3577
3605
  const [step, setStep] = (0, import_react9.useState)({ type: "setup" });
3578
3606
  const [flowMode, setFlowMode] = (0, import_react9.useState)(null);
@@ -3743,12 +3771,13 @@ function DepositFlow({
3743
3771
  txHash,
3744
3772
  sourceChain: chainId,
3745
3773
  sourceToken: token,
3746
- amount
3774
+ amount,
3775
+ directTransfer: isSameRoute(chainId, token, targetChain, targetToken)
3747
3776
  };
3748
3777
  });
3749
3778
  onDepositSubmitted?.({ txHash, sourceChain: chainId, amount });
3750
3779
  },
3751
- [onDepositSubmitted]
3780
+ [onDepositSubmitted, targetChain, targetToken]
3752
3781
  );
3753
3782
  const handleConnected = (0, import_react9.useCallback)(
3754
3783
  (addr, smartAccount) => {
@@ -3795,11 +3824,12 @@ function DepositFlow({
3795
3824
  txHash,
3796
3825
  sourceChain: chainId,
3797
3826
  sourceToken: token,
3798
- amount
3827
+ amount,
3828
+ directTransfer: isSameRoute(chainId, token, targetChain, targetToken)
3799
3829
  };
3800
3830
  });
3801
3831
  },
3802
- []
3832
+ [targetChain, targetToken]
3803
3833
  );
3804
3834
  const handleDepositSubmittedCallback = (0, import_react9.useCallback)(
3805
3835
  (txHash, sourceChain, amount) => {
@@ -3908,11 +3938,13 @@ function DepositFlow({
3908
3938
  amount: step.amount,
3909
3939
  waitForFinalTx,
3910
3940
  service,
3941
+ directTransfer: step.directTransfer,
3911
3942
  onClose,
3912
3943
  onNewDeposit: handleNewDeposit,
3913
3944
  onDepositComplete: handleDepositComplete,
3914
3945
  onDepositFailed: handleDepositFailed,
3915
- onError: handleError
3946
+ onError: handleError,
3947
+ debug
3916
3948
  }
3917
3949
  )
3918
3950
  ] });
@@ -3981,6 +4013,7 @@ function DepositFlow({
3981
4013
  walletClient: signerContext.walletClient,
3982
4014
  address: ownerAddress,
3983
4015
  smartAccount: step.smartAccount,
4016
+ recipient,
3984
4017
  asset: step.asset,
3985
4018
  amount: step.amount,
3986
4019
  balance: step.balance,
@@ -4004,6 +4037,7 @@ function DepositFlow({
4004
4037
  amount: step.amount,
4005
4038
  waitForFinalTx,
4006
4039
  service,
4040
+ directTransfer: step.directTransfer,
4007
4041
  onClose,
4008
4042
  onNewDeposit: handleNewDeposit,
4009
4043
  onDepositComplete: handleDepositComplete,
@@ -4238,7 +4272,8 @@ function DepositModalInner({
4238
4272
  onDepositSubmitted,
4239
4273
  onDepositComplete,
4240
4274
  onDepositFailed,
4241
- onError
4275
+ onError,
4276
+ debug
4242
4277
  }) {
4243
4278
  const modalRef = (0, import_react13.useRef)(null);
4244
4279
  const [currentStepIndex, setCurrentStepIndex] = (0, import_react13.useState)(0);
@@ -4406,7 +4441,8 @@ function DepositModalInner({
4406
4441
  onDepositSubmitted,
4407
4442
  onDepositComplete,
4408
4443
  onDepositFailed,
4409
- onError
4444
+ onError,
4445
+ debug
4410
4446
  }
4411
4447
  )
4412
4448
  ] })
@@ -5207,7 +5243,8 @@ function WithdrawFlow({
5207
5243
  onWithdrawSubmitted,
5208
5244
  onWithdrawComplete,
5209
5245
  onWithdrawFailed,
5210
- onError
5246
+ onError,
5247
+ debug
5211
5248
  }) {
5212
5249
  const [step, setStep] = (0, import_react15.useState)({ type: "form" });
5213
5250
  const [isSubmitting, setIsSubmitting] = (0, import_react15.useState)(false);
@@ -5596,7 +5633,8 @@ function WithdrawFlow({
5596
5633
  onNewDeposit: () => setStep({ type: "form" }),
5597
5634
  onDepositComplete: handleWithdrawComplete,
5598
5635
  onDepositFailed: handleWithdrawFailed,
5599
- onError: handleError
5636
+ onError: handleError,
5637
+ debug
5600
5638
  }
5601
5639
  )
5602
5640
  ] });
@@ -5697,7 +5735,8 @@ function WithdrawModalInner({
5697
5735
  onWithdrawSubmitted,
5698
5736
  onWithdrawComplete,
5699
5737
  onWithdrawFailed,
5700
- onError
5738
+ onError,
5739
+ debug
5701
5740
  }) {
5702
5741
  const modalRef = (0, import_react17.useRef)(null);
5703
5742
  const [currentStepIndex, setCurrentStepIndex] = (0, import_react17.useState)(0);
@@ -5863,7 +5902,8 @@ function WithdrawModalInner({
5863
5902
  onWithdrawSubmitted,
5864
5903
  onWithdrawComplete,
5865
5904
  onWithdrawFailed,
5866
- onError
5905
+ onError,
5906
+ debug
5867
5907
  }
5868
5908
  )
5869
5909
  ] })
package/dist/index.d.cts CHANGED
@@ -19,6 +19,7 @@ interface DepositModalUIConfig {
19
19
  showBackButton?: boolean;
20
20
  balanceTitle?: string;
21
21
  maxDepositUsd?: number;
22
+ minDepositUsd?: number;
22
23
  }
23
24
  interface DepositModalBranding {
24
25
  logoUrl?: string;
@@ -71,7 +72,7 @@ interface DepositModalProps {
71
72
  sourceChain?: Chain | number;
72
73
  sourceToken?: Address;
73
74
  defaultAmount?: string;
74
- recipient?: Address;
75
+ recipient: Address;
75
76
  backendUrl?: string;
76
77
  rhinestoneApiKey?: string;
77
78
  signerAddress?: Address;
@@ -91,6 +92,7 @@ interface DepositModalProps {
91
92
  onDepositComplete?: (data: DepositCompleteEventData) => void;
92
93
  onDepositFailed?: (data: DepositFailedEventData) => void;
93
94
  onError?: (data: ErrorEventData) => void;
95
+ debug?: boolean;
94
96
  }
95
97
  interface WithdrawSignParams {
96
98
  safeAddress: Address;
@@ -136,6 +138,7 @@ interface WithdrawModalProps {
136
138
  onWithdrawComplete?: (data: WithdrawCompleteEventData) => void;
137
139
  onWithdrawFailed?: (data: WithdrawFailedEventData) => void;
138
140
  onError?: (data: ErrorEventData) => void;
141
+ debug?: boolean;
139
142
  }
140
143
  interface AssetOption {
141
144
  id: string;
package/dist/index.d.ts CHANGED
@@ -19,6 +19,7 @@ interface DepositModalUIConfig {
19
19
  showBackButton?: boolean;
20
20
  balanceTitle?: string;
21
21
  maxDepositUsd?: number;
22
+ minDepositUsd?: number;
22
23
  }
23
24
  interface DepositModalBranding {
24
25
  logoUrl?: string;
@@ -71,7 +72,7 @@ interface DepositModalProps {
71
72
  sourceChain?: Chain | number;
72
73
  sourceToken?: Address;
73
74
  defaultAmount?: string;
74
- recipient?: Address;
75
+ recipient: Address;
75
76
  backendUrl?: string;
76
77
  rhinestoneApiKey?: string;
77
78
  signerAddress?: Address;
@@ -91,6 +92,7 @@ interface DepositModalProps {
91
92
  onDepositComplete?: (data: DepositCompleteEventData) => void;
92
93
  onDepositFailed?: (data: DepositFailedEventData) => void;
93
94
  onError?: (data: ErrorEventData) => void;
95
+ debug?: boolean;
94
96
  }
95
97
  interface WithdrawSignParams {
96
98
  safeAddress: Address;
@@ -136,6 +138,7 @@ interface WithdrawModalProps {
136
138
  onWithdrawComplete?: (data: WithdrawCompleteEventData) => void;
137
139
  onWithdrawFailed?: (data: WithdrawFailedEventData) => void;
138
140
  onError?: (data: ErrorEventData) => void;
141
+ debug?: boolean;
139
142
  }
140
143
  interface AssetOption {
141
144
  id: string;
package/dist/index.mjs CHANGED
@@ -1925,6 +1925,12 @@ function AmountStep({
1925
1925
  );
1926
1926
  return;
1927
1927
  }
1928
+ if (uiConfig?.minDepositUsd && usdValue < uiConfig.minDepositUsd) {
1929
+ setError(
1930
+ `Minimum deposit is ${currencyFormatter.format(uiConfig.minDepositUsd)}`
1931
+ );
1932
+ return;
1933
+ }
1928
1934
  if (tokenPriceUsd === null || tokenPriceUsd === 0) {
1929
1935
  setError("Unable to determine token price");
1930
1936
  return;
@@ -2197,6 +2203,7 @@ function ConfirmStep({
2197
2203
  walletClient,
2198
2204
  address,
2199
2205
  smartAccount,
2206
+ recipient,
2200
2207
  asset,
2201
2208
  amount,
2202
2209
  balance,
@@ -2292,10 +2299,11 @@ function ConfirmStep({
2292
2299
  if (!account || !chain) {
2293
2300
  throw new Error("Wallet not properly connected");
2294
2301
  }
2302
+ const transferTo = sameRoute ? recipient : smartAccount;
2295
2303
  const hash = isNativeAsset(asset) ? await walletClient.sendTransaction({
2296
2304
  account,
2297
2305
  chain,
2298
- to: smartAccount,
2306
+ to: transferTo,
2299
2307
  value: amountUnits
2300
2308
  }) : await walletClient.writeContract({
2301
2309
  account,
@@ -2303,7 +2311,7 @@ function ConfirmStep({
2303
2311
  address: asset.token,
2304
2312
  abi: erc20Abi2,
2305
2313
  functionName: "transfer",
2306
- args: [smartAccount, amountUnits]
2314
+ args: [transferTo, amountUnits]
2307
2315
  });
2308
2316
  onDepositSubmitted?.(hash, asset.chainId, amountUnits.toString());
2309
2317
  onConfirm(hash, asset.chainId, amountUnits.toString(), asset.token);
@@ -2509,8 +2517,8 @@ function getEventTxHash(event) {
2509
2517
  return asString(event.data?.transactionHash);
2510
2518
  }
2511
2519
  if (event.type === "bridge-started" || event.type === "bridge-complete") {
2512
- const source = isRecord(event.data?.source) ? event.data.source : void 0;
2513
- return asString(source?.transactionHash);
2520
+ const deposit = isRecord(event.data?.deposit) ? event.data.deposit : void 0;
2521
+ return asString(deposit?.transactionHash);
2514
2522
  }
2515
2523
  if (event.type === "bridge-failed" || event.type === "error") {
2516
2524
  const deposit = isRecord(event.data?.deposit) ? event.data.deposit : void 0;
@@ -2561,19 +2569,29 @@ function ProcessingStep({
2561
2569
  amount,
2562
2570
  waitForFinalTx,
2563
2571
  service,
2572
+ directTransfer,
2564
2573
  flowLabel = "deposit",
2574
+ debug,
2565
2575
  onClose,
2566
2576
  onNewDeposit,
2567
2577
  onDepositComplete,
2568
2578
  onDepositFailed,
2569
2579
  onError
2570
2580
  }) {
2571
- const [state, setState] = useState5({ type: "processing" });
2581
+ const [state, setState] = useState5(
2582
+ directTransfer ? { type: "complete" } : { type: "processing" }
2583
+ );
2572
2584
  const [elapsedSeconds, setElapsedSeconds] = useState5(0);
2573
2585
  const startTimeRef = useRef4(Date.now());
2574
2586
  const intervalRef = useRef4(null);
2575
- const sameChainAndToken = targetChain === sourceChain && targetToken.toLowerCase() === sourceToken.toLowerCase();
2576
2587
  useEffect5(() => {
2588
+ if (directTransfer) {
2589
+ onDepositComplete?.(txHash);
2590
+ return;
2591
+ }
2592
+ }, [directTransfer, txHash, onDepositComplete]);
2593
+ useEffect5(() => {
2594
+ if (directTransfer) return;
2577
2595
  startTimeRef.current = Date.now();
2578
2596
  intervalRef.current = setInterval(() => {
2579
2597
  setElapsedSeconds(Math.floor((Date.now() - startTimeRef.current) / 1e3));
@@ -2581,7 +2599,7 @@ function ProcessingStep({
2581
2599
  return () => {
2582
2600
  if (intervalRef.current) clearInterval(intervalRef.current);
2583
2601
  };
2584
- }, []);
2602
+ }, [directTransfer]);
2585
2603
  useEffect5(() => {
2586
2604
  if (state.type === "complete" || state.type === "failed" || state.type === "error") {
2587
2605
  if (intervalRef.current) {
@@ -2594,6 +2612,7 @@ function ProcessingStep({
2594
2612
  const pollTimeoutRef = useRef4(null);
2595
2613
  const processTimeoutRef = useRef4(null);
2596
2614
  useEffect5(() => {
2615
+ if (directTransfer) return;
2597
2616
  if (state.type !== "processing") {
2598
2617
  pollIntervalRef.current = INITIAL_POLL_INTERVAL;
2599
2618
  return;
@@ -2605,6 +2624,15 @@ function ProcessingStep({
2605
2624
  const lastEvent2 = data.lastEvent;
2606
2625
  const eventMatchesTx = isEventForTx(lastEvent2, txHash);
2607
2626
  const eventForCurrentTx = eventMatchesTx ? lastEvent2 : void 0;
2627
+ if (debug && lastEvent2) {
2628
+ const eventData = lastEvent2.data;
2629
+ console.log("[deposit-modal] status poll", {
2630
+ type: lastEvent2.type,
2631
+ matchesTx: eventMatchesTx,
2632
+ intentId: eventData?.intentId,
2633
+ data: eventData
2634
+ });
2635
+ }
2608
2636
  if (!isMounted) return;
2609
2637
  if (eventForCurrentTx?.type === "bridge-complete") {
2610
2638
  setState({ type: "complete", lastEvent: eventForCurrentTx });
@@ -2617,11 +2645,6 @@ function ProcessingStep({
2617
2645
  onDepositComplete?.(txHash);
2618
2646
  return;
2619
2647
  }
2620
- if (eventForCurrentTx?.type === "deposit-received" && sameChainAndToken) {
2621
- setState({ type: "complete", lastEvent: eventForCurrentTx });
2622
- onDepositComplete?.(txHash);
2623
- return;
2624
- }
2625
2648
  if (eventForCurrentTx?.type === "bridge-failed") {
2626
2649
  const formatted = formatBridgeFailedMessage(eventForCurrentTx);
2627
2650
  setState({
@@ -2666,16 +2689,17 @@ function ProcessingStep({
2666
2689
  }
2667
2690
  };
2668
2691
  }, [
2692
+ directTransfer,
2669
2693
  state.type,
2670
2694
  smartAccount,
2671
2695
  txHash,
2672
2696
  service,
2673
- sameChainAndToken,
2674
2697
  waitForFinalTx,
2675
2698
  onDepositComplete,
2676
2699
  onDepositFailed
2677
2700
  ]);
2678
2701
  useEffect5(() => {
2702
+ if (directTransfer) return;
2679
2703
  if (state.type !== "processing") {
2680
2704
  if (processTimeoutRef.current) {
2681
2705
  clearTimeout(processTimeoutRef.current);
@@ -2694,7 +2718,7 @@ function ProcessingStep({
2694
2718
  processTimeoutRef.current = null;
2695
2719
  }
2696
2720
  };
2697
- }, [state.type, onError]);
2721
+ }, [directTransfer, state.type, onError]);
2698
2722
  const isError = state.type === "error" || state.type === "failed";
2699
2723
  const isComplete = state.type === "complete";
2700
2724
  const isProcessing = state.type === "processing";
@@ -2748,7 +2772,7 @@ function ProcessingStep({
2748
2772
  }
2749
2773
  ) }),
2750
2774
  /* @__PURE__ */ jsx11("div", { className: "rs-success-title", children: isEarlyComplete ? `${flowCapitalized} confirmed` : `${flowCapitalized} successful` }),
2751
- /* @__PURE__ */ jsx11("div", { className: "rs-success-subtitle", children: isEarlyComplete ? "Your transfer has been confirmed and funds will arrive shortly." : `Your funds have been successfully bridged.` })
2775
+ /* @__PURE__ */ jsx11("div", { className: "rs-success-subtitle", children: directTransfer ? "Your transfer is complete." : isEarlyComplete ? "Your transfer has been confirmed and funds will arrive shortly." : "Your funds have been successfully bridged." })
2752
2776
  ] }),
2753
2777
  /* @__PURE__ */ jsxs10("div", { className: "rs-card", children: [
2754
2778
  /* @__PURE__ */ jsxs10("div", { className: "rs-card-row", children: [
@@ -3529,6 +3553,9 @@ var init_public_client = __esm({
3529
3553
  // src/DepositFlow.tsx
3530
3554
  import { useState as useState7, useCallback as useCallback4, useMemo as useMemo6, useEffect as useEffect7, useRef as useRef6 } from "react";
3531
3555
  import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
3556
+ function isSameRoute(sourceChain, sourceToken, targetChain, targetToken) {
3557
+ return sourceChain === targetChain && sourceToken.toLowerCase() === targetToken.toLowerCase();
3558
+ }
3532
3559
  function DepositFlow({
3533
3560
  dappWalletClient,
3534
3561
  dappPublicClient,
@@ -3557,7 +3584,8 @@ function DepositFlow({
3557
3584
  onDepositSubmitted,
3558
3585
  onDepositComplete,
3559
3586
  onDepositFailed,
3560
- onError
3587
+ onError,
3588
+ debug
3561
3589
  }) {
3562
3590
  const [step, setStep] = useState7({ type: "setup" });
3563
3591
  const [flowMode, setFlowMode] = useState7(null);
@@ -3728,12 +3756,13 @@ function DepositFlow({
3728
3756
  txHash,
3729
3757
  sourceChain: chainId,
3730
3758
  sourceToken: token,
3731
- amount
3759
+ amount,
3760
+ directTransfer: isSameRoute(chainId, token, targetChain, targetToken)
3732
3761
  };
3733
3762
  });
3734
3763
  onDepositSubmitted?.({ txHash, sourceChain: chainId, amount });
3735
3764
  },
3736
- [onDepositSubmitted]
3765
+ [onDepositSubmitted, targetChain, targetToken]
3737
3766
  );
3738
3767
  const handleConnected = useCallback4(
3739
3768
  (addr, smartAccount) => {
@@ -3780,11 +3809,12 @@ function DepositFlow({
3780
3809
  txHash,
3781
3810
  sourceChain: chainId,
3782
3811
  sourceToken: token,
3783
- amount
3812
+ amount,
3813
+ directTransfer: isSameRoute(chainId, token, targetChain, targetToken)
3784
3814
  };
3785
3815
  });
3786
3816
  },
3787
- []
3817
+ [targetChain, targetToken]
3788
3818
  );
3789
3819
  const handleDepositSubmittedCallback = useCallback4(
3790
3820
  (txHash, sourceChain, amount) => {
@@ -3893,11 +3923,13 @@ function DepositFlow({
3893
3923
  amount: step.amount,
3894
3924
  waitForFinalTx,
3895
3925
  service,
3926
+ directTransfer: step.directTransfer,
3896
3927
  onClose,
3897
3928
  onNewDeposit: handleNewDeposit,
3898
3929
  onDepositComplete: handleDepositComplete,
3899
3930
  onDepositFailed: handleDepositFailed,
3900
- onError: handleError
3931
+ onError: handleError,
3932
+ debug
3901
3933
  }
3902
3934
  )
3903
3935
  ] });
@@ -3966,6 +3998,7 @@ function DepositFlow({
3966
3998
  walletClient: signerContext.walletClient,
3967
3999
  address: ownerAddress,
3968
4000
  smartAccount: step.smartAccount,
4001
+ recipient,
3969
4002
  asset: step.asset,
3970
4003
  amount: step.amount,
3971
4004
  balance: step.balance,
@@ -3989,6 +4022,7 @@ function DepositFlow({
3989
4022
  amount: step.amount,
3990
4023
  waitForFinalTx,
3991
4024
  service,
4025
+ directTransfer: step.directTransfer,
3992
4026
  onClose,
3993
4027
  onNewDeposit: handleNewDeposit,
3994
4028
  onDepositComplete: handleDepositComplete,
@@ -4236,7 +4270,8 @@ function DepositModalInner({
4236
4270
  onDepositSubmitted,
4237
4271
  onDepositComplete,
4238
4272
  onDepositFailed,
4239
- onError
4273
+ onError,
4274
+ debug
4240
4275
  }) {
4241
4276
  const modalRef = useRef7(null);
4242
4277
  const [currentStepIndex, setCurrentStepIndex] = useState9(0);
@@ -4404,7 +4439,8 @@ function DepositModalInner({
4404
4439
  onDepositSubmitted,
4405
4440
  onDepositComplete,
4406
4441
  onDepositFailed,
4407
- onError
4442
+ onError,
4443
+ debug
4408
4444
  }
4409
4445
  )
4410
4446
  ] })
@@ -5214,7 +5250,8 @@ function WithdrawFlow({
5214
5250
  onWithdrawSubmitted,
5215
5251
  onWithdrawComplete,
5216
5252
  onWithdrawFailed,
5217
- onError
5253
+ onError,
5254
+ debug
5218
5255
  }) {
5219
5256
  const [step, setStep] = useState11({ type: "form" });
5220
5257
  const [isSubmitting, setIsSubmitting] = useState11(false);
@@ -5603,7 +5640,8 @@ function WithdrawFlow({
5603
5640
  onNewDeposit: () => setStep({ type: "form" }),
5604
5641
  onDepositComplete: handleWithdrawComplete,
5605
5642
  onDepositFailed: handleWithdrawFailed,
5606
- onError: handleError
5643
+ onError: handleError,
5644
+ debug
5607
5645
  }
5608
5646
  )
5609
5647
  ] });
@@ -5708,7 +5746,8 @@ function WithdrawModalInner({
5708
5746
  onWithdrawSubmitted,
5709
5747
  onWithdrawComplete,
5710
5748
  onWithdrawFailed,
5711
- onError
5749
+ onError,
5750
+ debug
5712
5751
  }) {
5713
5752
  const modalRef = useRef9(null);
5714
5753
  const [currentStepIndex, setCurrentStepIndex] = useState12(0);
@@ -5874,7 +5913,8 @@ function WithdrawModalInner({
5874
5913
  onWithdrawSubmitted,
5875
5914
  onWithdrawComplete,
5876
5915
  onWithdrawFailed,
5877
- onError
5916
+ onError,
5917
+ debug
5878
5918
  }
5879
5919
  )
5880
5920
  ] })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rhinestone/deposit-modal",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "React modal component for Rhinestone cross-chain deposits",
5
5
  "author": "Rhinestone <dev@rhinestone.wtf>",
6
6
  "bugs": {