@rhinestone/deposit-modal 0.1.6 → 0.1.8

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/dist/index.cjs CHANGED
@@ -651,12 +651,27 @@ async function signEnableSessionWithOwner(rhinestoneAccount, sessionDetails, sig
651
651
  rhinestoneAccount.config.owners = originalOwners;
652
652
  }
653
653
  }
654
- async function getSessionDetails(rhinestoneAccount, targetChain, signerAddress, sessionSigner, targetToken) {
654
+ async function getSessionDetails(rhinestoneAccount, targetChain, signerAddress, sessionSigner, targetToken, sessionChainIds) {
655
655
  const isTargetTestnet = Boolean(targetChain.testnet);
656
656
  const chainsByNetworkType = SUPPORTED_CHAINS.filter(
657
657
  (chain) => Boolean(chain.testnet) === isTargetTestnet
658
658
  );
659
+ const chainsById = new Map(
660
+ chainsByNetworkType.map((chain) => [chain.id, chain])
661
+ );
659
662
  let selectedChains = [...chainsByNetworkType];
663
+ if (sessionChainIds && sessionChainIds.length > 0) {
664
+ const selectedByCaller = [];
665
+ for (const chainId of sessionChainIds) {
666
+ const chain = chainsById.get(chainId);
667
+ if (chain) {
668
+ selectedByCaller.push(chain);
669
+ }
670
+ }
671
+ if (selectedByCaller.length > 0) {
672
+ selectedChains = selectedByCaller;
673
+ }
674
+ }
660
675
  if (targetToken) {
661
676
  const targetSymbol = getTokenSymbol(targetToken, targetChain.id).toUpperCase();
662
677
  if (targetSymbol && targetSymbol !== "TOKEN") {
@@ -671,7 +686,10 @@ async function getSessionDetails(rhinestoneAccount, targetChain, signerAddress,
671
686
  if (!selectedChains.some((c) => c.id === targetChain.id)) {
672
687
  selectedChains.push(targetChain);
673
688
  }
674
- const sessions = selectedChains.map(
689
+ const uniqueChains = Array.from(
690
+ new Map(selectedChains.map((chain) => [chain.id, chain])).values()
691
+ );
692
+ const sessions = uniqueChains.map(
675
693
  (chain) => buildSession(chain, signerAddress)
676
694
  );
677
695
  const sessionDetails = await rhinestoneAccount.experimental_getSessionDetails(sessions);
@@ -759,6 +777,7 @@ function SetupStep({
759
777
  targetChainObj,
760
778
  targetToken,
761
779
  signerAddress,
780
+ sessionChainIds,
762
781
  recipient,
763
782
  forceRegister,
764
783
  service,
@@ -799,7 +818,8 @@ function SetupStep({
799
818
  targetChainObj,
800
819
  signerAddress,
801
820
  sessionOwner.account,
802
- targetToken
821
+ targetToken,
822
+ sessionChainIds
803
823
  );
804
824
  setState({ type: "registering" });
805
825
  await service.registerAccount({
@@ -832,6 +852,7 @@ function SetupStep({
832
852
  targetChain,
833
853
  targetToken,
834
854
  signerAddress,
855
+ sessionChainIds,
835
856
  recipient,
836
857
  forceRegister,
837
858
  service,
@@ -2121,6 +2142,49 @@ var INITIAL_POLL_INTERVAL = 3e3;
2121
2142
  var MAX_POLL_INTERVAL = 3e4;
2122
2143
  var BACKOFF_MULTIPLIER = 1.5;
2123
2144
  var PROCESS_TIMEOUT_MS = 10 * 60 * 1e3;
2145
+ function getEventTxHash(event) {
2146
+ if (!event?.type) return void 0;
2147
+ if (event.type === "deposit-received") {
2148
+ const data = event.data;
2149
+ return typeof data?.transactionHash === "string" ? data.transactionHash : void 0;
2150
+ }
2151
+ if (event.type === "bridge-started" || event.type === "bridge-complete") {
2152
+ const data = event.data;
2153
+ const txHash = data?.source?.transactionHash;
2154
+ return typeof txHash === "string" ? txHash : void 0;
2155
+ }
2156
+ if (event.type === "bridge-failed") {
2157
+ const data = event.data;
2158
+ const txHash = data?.deposit?.transactionHash;
2159
+ return typeof txHash === "string" ? txHash : void 0;
2160
+ }
2161
+ if (event.type === "error") {
2162
+ const data = event.data;
2163
+ const txHash = data?.deposit?.transactionHash;
2164
+ return typeof txHash === "string" ? txHash : void 0;
2165
+ }
2166
+ return void 0;
2167
+ }
2168
+ function isEventForTx(event, txHash) {
2169
+ const eventTxHash = getEventTxHash(event);
2170
+ if (!eventTxHash) return false;
2171
+ return eventTxHash.toLowerCase() === txHash.toLowerCase();
2172
+ }
2173
+ function formatBridgeFailedMessage(event) {
2174
+ const eventData = event?.data ?? {};
2175
+ const code = typeof eventData.errorCode === "string" ? eventData.errorCode : void 0;
2176
+ const backendMessage = typeof eventData.message === "string" ? eventData.message.trim() : "";
2177
+ if (backendMessage.length > 0) {
2178
+ return {
2179
+ message: backendMessage,
2180
+ code
2181
+ };
2182
+ }
2183
+ if (code) {
2184
+ return { message: `Bridge failed (${code})`, code };
2185
+ }
2186
+ return { message: "Bridge failed" };
2187
+ }
2124
2188
  function ProcessingStep({
2125
2189
  publicClient,
2126
2190
  smartAccount,
@@ -2238,36 +2302,46 @@ function ProcessingStep({
2238
2302
  try {
2239
2303
  const data = await service.fetchStatus(smartAccount);
2240
2304
  const lastEvent2 = data.lastEvent;
2305
+ const eventMatchesTx = isEventForTx(lastEvent2, txHash);
2306
+ const eventForCurrentTx = eventMatchesTx ? lastEvent2 : void 0;
2241
2307
  if (!isMounted) return;
2242
- if (lastEvent2?.type === "bridge-complete") {
2243
- setState({ type: "complete", lastEvent: lastEvent2 });
2244
- const destinationTxHash2 = lastEvent2.data?.destination?.transactionHash;
2308
+ if (eventForCurrentTx?.type === "bridge-complete") {
2309
+ setState({ type: "complete", lastEvent: eventForCurrentTx });
2310
+ const destinationTxHash2 = eventForCurrentTx.data?.destination?.transactionHash;
2245
2311
  onDepositComplete?.(txHash, destinationTxHash2);
2246
2312
  return;
2247
2313
  }
2248
- if (!waitForFinalTx && lastEvent2?.type === "bridge-started") {
2249
- setState({ type: "complete", lastEvent: lastEvent2 });
2314
+ if (!waitForFinalTx && eventForCurrentTx?.type === "bridge-started") {
2315
+ setState({ type: "complete", lastEvent: eventForCurrentTx });
2250
2316
  onDepositComplete?.(txHash);
2251
2317
  return;
2252
2318
  }
2253
- if (lastEvent2?.type === "deposit-received" && sameChainAndToken) {
2254
- setState({ type: "complete", lastEvent: lastEvent2 });
2319
+ if (eventForCurrentTx?.type === "deposit-received" && sameChainAndToken) {
2320
+ setState({ type: "complete", lastEvent: eventForCurrentTx });
2255
2321
  onDepositComplete?.(txHash);
2256
2322
  return;
2257
2323
  }
2258
- if (lastEvent2?.type === "bridge-failed") {
2259
- const errorCode = lastEvent2.data?.errorCode ?? "Bridge failed";
2260
- setState({ type: "failed", message: errorCode, lastEvent: lastEvent2 });
2261
- onDepositFailed?.(txHash, errorCode);
2324
+ if (eventForCurrentTx?.type === "bridge-failed") {
2325
+ const formatted = formatBridgeFailedMessage(eventForCurrentTx);
2326
+ setState({
2327
+ type: "failed",
2328
+ message: formatted.message,
2329
+ lastEvent: eventForCurrentTx
2330
+ });
2331
+ onDepositFailed?.(txHash, formatted.message);
2262
2332
  return;
2263
2333
  }
2264
- if (lastEvent2?.type === "error") {
2265
- const errorMessage = lastEvent2.data?.message ?? "Unknown error";
2266
- setState({ type: "failed", message: errorMessage, lastEvent: lastEvent2 });
2334
+ if (eventForCurrentTx?.type === "error") {
2335
+ const errorMessage = eventForCurrentTx.data?.message ?? "Unknown error";
2336
+ setState({
2337
+ type: "failed",
2338
+ message: errorMessage,
2339
+ lastEvent: eventForCurrentTx
2340
+ });
2267
2341
  onDepositFailed?.(txHash, errorMessage);
2268
2342
  return;
2269
2343
  }
2270
- setState({ type: "processing", lastEvent: lastEvent2 });
2344
+ setState({ type: "processing", lastEvent: eventForCurrentTx });
2271
2345
  scheduleNextPoll();
2272
2346
  } catch {
2273
2347
  scheduleNextPoll();
@@ -2730,7 +2804,8 @@ function DepositFlow({
2730
2804
  amount: defaultAmount,
2731
2805
  recipient,
2732
2806
  signerAddress = DEFAULT_SIGNER_ADDRESS,
2733
- forceRegister = true,
2807
+ sessionChainIds,
2808
+ forceRegister = false,
2734
2809
  waitForFinalTx = true,
2735
2810
  onRequestConnect,
2736
2811
  connectButtonLabel,
@@ -2885,6 +2960,7 @@ function DepositFlow({
2885
2960
  targetChainObj,
2886
2961
  targetToken,
2887
2962
  signerAddress,
2963
+ sessionChainIds,
2888
2964
  recipient,
2889
2965
  forceRegister,
2890
2966
  service,
@@ -3024,7 +3100,8 @@ function DepositModal({
3024
3100
  recipient,
3025
3101
  backendUrl = DEFAULT_BACKEND_URL,
3026
3102
  signerAddress = DEFAULT_SIGNER_ADDRESS,
3027
- forceRegister = true,
3103
+ sessionChainIds,
3104
+ forceRegister = false,
3028
3105
  waitForFinalTx = true,
3029
3106
  onRequestConnect,
3030
3107
  connectButtonLabel,
@@ -3190,6 +3267,7 @@ function DepositModal({
3190
3267
  amount: defaultAmount,
3191
3268
  recipient,
3192
3269
  signerAddress,
3270
+ sessionChainIds,
3193
3271
  forceRegister,
3194
3272
  waitForFinalTx,
3195
3273
  onRequestConnect,
@@ -3964,6 +4042,8 @@ function WithdrawFlow({
3964
4042
  service,
3965
4043
  switchChain,
3966
4044
  signerAddress = DEFAULT_SIGNER_ADDRESS,
4045
+ sessionChainIds,
4046
+ forceRegister = false,
3967
4047
  waitForFinalTx = true,
3968
4048
  onRequestConnect,
3969
4049
  connectButtonLabel,
@@ -4052,29 +4132,34 @@ function WithdrawFlow({
4052
4132
  sessionOwner.account
4053
4133
  );
4054
4134
  const smartAccount = getAccountAddress(account);
4055
- const initData = getAccountInitData(account);
4056
- const sessionDetails = await getSessionDetails(
4057
- account,
4058
- targetChainObj,
4059
- signerAddress,
4060
- sessionOwner.account,
4061
- targetToken
4062
- );
4063
- await service.registerAccount({
4064
- address: smartAccount,
4065
- accountParams: {
4066
- factory: initData.factory,
4067
- factoryData: initData.factoryData,
4068
- sessionDetails
4069
- },
4070
- eoaAddress: address,
4071
- sessionOwner: sessionOwner.address,
4072
- target: {
4073
- chain: targetChain,
4074
- token: targetToken,
4075
- recipient
4076
- }
4077
- });
4135
+ const checkResult = await service.checkAccount(smartAccount);
4136
+ const targetMatches = checkResult.targetChain === targetChain && checkResult.targetToken?.toLowerCase() === targetToken.toLowerCase();
4137
+ if (!checkResult.isRegistered || forceRegister || !targetMatches) {
4138
+ const initData = getAccountInitData(account);
4139
+ const sessionDetails = await getSessionDetails(
4140
+ account,
4141
+ targetChainObj,
4142
+ signerAddress,
4143
+ sessionOwner.account,
4144
+ targetToken,
4145
+ sessionChainIds
4146
+ );
4147
+ await service.registerAccount({
4148
+ address: smartAccount,
4149
+ accountParams: {
4150
+ factory: initData.factory,
4151
+ factoryData: initData.factoryData,
4152
+ sessionDetails
4153
+ },
4154
+ eoaAddress: address,
4155
+ sessionOwner: sessionOwner.address,
4156
+ target: {
4157
+ chain: targetChain,
4158
+ token: targetToken,
4159
+ recipient
4160
+ }
4161
+ });
4162
+ }
4078
4163
  handleConnected(address, smartAccount);
4079
4164
  const amountUnits = (0, import_viem9.parseUnits)(amountValue, asset.decimals);
4080
4165
  const result = isSourceNative ? await executeSafeEthTransfer({
@@ -4122,6 +4207,8 @@ function WithdrawFlow({
4122
4207
  targetChainObj,
4123
4208
  resolveSessionOwner2,
4124
4209
  signerAddress,
4210
+ sessionChainIds,
4211
+ forceRegister,
4125
4212
  targetChain,
4126
4213
  targetToken,
4127
4214
  service,
@@ -4260,6 +4347,8 @@ function WithdrawModal({
4260
4347
  switchChain,
4261
4348
  backendUrl = DEFAULT_BACKEND_URL,
4262
4349
  signerAddress = DEFAULT_SIGNER_ADDRESS,
4350
+ sessionChainIds,
4351
+ forceRegister = false,
4263
4352
  waitForFinalTx = true,
4264
4353
  onRequestConnect,
4265
4354
  connectButtonLabel,
@@ -4423,6 +4512,8 @@ function WithdrawModal({
4423
4512
  service,
4424
4513
  switchChain,
4425
4514
  signerAddress,
4515
+ sessionChainIds,
4516
+ forceRegister,
4426
4517
  waitForFinalTx,
4427
4518
  onRequestConnect,
4428
4519
  connectButtonLabel,
package/dist/index.d.cts CHANGED
@@ -77,6 +77,7 @@ interface DepositModalProps {
77
77
  recipient?: Address;
78
78
  backendUrl?: string;
79
79
  signerAddress?: Address;
80
+ sessionChainIds?: number[];
80
81
  forceRegister?: boolean;
81
82
  waitForFinalTx?: boolean;
82
83
  onRequestConnect?: () => void;
@@ -111,6 +112,8 @@ interface WithdrawModalProps {
111
112
  } | void>;
112
113
  backendUrl?: string;
113
114
  signerAddress?: Address;
115
+ sessionChainIds?: number[];
116
+ forceRegister?: boolean;
114
117
  waitForFinalTx?: boolean;
115
118
  onRequestConnect?: () => void;
116
119
  connectButtonLabel?: string;
@@ -136,12 +139,12 @@ interface AssetOption {
136
139
  balanceUsd?: number;
137
140
  }
138
141
 
139
- declare function DepositModal({ walletClient, publicClient, address, targetChain: targetChainProp, targetToken, isOpen, onClose, inline, switchChain, sourceChain: sourceChainProp, sourceToken, defaultAmount, recipient, backendUrl, signerAddress, forceRegister, waitForFinalTx, onRequestConnect, connectButtonLabel, theme, branding, uiConfig, className, onReady, onConnected, onDepositSubmitted, onDepositComplete, onDepositFailed, onError, }: DepositModalProps): react_jsx_runtime.JSX.Element;
142
+ declare function DepositModal({ walletClient, publicClient, address, targetChain: targetChainProp, targetToken, isOpen, onClose, inline, switchChain, sourceChain: sourceChainProp, sourceToken, defaultAmount, recipient, backendUrl, signerAddress, sessionChainIds, forceRegister, waitForFinalTx, onRequestConnect, connectButtonLabel, theme, branding, uiConfig, className, onReady, onConnected, onDepositSubmitted, onDepositComplete, onDepositFailed, onError, }: DepositModalProps): react_jsx_runtime.JSX.Element;
140
143
  declare namespace DepositModal {
141
144
  var displayName: string;
142
145
  }
143
146
 
144
- declare function WithdrawModal({ walletClient, publicClient, address, safeAddress, sourceChain: sourceChainProp, sourceToken, targetChain: targetChainProp, targetToken, recipient, defaultAmount, isOpen, onClose, inline, switchChain, backendUrl, signerAddress, waitForFinalTx, onRequestConnect, connectButtonLabel, theme, branding, uiConfig, className, onReady, onConnected, onWithdrawSubmitted, onWithdrawComplete, onWithdrawFailed, onError, }: WithdrawModalProps): react_jsx_runtime.JSX.Element;
147
+ declare function WithdrawModal({ walletClient, publicClient, address, safeAddress, sourceChain: sourceChainProp, sourceToken, targetChain: targetChainProp, targetToken, recipient, defaultAmount, isOpen, onClose, inline, switchChain, backendUrl, signerAddress, sessionChainIds, forceRegister, waitForFinalTx, onRequestConnect, connectButtonLabel, theme, branding, uiConfig, className, onReady, onConnected, onWithdrawSubmitted, onWithdrawComplete, onWithdrawFailed, onError, }: WithdrawModalProps): react_jsx_runtime.JSX.Element;
145
148
  declare namespace WithdrawModal {
146
149
  var displayName: string;
147
150
  }
package/dist/index.d.ts CHANGED
@@ -77,6 +77,7 @@ interface DepositModalProps {
77
77
  recipient?: Address;
78
78
  backendUrl?: string;
79
79
  signerAddress?: Address;
80
+ sessionChainIds?: number[];
80
81
  forceRegister?: boolean;
81
82
  waitForFinalTx?: boolean;
82
83
  onRequestConnect?: () => void;
@@ -111,6 +112,8 @@ interface WithdrawModalProps {
111
112
  } | void>;
112
113
  backendUrl?: string;
113
114
  signerAddress?: Address;
115
+ sessionChainIds?: number[];
116
+ forceRegister?: boolean;
114
117
  waitForFinalTx?: boolean;
115
118
  onRequestConnect?: () => void;
116
119
  connectButtonLabel?: string;
@@ -136,12 +139,12 @@ interface AssetOption {
136
139
  balanceUsd?: number;
137
140
  }
138
141
 
139
- declare function DepositModal({ walletClient, publicClient, address, targetChain: targetChainProp, targetToken, isOpen, onClose, inline, switchChain, sourceChain: sourceChainProp, sourceToken, defaultAmount, recipient, backendUrl, signerAddress, forceRegister, waitForFinalTx, onRequestConnect, connectButtonLabel, theme, branding, uiConfig, className, onReady, onConnected, onDepositSubmitted, onDepositComplete, onDepositFailed, onError, }: DepositModalProps): react_jsx_runtime.JSX.Element;
142
+ declare function DepositModal({ walletClient, publicClient, address, targetChain: targetChainProp, targetToken, isOpen, onClose, inline, switchChain, sourceChain: sourceChainProp, sourceToken, defaultAmount, recipient, backendUrl, signerAddress, sessionChainIds, forceRegister, waitForFinalTx, onRequestConnect, connectButtonLabel, theme, branding, uiConfig, className, onReady, onConnected, onDepositSubmitted, onDepositComplete, onDepositFailed, onError, }: DepositModalProps): react_jsx_runtime.JSX.Element;
140
143
  declare namespace DepositModal {
141
144
  var displayName: string;
142
145
  }
143
146
 
144
- declare function WithdrawModal({ walletClient, publicClient, address, safeAddress, sourceChain: sourceChainProp, sourceToken, targetChain: targetChainProp, targetToken, recipient, defaultAmount, isOpen, onClose, inline, switchChain, backendUrl, signerAddress, waitForFinalTx, onRequestConnect, connectButtonLabel, theme, branding, uiConfig, className, onReady, onConnected, onWithdrawSubmitted, onWithdrawComplete, onWithdrawFailed, onError, }: WithdrawModalProps): react_jsx_runtime.JSX.Element;
147
+ declare function WithdrawModal({ walletClient, publicClient, address, safeAddress, sourceChain: sourceChainProp, sourceToken, targetChain: targetChainProp, targetToken, recipient, defaultAmount, isOpen, onClose, inline, switchChain, backendUrl, signerAddress, sessionChainIds, forceRegister, waitForFinalTx, onRequestConnect, connectButtonLabel, theme, branding, uiConfig, className, onReady, onConnected, onWithdrawSubmitted, onWithdrawComplete, onWithdrawFailed, onError, }: WithdrawModalProps): react_jsx_runtime.JSX.Element;
145
148
  declare namespace WithdrawModal {
146
149
  var displayName: string;
147
150
  }
package/dist/index.mjs CHANGED
@@ -610,12 +610,27 @@ async function signEnableSessionWithOwner(rhinestoneAccount, sessionDetails, sig
610
610
  rhinestoneAccount.config.owners = originalOwners;
611
611
  }
612
612
  }
613
- async function getSessionDetails(rhinestoneAccount, targetChain, signerAddress, sessionSigner, targetToken) {
613
+ async function getSessionDetails(rhinestoneAccount, targetChain, signerAddress, sessionSigner, targetToken, sessionChainIds) {
614
614
  const isTargetTestnet = Boolean(targetChain.testnet);
615
615
  const chainsByNetworkType = SUPPORTED_CHAINS.filter(
616
616
  (chain) => Boolean(chain.testnet) === isTargetTestnet
617
617
  );
618
+ const chainsById = new Map(
619
+ chainsByNetworkType.map((chain) => [chain.id, chain])
620
+ );
618
621
  let selectedChains = [...chainsByNetworkType];
622
+ if (sessionChainIds && sessionChainIds.length > 0) {
623
+ const selectedByCaller = [];
624
+ for (const chainId of sessionChainIds) {
625
+ const chain = chainsById.get(chainId);
626
+ if (chain) {
627
+ selectedByCaller.push(chain);
628
+ }
629
+ }
630
+ if (selectedByCaller.length > 0) {
631
+ selectedChains = selectedByCaller;
632
+ }
633
+ }
619
634
  if (targetToken) {
620
635
  const targetSymbol = getTokenSymbol(targetToken, targetChain.id).toUpperCase();
621
636
  if (targetSymbol && targetSymbol !== "TOKEN") {
@@ -630,7 +645,10 @@ async function getSessionDetails(rhinestoneAccount, targetChain, signerAddress,
630
645
  if (!selectedChains.some((c) => c.id === targetChain.id)) {
631
646
  selectedChains.push(targetChain);
632
647
  }
633
- const sessions = selectedChains.map(
648
+ const uniqueChains = Array.from(
649
+ new Map(selectedChains.map((chain) => [chain.id, chain])).values()
650
+ );
651
+ const sessions = uniqueChains.map(
634
652
  (chain) => buildSession(chain, signerAddress)
635
653
  );
636
654
  const sessionDetails = await rhinestoneAccount.experimental_getSessionDetails(sessions);
@@ -721,6 +739,7 @@ function SetupStep({
721
739
  targetChainObj,
722
740
  targetToken,
723
741
  signerAddress,
742
+ sessionChainIds,
724
743
  recipient,
725
744
  forceRegister,
726
745
  service,
@@ -761,7 +780,8 @@ function SetupStep({
761
780
  targetChainObj,
762
781
  signerAddress,
763
782
  sessionOwner.account,
764
- targetToken
783
+ targetToken,
784
+ sessionChainIds
765
785
  );
766
786
  setState({ type: "registering" });
767
787
  await service.registerAccount({
@@ -794,6 +814,7 @@ function SetupStep({
794
814
  targetChain,
795
815
  targetToken,
796
816
  signerAddress,
817
+ sessionChainIds,
797
818
  recipient,
798
819
  forceRegister,
799
820
  service,
@@ -2083,6 +2104,49 @@ var INITIAL_POLL_INTERVAL = 3e3;
2083
2104
  var MAX_POLL_INTERVAL = 3e4;
2084
2105
  var BACKOFF_MULTIPLIER = 1.5;
2085
2106
  var PROCESS_TIMEOUT_MS = 10 * 60 * 1e3;
2107
+ function getEventTxHash(event) {
2108
+ if (!event?.type) return void 0;
2109
+ if (event.type === "deposit-received") {
2110
+ const data = event.data;
2111
+ return typeof data?.transactionHash === "string" ? data.transactionHash : void 0;
2112
+ }
2113
+ if (event.type === "bridge-started" || event.type === "bridge-complete") {
2114
+ const data = event.data;
2115
+ const txHash = data?.source?.transactionHash;
2116
+ return typeof txHash === "string" ? txHash : void 0;
2117
+ }
2118
+ if (event.type === "bridge-failed") {
2119
+ const data = event.data;
2120
+ const txHash = data?.deposit?.transactionHash;
2121
+ return typeof txHash === "string" ? txHash : void 0;
2122
+ }
2123
+ if (event.type === "error") {
2124
+ const data = event.data;
2125
+ const txHash = data?.deposit?.transactionHash;
2126
+ return typeof txHash === "string" ? txHash : void 0;
2127
+ }
2128
+ return void 0;
2129
+ }
2130
+ function isEventForTx(event, txHash) {
2131
+ const eventTxHash = getEventTxHash(event);
2132
+ if (!eventTxHash) return false;
2133
+ return eventTxHash.toLowerCase() === txHash.toLowerCase();
2134
+ }
2135
+ function formatBridgeFailedMessage(event) {
2136
+ const eventData = event?.data ?? {};
2137
+ const code = typeof eventData.errorCode === "string" ? eventData.errorCode : void 0;
2138
+ const backendMessage = typeof eventData.message === "string" ? eventData.message.trim() : "";
2139
+ if (backendMessage.length > 0) {
2140
+ return {
2141
+ message: backendMessage,
2142
+ code
2143
+ };
2144
+ }
2145
+ if (code) {
2146
+ return { message: `Bridge failed (${code})`, code };
2147
+ }
2148
+ return { message: "Bridge failed" };
2149
+ }
2086
2150
  function ProcessingStep({
2087
2151
  publicClient,
2088
2152
  smartAccount,
@@ -2200,36 +2264,46 @@ function ProcessingStep({
2200
2264
  try {
2201
2265
  const data = await service.fetchStatus(smartAccount);
2202
2266
  const lastEvent2 = data.lastEvent;
2267
+ const eventMatchesTx = isEventForTx(lastEvent2, txHash);
2268
+ const eventForCurrentTx = eventMatchesTx ? lastEvent2 : void 0;
2203
2269
  if (!isMounted) return;
2204
- if (lastEvent2?.type === "bridge-complete") {
2205
- setState({ type: "complete", lastEvent: lastEvent2 });
2206
- const destinationTxHash2 = lastEvent2.data?.destination?.transactionHash;
2270
+ if (eventForCurrentTx?.type === "bridge-complete") {
2271
+ setState({ type: "complete", lastEvent: eventForCurrentTx });
2272
+ const destinationTxHash2 = eventForCurrentTx.data?.destination?.transactionHash;
2207
2273
  onDepositComplete?.(txHash, destinationTxHash2);
2208
2274
  return;
2209
2275
  }
2210
- if (!waitForFinalTx && lastEvent2?.type === "bridge-started") {
2211
- setState({ type: "complete", lastEvent: lastEvent2 });
2276
+ if (!waitForFinalTx && eventForCurrentTx?.type === "bridge-started") {
2277
+ setState({ type: "complete", lastEvent: eventForCurrentTx });
2212
2278
  onDepositComplete?.(txHash);
2213
2279
  return;
2214
2280
  }
2215
- if (lastEvent2?.type === "deposit-received" && sameChainAndToken) {
2216
- setState({ type: "complete", lastEvent: lastEvent2 });
2281
+ if (eventForCurrentTx?.type === "deposit-received" && sameChainAndToken) {
2282
+ setState({ type: "complete", lastEvent: eventForCurrentTx });
2217
2283
  onDepositComplete?.(txHash);
2218
2284
  return;
2219
2285
  }
2220
- if (lastEvent2?.type === "bridge-failed") {
2221
- const errorCode = lastEvent2.data?.errorCode ?? "Bridge failed";
2222
- setState({ type: "failed", message: errorCode, lastEvent: lastEvent2 });
2223
- onDepositFailed?.(txHash, errorCode);
2286
+ if (eventForCurrentTx?.type === "bridge-failed") {
2287
+ const formatted = formatBridgeFailedMessage(eventForCurrentTx);
2288
+ setState({
2289
+ type: "failed",
2290
+ message: formatted.message,
2291
+ lastEvent: eventForCurrentTx
2292
+ });
2293
+ onDepositFailed?.(txHash, formatted.message);
2224
2294
  return;
2225
2295
  }
2226
- if (lastEvent2?.type === "error") {
2227
- const errorMessage = lastEvent2.data?.message ?? "Unknown error";
2228
- setState({ type: "failed", message: errorMessage, lastEvent: lastEvent2 });
2296
+ if (eventForCurrentTx?.type === "error") {
2297
+ const errorMessage = eventForCurrentTx.data?.message ?? "Unknown error";
2298
+ setState({
2299
+ type: "failed",
2300
+ message: errorMessage,
2301
+ lastEvent: eventForCurrentTx
2302
+ });
2229
2303
  onDepositFailed?.(txHash, errorMessage);
2230
2304
  return;
2231
2305
  }
2232
- setState({ type: "processing", lastEvent: lastEvent2 });
2306
+ setState({ type: "processing", lastEvent: eventForCurrentTx });
2233
2307
  scheduleNextPoll();
2234
2308
  } catch {
2235
2309
  scheduleNextPoll();
@@ -2692,7 +2766,8 @@ function DepositFlow({
2692
2766
  amount: defaultAmount,
2693
2767
  recipient,
2694
2768
  signerAddress = DEFAULT_SIGNER_ADDRESS,
2695
- forceRegister = true,
2769
+ sessionChainIds,
2770
+ forceRegister = false,
2696
2771
  waitForFinalTx = true,
2697
2772
  onRequestConnect,
2698
2773
  connectButtonLabel,
@@ -2847,6 +2922,7 @@ function DepositFlow({
2847
2922
  targetChainObj,
2848
2923
  targetToken,
2849
2924
  signerAddress,
2925
+ sessionChainIds,
2850
2926
  recipient,
2851
2927
  forceRegister,
2852
2928
  service,
@@ -2986,7 +3062,8 @@ function DepositModal({
2986
3062
  recipient,
2987
3063
  backendUrl = DEFAULT_BACKEND_URL,
2988
3064
  signerAddress = DEFAULT_SIGNER_ADDRESS,
2989
- forceRegister = true,
3065
+ sessionChainIds,
3066
+ forceRegister = false,
2990
3067
  waitForFinalTx = true,
2991
3068
  onRequestConnect,
2992
3069
  connectButtonLabel,
@@ -3152,6 +3229,7 @@ function DepositModal({
3152
3229
  amount: defaultAmount,
3153
3230
  recipient,
3154
3231
  signerAddress,
3232
+ sessionChainIds,
3155
3233
  forceRegister,
3156
3234
  waitForFinalTx,
3157
3235
  onRequestConnect,
@@ -3934,6 +4012,8 @@ function WithdrawFlow({
3934
4012
  service,
3935
4013
  switchChain,
3936
4014
  signerAddress = DEFAULT_SIGNER_ADDRESS,
4015
+ sessionChainIds,
4016
+ forceRegister = false,
3937
4017
  waitForFinalTx = true,
3938
4018
  onRequestConnect,
3939
4019
  connectButtonLabel,
@@ -4022,29 +4102,34 @@ function WithdrawFlow({
4022
4102
  sessionOwner.account
4023
4103
  );
4024
4104
  const smartAccount = getAccountAddress(account);
4025
- const initData = getAccountInitData(account);
4026
- const sessionDetails = await getSessionDetails(
4027
- account,
4028
- targetChainObj,
4029
- signerAddress,
4030
- sessionOwner.account,
4031
- targetToken
4032
- );
4033
- await service.registerAccount({
4034
- address: smartAccount,
4035
- accountParams: {
4036
- factory: initData.factory,
4037
- factoryData: initData.factoryData,
4038
- sessionDetails
4039
- },
4040
- eoaAddress: address,
4041
- sessionOwner: sessionOwner.address,
4042
- target: {
4043
- chain: targetChain,
4044
- token: targetToken,
4045
- recipient
4046
- }
4047
- });
4105
+ const checkResult = await service.checkAccount(smartAccount);
4106
+ const targetMatches = checkResult.targetChain === targetChain && checkResult.targetToken?.toLowerCase() === targetToken.toLowerCase();
4107
+ if (!checkResult.isRegistered || forceRegister || !targetMatches) {
4108
+ const initData = getAccountInitData(account);
4109
+ const sessionDetails = await getSessionDetails(
4110
+ account,
4111
+ targetChainObj,
4112
+ signerAddress,
4113
+ sessionOwner.account,
4114
+ targetToken,
4115
+ sessionChainIds
4116
+ );
4117
+ await service.registerAccount({
4118
+ address: smartAccount,
4119
+ accountParams: {
4120
+ factory: initData.factory,
4121
+ factoryData: initData.factoryData,
4122
+ sessionDetails
4123
+ },
4124
+ eoaAddress: address,
4125
+ sessionOwner: sessionOwner.address,
4126
+ target: {
4127
+ chain: targetChain,
4128
+ token: targetToken,
4129
+ recipient
4130
+ }
4131
+ });
4132
+ }
4048
4133
  handleConnected(address, smartAccount);
4049
4134
  const amountUnits = parseUnits4(amountValue, asset.decimals);
4050
4135
  const result = isSourceNative ? await executeSafeEthTransfer({
@@ -4092,6 +4177,8 @@ function WithdrawFlow({
4092
4177
  targetChainObj,
4093
4178
  resolveSessionOwner2,
4094
4179
  signerAddress,
4180
+ sessionChainIds,
4181
+ forceRegister,
4095
4182
  targetChain,
4096
4183
  targetToken,
4097
4184
  service,
@@ -4230,6 +4317,8 @@ function WithdrawModal({
4230
4317
  switchChain,
4231
4318
  backendUrl = DEFAULT_BACKEND_URL,
4232
4319
  signerAddress = DEFAULT_SIGNER_ADDRESS,
4320
+ sessionChainIds,
4321
+ forceRegister = false,
4233
4322
  waitForFinalTx = true,
4234
4323
  onRequestConnect,
4235
4324
  connectButtonLabel,
@@ -4393,6 +4482,8 @@ function WithdrawModal({
4393
4482
  service,
4394
4483
  switchChain,
4395
4484
  signerAddress,
4485
+ sessionChainIds,
4486
+ forceRegister,
4396
4487
  waitForFinalTx,
4397
4488
  onRequestConnect,
4398
4489
  connectButtonLabel,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rhinestone/deposit-modal",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "React modal component for Rhinestone cross-chain deposits",
5
5
  "author": "Rhinestone <dev@rhinestone.wtf>",
6
6
  "bugs": {