@oasisprotocol/privana-sdk 0.5.2 → 0.5.4

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
@@ -1,17 +1,17 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkUHXVYWTF_cjs = require('./chunk-UHXVYWTF.cjs');
4
+ var chunkFGWMLLEC_cjs = require('./chunk-FGWMLLEC.cjs');
5
5
  var react = require('react');
6
6
  var reactQuery = require('@tanstack/react-query');
7
7
  var wagmi = require('wagmi');
8
8
  var viem = require('viem');
9
+ var moonpayReact = require('@moonpay/moonpay-react');
9
10
  var DialogPrimitive = require('@radix-ui/react-dialog');
10
11
  var lucideReact = require('lucide-react');
11
12
  var jsxRuntime = require('react/jsx-runtime');
12
13
  var sonner = require('sonner');
13
14
  var qrcode_react = require('qrcode.react');
14
- var moonpayReact = require('@moonpay/moonpay-react');
15
15
 
16
16
  function _interopNamespace(e) {
17
17
  if (e && e.__esModule) return e;
@@ -35,18 +35,18 @@ var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive)
35
35
 
36
36
  // src/sdk/hooks/use-privana-client.ts
37
37
  function usePrivanaClient() {
38
- const { client } = chunkUHXVYWTF_cjs.usePrivanaContext();
38
+ const { client } = chunkFGWMLLEC_cjs.usePrivanaContext();
39
39
  return client;
40
40
  }
41
41
  var hostedAuthExchangeInflight = /* @__PURE__ */ new Map();
42
42
  function normalizeHostedAuthError(error) {
43
- if (error instanceof chunkUHXVYWTF_cjs.AccountingApiError && error.detail) {
44
- return new chunkUHXVYWTF_cjs.HostedAuthError(error.detail);
43
+ if (error instanceof chunkFGWMLLEC_cjs.AccountingApiError && error.detail) {
44
+ return new chunkFGWMLLEC_cjs.HostedAuthError(error.detail);
45
45
  }
46
46
  if (error instanceof Error) {
47
47
  return error;
48
48
  }
49
- return new chunkUHXVYWTF_cjs.HostedAuthError("Hosted authentication failed.");
49
+ return new chunkFGWMLLEC_cjs.HostedAuthError("Hosted authentication failed.");
50
50
  }
51
51
  function useHostedRedirectAuth() {
52
52
  const {
@@ -57,30 +57,30 @@ function useHostedRedirectAuth() {
57
57
  setHostedAuthSession,
58
58
  clearHostedAuthSession,
59
59
  refreshHostedAuthSession
60
- } = chunkUHXVYWTF_cjs.usePrivanaContext();
60
+ } = chunkFGWMLLEC_cjs.usePrivanaContext();
61
61
  const [error, setError] = react.useState(null);
62
62
  const [isLoading, setIsLoading] = react.useState(false);
63
63
  const loginInflight = react.useRef(null);
64
64
  const completionInflight = react.useRef(null);
65
65
  const pendingStorageKey = react.useMemo(
66
- () => hostedAuthConfig ? chunkUHXVYWTF_cjs.createHostedAuthPendingStorageKey(client.getBaseUrl(), hostedAuthConfig) : null,
66
+ () => hostedAuthConfig ? chunkFGWMLLEC_cjs.createHostedAuthPendingStorageKey(client.getBaseUrl(), hostedAuthConfig) : null,
67
67
  [client, hostedAuthConfig]
68
68
  );
69
69
  const clearPendingLogin = react.useCallback(() => {
70
70
  if (!pendingStorageKey || typeof window === "undefined") return;
71
- chunkUHXVYWTF_cjs.clearHostedAuthPendingTransaction(window.sessionStorage, pendingStorageKey);
71
+ chunkFGWMLLEC_cjs.clearHostedAuthPendingTransaction(window.sessionStorage, pendingStorageKey);
72
72
  }, [pendingStorageKey]);
73
73
  const login = react.useCallback(async () => {
74
74
  if (!hostedAuthConfig) {
75
- throw new chunkUHXVYWTF_cjs.HostedAuthRequiredError(
75
+ throw new chunkFGWMLLEC_cjs.HostedAuthRequiredError(
76
76
  "Hosted redirect authentication is not configured for this provider."
77
77
  );
78
78
  }
79
79
  if (typeof window === "undefined") {
80
- throw new chunkUHXVYWTF_cjs.HostedAuthError("Hosted redirect authentication requires a browser environment.");
80
+ throw new chunkFGWMLLEC_cjs.HostedAuthError("Hosted redirect authentication requires a browser environment.");
81
81
  }
82
82
  if (!pendingStorageKey) {
83
- throw new chunkUHXVYWTF_cjs.HostedAuthError("Hosted redirect authentication storage is not configured.");
83
+ throw new chunkFGWMLLEC_cjs.HostedAuthError("Hosted redirect authentication storage is not configured.");
84
84
  }
85
85
  if (loginInflight.current) {
86
86
  return loginInflight.current;
@@ -89,10 +89,10 @@ function useHostedRedirectAuth() {
89
89
  setIsLoading(true);
90
90
  setError(null);
91
91
  try {
92
- const verifier = chunkUHXVYWTF_cjs.createPkceVerifier();
93
- const codeChallenge = await chunkUHXVYWTF_cjs.createPkceChallenge(verifier);
94
- const state = chunkUHXVYWTF_cjs.createHostedAuthState();
95
- chunkUHXVYWTF_cjs.persistHostedAuthPendingTransaction(window.sessionStorage, pendingStorageKey, {
92
+ const verifier = chunkFGWMLLEC_cjs.createPkceVerifier();
93
+ const codeChallenge = await chunkFGWMLLEC_cjs.createPkceChallenge(verifier);
94
+ const state = chunkFGWMLLEC_cjs.createHostedAuthState();
95
+ chunkFGWMLLEC_cjs.persistHostedAuthPendingTransaction(window.sessionStorage, pendingStorageKey, {
96
96
  codeVerifier: verifier,
97
97
  state
98
98
  });
@@ -121,15 +121,15 @@ function useHostedRedirectAuth() {
121
121
  }, [clearPendingLogin, client, hostedAuthConfig, networkConfig.chainId, pendingStorageKey]);
122
122
  const completeLogin = react.useCallback(async () => {
123
123
  if (!hostedAuthConfig) {
124
- throw new chunkUHXVYWTF_cjs.HostedAuthRequiredError(
124
+ throw new chunkFGWMLLEC_cjs.HostedAuthRequiredError(
125
125
  "Hosted redirect authentication is not configured for this provider."
126
126
  );
127
127
  }
128
128
  if (typeof window === "undefined") {
129
- throw new chunkUHXVYWTF_cjs.HostedAuthError("Hosted redirect authentication requires a browser environment.");
129
+ throw new chunkFGWMLLEC_cjs.HostedAuthError("Hosted redirect authentication requires a browser environment.");
130
130
  }
131
131
  if (!pendingStorageKey) {
132
- throw new chunkUHXVYWTF_cjs.HostedAuthError("Hosted redirect authentication storage is not configured.");
132
+ throw new chunkFGWMLLEC_cjs.HostedAuthError("Hosted redirect authentication storage is not configured.");
133
133
  }
134
134
  if (completionInflight.current) {
135
135
  return completionInflight.current;
@@ -139,30 +139,30 @@ function useHostedRedirectAuth() {
139
139
  setError(null);
140
140
  const callbackUrl = new URL(window.location.href);
141
141
  const cleanupCallbackUrl = () => {
142
- window.history.replaceState(null, "", chunkUHXVYWTF_cjs.stripHostedAuthCallbackParams(callbackUrl));
142
+ window.history.replaceState(null, "", chunkFGWMLLEC_cjs.stripHostedAuthCallbackParams(callbackUrl));
143
143
  };
144
144
  try {
145
- const callback = chunkUHXVYWTF_cjs.parseHostedAuthCallback(callbackUrl, hostedAuthConfig.redirectUri);
145
+ const callback = chunkFGWMLLEC_cjs.parseHostedAuthCallback(callbackUrl, hostedAuthConfig.redirectUri);
146
146
  if (!callback) {
147
147
  return null;
148
148
  }
149
- const pending = chunkUHXVYWTF_cjs.readHostedAuthPendingTransaction(window.sessionStorage, pendingStorageKey);
149
+ const pending = chunkFGWMLLEC_cjs.readHostedAuthPendingTransaction(window.sessionStorage, pendingStorageKey);
150
150
  if (!pending) {
151
151
  clearPendingLogin();
152
152
  cleanupCallbackUrl();
153
- throw new chunkUHXVYWTF_cjs.HostedAuthError(
153
+ throw new chunkFGWMLLEC_cjs.HostedAuthError(
154
154
  "Hosted authentication response could not be matched to a pending login request."
155
155
  );
156
156
  }
157
157
  if (!callback.state || callback.state !== pending.state) {
158
158
  clearPendingLogin();
159
159
  cleanupCallbackUrl();
160
- throw new chunkUHXVYWTF_cjs.HostedAuthStateMismatchError();
160
+ throw new chunkFGWMLLEC_cjs.HostedAuthStateMismatchError();
161
161
  }
162
162
  if ("error" in callback) {
163
163
  clearPendingLogin();
164
164
  cleanupCallbackUrl();
165
- throw new chunkUHXVYWTF_cjs.HostedAuthError(
165
+ throw new chunkFGWMLLEC_cjs.HostedAuthError(
166
166
  callback.errorDescription || callback.error || "Hosted authentication failed."
167
167
  );
168
168
  }
@@ -177,7 +177,7 @@ function useHostedRedirectAuth() {
177
177
  client_id: hostedAuthConfig.clientId,
178
178
  redirect_uri: hostedAuthConfig.redirectUri
179
179
  });
180
- const session = chunkUHXVYWTF_cjs.buildHostedAuthSession(response, hostedAuthConfig);
180
+ const session = chunkFGWMLLEC_cjs.buildHostedAuthSession(response, hostedAuthConfig);
181
181
  setHostedAuthSession(session);
182
182
  clearPendingLogin();
183
183
  cleanupCallbackUrl();
@@ -222,7 +222,7 @@ function useHostedRedirectAuth() {
222
222
  try {
223
223
  return await refreshHostedAuthSession();
224
224
  } catch (refreshError) {
225
- const normalizedError = refreshError instanceof Error ? refreshError : new chunkUHXVYWTF_cjs.HostedAuthError("Hosted authentication refresh failed.");
225
+ const normalizedError = refreshError instanceof Error ? refreshError : new chunkFGWMLLEC_cjs.HostedAuthError("Hosted authentication refresh failed.");
226
226
  setError(normalizedError);
227
227
  throw normalizedError;
228
228
  } finally {
@@ -242,12 +242,12 @@ function useHostedRedirectAuth() {
242
242
  }
243
243
  function useBalance(options = {}) {
244
244
  const queryClient = react.useContext(reactQuery.QueryClientContext);
245
- const accountingContext = chunkUHXVYWTF_cjs.useSafePrivanaContext();
245
+ const accountingContext = chunkFGWMLLEC_cjs.useSafePrivanaContext();
246
246
  const hasProviders = !!queryClient && !!accountingContext;
247
247
  const client = accountingContext?.client;
248
248
  const defaultToken = accountingContext?.defaultToken;
249
249
  const pollingInterval = accountingContext?.pollingInterval ?? 1e4;
250
- const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkUHXVYWTF_cjs.usePrivateReadRequest();
250
+ const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkFGWMLLEC_cjs.usePrivateReadRequest();
251
251
  const tokenId = options.tokenId ?? defaultToken?.id;
252
252
  const query = reactQuery.useQuery({
253
253
  queryKey: ["accounting-balance", ...privateReadQueryScope, tokenId],
@@ -255,7 +255,7 @@ function useBalance(options = {}) {
255
255
  if (!privateReadAddress) throw new Error("No authenticated account available");
256
256
  if (!tokenId) throw new Error("No token ID provided");
257
257
  if (!client) throw new Error("No accounting client");
258
- return executePrivateRead(() => client.getBalance(tokenId));
258
+ return executePrivateRead((readClient) => readClient.getBalance(tokenId));
259
259
  },
260
260
  enabled: hasProviders && (options.enabled ?? true) && privateReadReady && !!privateReadAddress && !!tokenId && !!client,
261
261
  refetchInterval: pollingInterval
@@ -264,7 +264,7 @@ function useBalance(options = {}) {
264
264
  return {
265
265
  balance: balanceWei,
266
266
  balanceWei,
267
- balanceFormatted: chunkUHXVYWTF_cjs.formatTokenAmount(balanceWei),
267
+ balanceFormatted: chunkFGWMLLEC_cjs.formatTokenAmount(balanceWei),
268
268
  tokenSymbol: query.data?.token_symbol ?? "",
269
269
  chainId: query.data?.chain_id ?? "",
270
270
  isLoading: query.isPending || query.isLoading,
@@ -274,13 +274,15 @@ function useBalance(options = {}) {
274
274
  };
275
275
  }
276
276
  function useBatchBalances(options) {
277
- const { client, pollingInterval } = chunkUHXVYWTF_cjs.usePrivanaContext();
278
- const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkUHXVYWTF_cjs.usePrivateReadRequest();
277
+ const { client, pollingInterval } = chunkFGWMLLEC_cjs.usePrivanaContext();
278
+ const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkFGWMLLEC_cjs.usePrivateReadRequest();
279
279
  const query = reactQuery.useQuery({
280
280
  queryKey: ["accounting-batch-balances", ...privateReadQueryScope, options.tokenIds],
281
281
  queryFn: async () => {
282
282
  if (!privateReadAddress) throw new Error("No authenticated account available");
283
- return executePrivateRead(() => client.getBatchBalances({ token_ids: options.tokenIds }));
283
+ return executePrivateRead(
284
+ (readClient) => readClient.getBatchBalances({ token_ids: options.tokenIds })
285
+ );
284
286
  },
285
287
  enabled: (options.enabled ?? true) && privateReadReady && !!privateReadAddress && options.tokenIds.length > 0 && !!client,
286
288
  refetchInterval: pollingInterval
@@ -298,17 +300,17 @@ function storageKey(address) {
298
300
  return `privana:pending-deposit:${address.toLowerCase()}`;
299
301
  }
300
302
  function savePendingDeposit(address, data) {
301
- const stored = chunkUHXVYWTF_cjs.setBrowserStorageItem(storageKey(address), JSON.stringify(data));
303
+ const stored = chunkFGWMLLEC_cjs.setBrowserStorageItem(storageKey(address), JSON.stringify(data));
302
304
  if (!stored && data.signedLock) {
303
305
  throw new Error("Unable to persist pending locked deposit for recovery");
304
306
  }
305
307
  }
306
308
  function loadPendingDeposit(address) {
307
309
  try {
308
- const raw = chunkUHXVYWTF_cjs.getBrowserStorageItem(storageKey(address));
310
+ const raw = chunkFGWMLLEC_cjs.getBrowserStorageItem(storageKey(address));
309
311
  if (!raw) return null;
310
312
  const data = JSON.parse(raw);
311
- if (Date.now() - data.savedAt > STALE_MS && !(data.signedLock && chunkUHXVYWTF_cjs.isSignedLockUsable(data.signedLock))) {
313
+ if (Date.now() - data.savedAt > STALE_MS && !(data.signedLock && chunkFGWMLLEC_cjs.isSignedLockUsable(data.signedLock))) {
312
314
  clearPendingDeposit(address);
313
315
  return null;
314
316
  }
@@ -320,21 +322,23 @@ function loadPendingDeposit(address) {
320
322
  function clearPendingDeposit(address, onlyForTxHash) {
321
323
  if (onlyForTxHash) {
322
324
  try {
323
- const raw = chunkUHXVYWTF_cjs.getBrowserStorageItem(storageKey(address));
325
+ const raw = chunkFGWMLLEC_cjs.getBrowserStorageItem(storageKey(address));
324
326
  const recordTxHash = raw ? JSON.parse(raw).txHash : void 0;
325
327
  if (recordTxHash && recordTxHash !== onlyForTxHash) return;
326
328
  } catch {
327
329
  }
328
330
  }
329
- chunkUHXVYWTF_cjs.removeBrowserStorageItem(storageKey(address));
331
+ chunkFGWMLLEC_cjs.removeBrowserStorageItem(storageKey(address));
330
332
  }
331
333
  function useDeposit(options = {}) {
332
334
  const { address } = wagmi.useAccount();
333
- const { client, enabledTokens, getChainById: getChainById2, networkConfig, serviceAddress } = chunkUHXVYWTF_cjs.usePrivanaContext();
335
+ const { client, enabledTokens, getChainById: getChainById2, networkConfig, serviceAddress } = chunkFGWMLLEC_cjs.usePrivanaContext();
334
336
  const { data: walletClient } = wagmi.useWalletClient();
335
337
  const queryClient = reactQuery.useQueryClient();
336
338
  const config = wagmi.useConfig();
337
- const { executePrivateRead } = chunkUHXVYWTF_cjs.usePrivateReadRequest();
339
+ const { executePrivateRead, privateReadAddress } = chunkFGWMLLEC_cjs.usePrivateReadRequest();
340
+ const privateReadAddressRef = react.useRef(privateReadAddress);
341
+ privateReadAddressRef.current = privateReadAddress;
338
342
  const confirmations = options.confirmations ?? 15;
339
343
  const [depositAddress, setDepositAddress] = react.useState(null);
340
344
  const [txHash, setTxHash] = react.useState();
@@ -370,12 +374,12 @@ function useDeposit(options = {}) {
370
374
  ]);
371
375
  const pendingLockRef = react.useRef(null);
372
376
  const submitPendingLockAfterCredit = react.useCallback(
373
- async (signedLock, response) => {
377
+ async (signedLock, creditedAmount) => {
374
378
  try {
375
- const result = await chunkUHXVYWTF_cjs.submitPendingLock({
379
+ const result = await chunkFGWMLLEC_cjs.submitPendingLock({
376
380
  client,
377
381
  payload: signedLock,
378
- creditedAmount: response.amount != null ? BigInt(response.amount) : void 0
382
+ creditedAmount
379
383
  });
380
384
  queryClient.invalidateQueries({ queryKey: ["accounting-balance"] });
381
385
  queryClient.invalidateQueries({ queryKey: ["accounting-locked-funds"] });
@@ -383,11 +387,11 @@ function useDeposit(options = {}) {
383
387
  queryClient.invalidateQueries({ queryKey: ["accounting-history"] });
384
388
  onLockSubmittedRef.current?.(result);
385
389
  } catch (err) {
386
- const error2 = err instanceof chunkUHXVYWTF_cjs.PostDepositLockError ? err : new chunkUHXVYWTF_cjs.PostDepositLockError(
390
+ const error2 = err instanceof chunkFGWMLLEC_cjs.PostDepositLockError ? err : new chunkFGWMLLEC_cjs.PostDepositLockError(
387
391
  err instanceof Error ? err.message : "Lock submission failed",
388
392
  "submission-failed",
389
393
  BigInt(signedLock.amount),
390
- void 0,
394
+ creditedAmount,
391
395
  { cause: err }
392
396
  );
393
397
  (onLockFailedRef.current ?? onErrorRef.current)?.(error2);
@@ -402,15 +406,15 @@ function useDeposit(options = {}) {
402
406
  error: verificationError,
403
407
  verify,
404
408
  reset: resetVerification
405
- } = chunkUHXVYWTF_cjs.useDepositVerification({
409
+ } = chunkFGWMLLEC_cjs.useDepositVerification({
406
410
  pollInterval: options.pollInterval,
407
411
  pollTimeout: options.pollTimeout,
408
- onCredited: (hash, response) => {
412
+ onCredited: (hash, response, creditedAmount) => {
409
413
  verificationContextRef.current = null;
410
414
  const signedLock = pendingLockRef.current;
411
415
  pendingLockRef.current = null;
412
416
  if (signedLock) {
413
- void submitPendingLockAfterCredit(signedLock, response).finally(() => {
417
+ void submitPendingLockAfterCredit(signedLock, creditedAmount).finally(() => {
414
418
  if (address) clearPendingDeposit(address, hash);
415
419
  });
416
420
  } else if (address) {
@@ -428,7 +432,7 @@ function useDeposit(options = {}) {
428
432
  const addressMutation = reactQuery.useMutation({
429
433
  mutationFn: async () => {
430
434
  if (!address) throw new Error("No wallet connected");
431
- return executePrivateRead(() => client.getDepositAddress());
435
+ return executePrivateRead((readClient) => readClient.getDepositAddress());
432
436
  },
433
437
  onSuccess: (data) => {
434
438
  setDepositAddress(data);
@@ -452,7 +456,7 @@ function useDeposit(options = {}) {
452
456
  } = wagmi.useSendTransaction();
453
457
  const isSendingTx = isWritingContract || isSendingNative;
454
458
  const sendError = writeError ?? sendNativeError;
455
- const { ensureCorrectChain } = chunkUHXVYWTF_cjs.useEnsureCorrectChain();
459
+ const { ensureCorrectChain } = chunkFGWMLLEC_cjs.useEnsureCorrectChain();
456
460
  const invalidateGeneration = react.useCallback(() => {
457
461
  generationRef.current++;
458
462
  }, []);
@@ -500,16 +504,16 @@ function useDeposit(options = {}) {
500
504
  try {
501
505
  let confirmed = false;
502
506
  try {
503
- const receipt = await chunkUHXVYWTF_cjs.getTransactionReceipt(config, {
507
+ const receipt = await chunkFGWMLLEC_cjs.getTransactionReceipt(config, {
504
508
  hash,
505
509
  chainId: persisted.chainId
506
510
  });
507
- const blockNumber = await chunkUHXVYWTF_cjs.getBlockNumber(config, { chainId: persisted.chainId });
511
+ const blockNumber = await chunkFGWMLLEC_cjs.getBlockNumber(config, { chainId: persisted.chainId });
508
512
  confirmed = blockNumber - receipt.blockNumber + 1n >= BigInt(confirmations);
509
513
  } catch {
510
514
  }
511
515
  if (!confirmed) {
512
- await chunkUHXVYWTF_cjs.waitForTransactionReceipt(config, {
516
+ await chunkFGWMLLEC_cjs.waitForTransactionReceipt(config, {
513
517
  hash,
514
518
  chainId: persisted.chainId,
515
519
  confirmations
@@ -560,12 +564,13 @@ function useDeposit(options = {}) {
560
564
  `Amount is below the minimum deposit (${minAmountStr}) for ${isNative ? "native" : "ERC-20"} on chain ${sourceChain.id}`
561
565
  );
562
566
  }
563
- if (params.postDepositLock && !chunkUHXVYWTF_cjs.canUseBrowserStorage()) {
567
+ if (params.postDepositLock && !chunkFGWMLLEC_cjs.canUseBrowserStorage()) {
564
568
  throw new Error("Browser storage is required for locked deposit recovery");
565
569
  }
566
- const lockAmount = chunkUHXVYWTF_cjs.clampLockAmount(params.amount, params.postDepositLock?.maxAmount);
570
+ const lockAmount = chunkFGWMLLEC_cjs.clampLockAmount(params.amount, params.postDepositLock?.maxAmount);
567
571
  let signedLock;
568
572
  if (params.postDepositLock) {
573
+ const lockOwner = chunkFGWMLLEC_cjs.requireDepositLockOwner(address, privateReadAddress);
569
574
  setIsSwitchingChain(true);
570
575
  try {
571
576
  await ensureCorrectChain(networkConfig.chainId);
@@ -573,21 +578,24 @@ function useDeposit(options = {}) {
573
578
  if (!isStale()) setIsSwitchingChain(false);
574
579
  }
575
580
  if (isStale()) return;
576
- const signingWalletClient = await chunkUHXVYWTF_cjs.getWalletClient(config, {
581
+ const signingWalletClient = await chunkFGWMLLEC_cjs.getWalletClient(config, {
577
582
  chainId: networkConfig.chainId
578
583
  });
579
- signedLock = await chunkUHXVYWTF_cjs.createSignedLockRequest({
584
+ signedLock = await chunkFGWMLLEC_cjs.createSignedLockRequest({
580
585
  client,
581
586
  walletClient: signingWalletClient,
582
- userAddress: address,
587
+ userAddress: lockOwner,
583
588
  networkConfig,
584
- serviceAddress: requireServiceAddress(
589
+ serviceAddress: chunkFGWMLLEC_cjs.requireServiceAddress(
585
590
  params.postDepositLock.serviceAddress ?? serviceAddress
586
591
  ),
587
592
  tokenId: params.tokenId,
588
593
  amount: lockAmount,
589
594
  lockDuration: params.postDepositLock.lockDuration
590
595
  });
596
+ if (privateReadAddressRef.current?.toLowerCase() !== lockOwner.toLowerCase()) {
597
+ throw new Error("Authenticated deposit account changed while signing");
598
+ }
591
599
  }
592
600
  if (isStale()) return;
593
601
  setIsSwitchingChain(true);
@@ -632,7 +640,7 @@ function useDeposit(options = {}) {
632
640
  try {
633
641
  setIsWaitingForConfirmation(true);
634
642
  try {
635
- await chunkUHXVYWTF_cjs.waitForTransactionReceipt(config, {
643
+ await chunkFGWMLLEC_cjs.waitForTransactionReceipt(config, {
636
644
  hash,
637
645
  chainId: sourceChain.id,
638
646
  confirmations
@@ -670,6 +678,7 @@ function useDeposit(options = {}) {
670
678
  enabledTokens,
671
679
  ensureCorrectChain,
672
680
  networkConfig,
681
+ privateReadAddress,
673
682
  queryClient,
674
683
  serviceAddress,
675
684
  writeContractAsync,
@@ -706,29 +715,24 @@ function useDeposit(options = {}) {
706
715
  reset
707
716
  };
708
717
  }
709
- function requireServiceAddress(serviceAddress) {
710
- if (!serviceAddress) {
711
- throw new Error("Service address not configured");
712
- }
713
- return serviceAddress;
714
- }
715
718
  function useDepositAddress(options = {}) {
716
719
  const queryClient = react.useContext(reactQuery.QueryClientContext);
717
- const accountingContext = chunkUHXVYWTF_cjs.useSafePrivanaContext();
720
+ const accountingContext = chunkFGWMLLEC_cjs.useSafePrivanaContext();
718
721
  const hasProviders = !!queryClient && !!accountingContext;
719
722
  const client = accountingContext?.client;
720
- const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkUHXVYWTF_cjs.usePrivateReadRequest();
723
+ const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkFGWMLLEC_cjs.usePrivateReadRequest();
721
724
  const isReady = hasProviders && privateReadReady && !!privateReadAddress && !!client;
722
725
  const query = reactQuery.useQuery({
723
726
  queryKey: ["accounting-deposit-address", ...privateReadQueryScope],
724
727
  queryFn: async () => {
725
728
  if (!privateReadAddress) throw new Error("No authenticated account available");
726
729
  if (!client) throw new Error("No accounting client");
727
- return executePrivateRead(() => client.getDepositAddress());
730
+ return executePrivateRead((readClient) => readClient.getDepositAddress());
728
731
  },
729
732
  enabled: isReady && (options.enabled ?? true)
730
733
  });
731
734
  return {
735
+ response: query.data,
732
736
  depositAddress: query.data?.deposit_address ?? null,
733
737
  isReady,
734
738
  isLoading: query.isLoading,
@@ -740,9 +744,9 @@ function useDepositAddress(options = {}) {
740
744
  function useWithdraw(options = {}) {
741
745
  const { address } = wagmi.useAccount();
742
746
  const { data: walletClient } = wagmi.useWalletClient();
743
- const { client, networkConfig } = chunkUHXVYWTF_cjs.usePrivanaContext();
747
+ const { client, networkConfig } = chunkFGWMLLEC_cjs.usePrivanaContext();
744
748
  const queryClient = reactQuery.useQueryClient();
745
- const { chainId, ensureCorrectChain } = chunkUHXVYWTF_cjs.useEnsureCorrectChain();
749
+ const { chainId, ensureCorrectChain } = chunkFGWMLLEC_cjs.useEnsureCorrectChain();
746
750
  const pollInterval = options.pollInterval ?? 3e3;
747
751
  const pollTimeout = options.pollTimeout ?? 18e4;
748
752
  const [currentStep, setCurrentStep] = react.useState("idle");
@@ -810,7 +814,7 @@ function useWithdraw(options = {}) {
810
814
  if (isStale()) return void 0;
811
815
  const nonce = BigInt(nonceResponse.nonce);
812
816
  setCurrentStep("signing");
813
- const signature = await chunkUHXVYWTF_cjs.signWithdrawMessage({
817
+ const signature = await chunkFGWMLLEC_cjs.signWithdrawMessage({
814
818
  walletClient,
815
819
  chainId: signingChainId,
816
820
  verifyingContract: networkConfig.accountingContract,
@@ -939,7 +943,7 @@ function useWithdraw(options = {}) {
939
943
  function useLockFunds(options = {}) {
940
944
  const { address } = wagmi.useAccount();
941
945
  const { data: walletClient } = wagmi.useWalletClient();
942
- const { client, networkConfig, serviceAddress } = chunkUHXVYWTF_cjs.usePrivanaContext();
946
+ const { client, networkConfig, serviceAddress } = chunkFGWMLLEC_cjs.usePrivanaContext();
943
947
  const queryClient = reactQuery.useQueryClient();
944
948
  const mutation = reactQuery.useMutation({
945
949
  mutationFn: async (params) => {
@@ -950,7 +954,7 @@ function useLockFunds(options = {}) {
950
954
  throw new Error("Service address not configured");
951
955
  }
952
956
  const { nonce } = await client.getLockNonce(address);
953
- const signature = await chunkUHXVYWTF_cjs.signLockMessage({
957
+ const signature = await chunkFGWMLLEC_cjs.signLockMessage({
954
958
  walletClient,
955
959
  chainId: networkConfig.chainId,
956
960
  verifyingContract: networkConfig.accountingContract,
@@ -998,7 +1002,7 @@ function useLockFunds(options = {}) {
998
1002
  }
999
1003
  function useUnlockFunds(options = {}) {
1000
1004
  const { address } = wagmi.useAccount();
1001
- const { client } = chunkUHXVYWTF_cjs.usePrivanaContext();
1005
+ const { client } = chunkFGWMLLEC_cjs.usePrivanaContext();
1002
1006
  const queryClient = reactQuery.useQueryClient();
1003
1007
  const unlockMutation = reactQuery.useMutation({
1004
1008
  mutationFn: async (params) => {
@@ -1068,7 +1072,7 @@ function useUnlockFunds(options = {}) {
1068
1072
  function useTransfer(options = {}) {
1069
1073
  const { address } = wagmi.useAccount();
1070
1074
  const { data: walletClient } = wagmi.useWalletClient();
1071
- const { client, networkConfig, serviceAddress } = chunkUHXVYWTF_cjs.usePrivanaContext();
1075
+ const { client, networkConfig, serviceAddress } = chunkFGWMLLEC_cjs.usePrivanaContext();
1072
1076
  const queryClient = reactQuery.useQueryClient();
1073
1077
  const transferMutation = reactQuery.useMutation({
1074
1078
  mutationFn: async (params) => {
@@ -1076,7 +1080,7 @@ function useTransfer(options = {}) {
1076
1080
  throw new Error("Wallet not connected");
1077
1081
  }
1078
1082
  const { nonce } = await client.getTransferNonce(address);
1079
- const signature = await chunkUHXVYWTF_cjs.signTransferMessage({
1083
+ const signature = await chunkFGWMLLEC_cjs.signTransferMessage({
1080
1084
  walletClient,
1081
1085
  chainId: networkConfig.chainId,
1082
1086
  verifyingContract: networkConfig.accountingContract,
@@ -1113,7 +1117,7 @@ function useTransfer(options = {}) {
1113
1117
  throw new Error("Service address not configured");
1114
1118
  }
1115
1119
  const { nonce } = await client.getTransferLockedNonce(serviceAddress);
1116
- const signature = await chunkUHXVYWTF_cjs.signTransferLockedMessage({
1120
+ const signature = await chunkFGWMLLEC_cjs.signTransferLockedMessage({
1117
1121
  walletClient,
1118
1122
  chainId: networkConfig.chainId,
1119
1123
  verifyingContract: networkConfig.accountingContract,
@@ -1173,13 +1177,13 @@ function useTransfer(options = {}) {
1173
1177
  };
1174
1178
  }
1175
1179
  function useLockedFunds(options = {}) {
1176
- const { client, pollingInterval, serviceAddress } = chunkUHXVYWTF_cjs.usePrivanaContext();
1177
- const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkUHXVYWTF_cjs.usePrivateReadRequest();
1180
+ const { client, pollingInterval, serviceAddress } = chunkFGWMLLEC_cjs.usePrivanaContext();
1181
+ const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkFGWMLLEC_cjs.usePrivateReadRequest();
1178
1182
  const query = reactQuery.useQuery({
1179
1183
  queryKey: ["accounting-locked-funds", ...privateReadQueryScope, serviceAddress ?? null],
1180
1184
  queryFn: async () => {
1181
1185
  if (!privateReadAddress) throw new Error("No authenticated account available");
1182
- return executePrivateRead(() => client.getLockedFunds(serviceAddress));
1186
+ return executePrivateRead((readClient) => readClient.getLockedFunds(serviceAddress));
1183
1187
  },
1184
1188
  enabled: (options.enabled ?? true) && privateReadReady && !!privateReadAddress && !!client,
1185
1189
  refetchInterval: pollingInterval,
@@ -1196,15 +1200,15 @@ function useLockedFunds(options = {}) {
1196
1200
  };
1197
1201
  }
1198
1202
  function useTotalLockedBalance(options = {}) {
1199
- const { client, pollingInterval, defaultToken } = chunkUHXVYWTF_cjs.usePrivanaContext();
1200
- const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkUHXVYWTF_cjs.usePrivateReadRequest();
1203
+ const { client, pollingInterval, defaultToken } = chunkFGWMLLEC_cjs.usePrivanaContext();
1204
+ const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkFGWMLLEC_cjs.usePrivateReadRequest();
1201
1205
  const tokenId = options.tokenId ?? defaultToken?.id;
1202
1206
  const query = reactQuery.useQuery({
1203
1207
  queryKey: ["accounting-total-locked-balance", ...privateReadQueryScope, tokenId],
1204
1208
  queryFn: async () => {
1205
1209
  if (!privateReadAddress) throw new Error("No authenticated account available");
1206
1210
  if (!tokenId) throw new Error("No token ID provided");
1207
- return executePrivateRead(() => client.getTotalLockedBalance(tokenId));
1211
+ return executePrivateRead((readClient) => readClient.getTotalLockedBalance(tokenId));
1208
1212
  },
1209
1213
  enabled: (options.enabled ?? true) && privateReadReady && !!privateReadAddress && !!tokenId && !!client,
1210
1214
  refetchInterval: pollingInterval
@@ -1218,13 +1222,13 @@ function useTotalLockedBalance(options = {}) {
1218
1222
  };
1219
1223
  }
1220
1224
  function useExpiredLocks(options = {}) {
1221
- const { client, pollingInterval } = chunkUHXVYWTF_cjs.usePrivanaContext();
1222
- const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkUHXVYWTF_cjs.usePrivateReadRequest();
1225
+ const { client, pollingInterval } = chunkFGWMLLEC_cjs.usePrivanaContext();
1226
+ const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkFGWMLLEC_cjs.usePrivateReadRequest();
1223
1227
  const query = reactQuery.useQuery({
1224
1228
  queryKey: ["accounting-expired-locks", ...privateReadQueryScope],
1225
1229
  queryFn: async () => {
1226
1230
  if (!privateReadAddress) throw new Error("No authenticated account available");
1227
- return executePrivateRead(() => client.getExpiredLocks());
1231
+ return executePrivateRead((readClient) => readClient.getExpiredLocks());
1228
1232
  },
1229
1233
  enabled: (options.enabled ?? true) && privateReadReady && !!privateReadAddress && !!client,
1230
1234
  refetchInterval: pollingInterval
@@ -1240,14 +1244,14 @@ function useExpiredLocks(options = {}) {
1240
1244
  };
1241
1245
  }
1242
1246
  function statusCodeOf(error) {
1243
- return error instanceof chunkUHXVYWTF_cjs.AccountingApiError ? error.statusCode : void 0;
1247
+ return error instanceof chunkFGWMLLEC_cjs.AccountingApiError ? error.statusCode : void 0;
1244
1248
  }
1245
1249
  function usePendingDeposits(options = {}) {
1246
1250
  const queryClient = react.useContext(reactQuery.QueryClientContext);
1247
- const accountingContext = chunkUHXVYWTF_cjs.useSafePrivanaContext();
1251
+ const accountingContext = chunkFGWMLLEC_cjs.useSafePrivanaContext();
1248
1252
  const hasProviders = !!queryClient && !!accountingContext;
1249
1253
  const client = accountingContext?.client;
1250
- const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkUHXVYWTF_cjs.usePrivateReadRequest();
1254
+ const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkFGWMLLEC_cjs.usePrivateReadRequest();
1251
1255
  const { chainId, tokenAddress, lookbackBlocks } = options;
1252
1256
  const query = reactQuery.useQuery({
1253
1257
  queryKey: ["accounting-pending-deposits", ...privateReadQueryScope, chainId, tokenAddress],
@@ -1257,7 +1261,7 @@ function usePendingDeposits(options = {}) {
1257
1261
  if (!client) throw new Error("No accounting client");
1258
1262
  try {
1259
1263
  return await executePrivateRead(
1260
- () => client.getPendingDeposits({
1264
+ (readClient) => readClient.getPendingDeposits({
1261
1265
  chain_id: chainId,
1262
1266
  token_address: tokenAddress,
1263
1267
  lookback_blocks: lookbackBlocks
@@ -1294,7 +1298,7 @@ function usePendingDeposits(options = {}) {
1294
1298
  }
1295
1299
  function usePendingWithdrawals(options = {}) {
1296
1300
  const { address, isConnected } = wagmi.useAccount();
1297
- const { client, pollingInterval } = chunkUHXVYWTF_cjs.usePrivanaContext();
1301
+ const { client, pollingInterval } = chunkFGWMLLEC_cjs.usePrivanaContext();
1298
1302
  const query = reactQuery.useQuery({
1299
1303
  queryKey: ["accounting-pending-withdrawals", address],
1300
1304
  queryFn: async () => {
@@ -1330,15 +1334,15 @@ function usePendingWithdrawals(options = {}) {
1330
1334
  };
1331
1335
  }
1332
1336
  function useHistory(options = {}) {
1333
- const { client, pollingInterval } = chunkUHXVYWTF_cjs.usePrivanaContext();
1334
- const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkUHXVYWTF_cjs.usePrivateReadRequest();
1337
+ const { client, pollingInterval } = chunkFGWMLLEC_cjs.usePrivanaContext();
1338
+ const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = chunkFGWMLLEC_cjs.usePrivateReadRequest();
1335
1339
  const offset = options.offset ?? -1;
1336
1340
  const limit = options.limit ?? 50;
1337
1341
  const query = reactQuery.useQuery({
1338
1342
  queryKey: ["accounting-history", ...privateReadQueryScope, offset, limit],
1339
1343
  queryFn: async () => {
1340
1344
  if (!privateReadAddress) throw new Error("No authenticated account available");
1341
- return executePrivateRead(() => client.getHistory({ offset, limit }));
1345
+ return executePrivateRead((readClient) => readClient.getHistory({ offset, limit }));
1342
1346
  },
1343
1347
  enabled: (options.enabled ?? true) && privateReadReady && !!privateReadAddress && !!client,
1344
1348
  refetchInterval: pollingInterval,
@@ -1355,7 +1359,7 @@ function useHistory(options = {}) {
1355
1359
  };
1356
1360
  }
1357
1361
  function useTokenInfo(options = {}) {
1358
- const { client } = chunkUHXVYWTF_cjs.usePrivanaContext();
1362
+ const { client } = chunkFGWMLLEC_cjs.usePrivanaContext();
1359
1363
  const { tokenId } = options;
1360
1364
  const query = reactQuery.useQuery({
1361
1365
  queryKey: ["accounting-token-info", tokenId],
@@ -1375,7 +1379,7 @@ function useTokenInfo(options = {}) {
1375
1379
  };
1376
1380
  }
1377
1381
  function useTokenList(options = {}) {
1378
- const { client } = chunkUHXVYWTF_cjs.usePrivanaContext();
1382
+ const { client } = chunkFGWMLLEC_cjs.usePrivanaContext();
1379
1383
  const query = reactQuery.useQuery({
1380
1384
  queryKey: ["accounting-token-list"],
1381
1385
  queryFn: () => client.listTokens(),
@@ -1393,7 +1397,7 @@ function useTokenList(options = {}) {
1393
1397
  function useModifyLock(options = {}) {
1394
1398
  const { address } = wagmi.useAccount();
1395
1399
  const { data: walletClient } = wagmi.useWalletClient();
1396
- const { client, networkConfig } = chunkUHXVYWTF_cjs.usePrivanaContext();
1400
+ const { client, networkConfig } = chunkFGWMLLEC_cjs.usePrivanaContext();
1397
1401
  const queryClient = reactQuery.useQueryClient();
1398
1402
  const mutation = reactQuery.useMutation({
1399
1403
  mutationFn: async (params) => {
@@ -1401,7 +1405,7 @@ function useModifyLock(options = {}) {
1401
1405
  throw new Error("Wallet not connected");
1402
1406
  }
1403
1407
  const { nonce } = await client.getModifyLockNonce(address);
1404
- const signature = await chunkUHXVYWTF_cjs.signModifyLockMessage({
1408
+ const signature = await chunkFGWMLLEC_cjs.signModifyLockMessage({
1405
1409
  walletClient,
1406
1410
  chainId: networkConfig.chainId,
1407
1411
  verifyingContract: networkConfig.accountingContract,
@@ -1460,7 +1464,7 @@ function DialogOverlay({
1460
1464
  {
1461
1465
  "data-slot": "dialog-overlay",
1462
1466
  "data-privana": true,
1463
- className: chunkUHXVYWTF_cjs.cn(
1467
+ className: chunkFGWMLLEC_cjs.cn(
1464
1468
  "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
1465
1469
  className
1466
1470
  ),
@@ -1482,7 +1486,7 @@ function DialogContent({
1482
1486
  {
1483
1487
  "data-slot": "dialog-content",
1484
1488
  "data-privana": true,
1485
- className: chunkUHXVYWTF_cjs.cn(
1489
+ className: chunkFGWMLLEC_cjs.cn(
1486
1490
  "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
1487
1491
  className
1488
1492
  ),
@@ -1505,22 +1509,12 @@ function DialogContent({
1505
1509
  )
1506
1510
  ] });
1507
1511
  }
1508
- function DialogHeader({ className, ...props }) {
1509
- return /* @__PURE__ */ jsxRuntime.jsx(
1510
- "div",
1511
- {
1512
- "data-slot": "dialog-header",
1513
- className: chunkUHXVYWTF_cjs.cn("flex flex-col gap-2 text-center sm:text-left", className),
1514
- ...props
1515
- }
1516
- );
1517
- }
1518
1512
  function DialogTitle({ className, ...props }) {
1519
1513
  return /* @__PURE__ */ jsxRuntime.jsx(
1520
1514
  DialogPrimitive__namespace.Title,
1521
1515
  {
1522
1516
  "data-slot": "dialog-title",
1523
- className: chunkUHXVYWTF_cjs.cn("text-lg leading-none font-semibold", className),
1517
+ className: chunkFGWMLLEC_cjs.cn("text-lg leading-none font-semibold", className),
1524
1518
  ...props
1525
1519
  }
1526
1520
  );
@@ -1533,11 +1527,750 @@ function DialogDescription({
1533
1527
  DialogPrimitive__namespace.Description,
1534
1528
  {
1535
1529
  "data-slot": "dialog-description",
1536
- className: chunkUHXVYWTF_cjs.cn("text-muted-foreground text-sm", className),
1530
+ className: chunkFGWMLLEC_cjs.cn("text-muted-foreground text-sm", className),
1537
1531
  ...props
1538
1532
  }
1539
1533
  );
1540
1534
  }
1535
+
1536
+ // src/sdk/hooks/external-deposit-lock.ts
1537
+ var ACTIVE_SESSION_PREFIX = "privana:external-deposit-lock:active:";
1538
+ var SESSION_PREFIX = "privana:external-deposit-lock:session:";
1539
+ var ExternalDepositLockSessionChangedError = class _ExternalDepositLockSessionChangedError extends Error {
1540
+ constructor() {
1541
+ super("External deposit lock session changed");
1542
+ this.name = "ExternalDepositLockSessionChangedError";
1543
+ Object.setPrototypeOf(this, _ExternalDepositLockSessionChangedError.prototype);
1544
+ }
1545
+ };
1546
+ function externalDepositSessionId(chainId, tokenId) {
1547
+ return `${chainId}:${tokenId.toLowerCase()}`;
1548
+ }
1549
+ function isExternalDepositBlockInSession(session, blockNumber) {
1550
+ return Number.isSafeInteger(blockNumber) && blockNumber > session.startBlock;
1551
+ }
1552
+ function isCurrentExternalDepositVerification(session, txHash) {
1553
+ return session.creditedAmount === void 0 && session.verification?.hash.toLowerCase() === txHash.toLowerCase();
1554
+ }
1555
+ function getExternalDepositMinimum(response, chainId) {
1556
+ const value = response?.min_deposit?.[String(chainId)]?.erc20;
1557
+ if (value === void 0) return void 0;
1558
+ try {
1559
+ const amount = BigInt(value);
1560
+ return amount >= 0n ? amount : void 0;
1561
+ } catch {
1562
+ return void 0;
1563
+ }
1564
+ }
1565
+ function activeSessionKey(owner) {
1566
+ return `${ACTIVE_SESSION_PREFIX}${owner.toLowerCase()}`;
1567
+ }
1568
+ function sessionKey(owner, sessionId) {
1569
+ return `${SESSION_PREFIX}${owner.toLowerCase()}:${sessionId}`;
1570
+ }
1571
+ function activeSessionId(owner) {
1572
+ const value = chunkFGWMLLEC_cjs.getSharedBrowserStorageItem(activeSessionKey(owner));
1573
+ return value || void 0;
1574
+ }
1575
+ function isPositiveIntegerString(value) {
1576
+ if (typeof value !== "string") return false;
1577
+ try {
1578
+ return BigInt(value) > 0n;
1579
+ } catch {
1580
+ return false;
1581
+ }
1582
+ }
1583
+ function isSessionRecord(value) {
1584
+ if (!value || typeof value !== "object") return false;
1585
+ const record = value;
1586
+ if (record.version !== 1 || typeof record.owner !== "string" || typeof record.serviceAddress !== "string" || !Number.isInteger(record.chainId) || (record.chainId ?? 0) <= 0 || typeof record.tokenId !== "string" || !Number.isSafeInteger(record.startBlock) || (record.startBlock ?? -1) < 0 || !isPositiveIntegerString(record.depositAmount) || !isPositiveIntegerString(record.maxLockAmount) || !Number.isInteger(record.lockDuration) || (record.lockDuration ?? 0) <= 0 || typeof record.generation !== "string" || !record.generation || record.submissionAmbiguous !== void 0 && typeof record.submissionAmbiguous !== "boolean" || record.creditedAmount !== void 0 && !isPositiveIntegerString(record.creditedAmount)) {
1587
+ return false;
1588
+ }
1589
+ if (record.verification && (typeof record.verification.hash !== "string" || record.verification.chainId !== record.chainId || !isPositiveIntegerString(record.verification.amount) || record.verification.logIndex !== void 0 && (!Number.isInteger(record.verification.logIndex) || record.verification.logIndex < 0))) {
1590
+ return false;
1591
+ }
1592
+ if (record.verification && record.creditedAmount !== void 0) return false;
1593
+ if (record.submissionAmbiguous && record.creditedAmount === void 0) return false;
1594
+ if (!record.payload) {
1595
+ return record.creditedAmount !== void 0 && !record.submissionAmbiguous;
1596
+ }
1597
+ if (typeof record.payload.signature !== "string" || typeof record.payload.token_id !== "string" || typeof record.payload.service_address !== "string" || record.payload.signature !== record.generation || record.payload.token_id.toLowerCase() !== record.tokenId.toLowerCase() || record.payload.service_address.toLowerCase() !== record.serviceAddress.toLowerCase() || !isPositiveIntegerString(record.payload.amount)) {
1598
+ return false;
1599
+ }
1600
+ return BigInt(record.payload.amount) <= BigInt(record.maxLockAmount);
1601
+ }
1602
+ function writeSessionRecord(session) {
1603
+ const id = externalDepositSessionId(session.chainId, session.tokenId);
1604
+ return chunkFGWMLLEC_cjs.setSharedBrowserStorageItem(sessionKey(session.owner, id), JSON.stringify(session));
1605
+ }
1606
+ function saveExternalDepositLockSession(session, expectedSession = null) {
1607
+ if (!isSessionRecord(session)) throw new Error("Invalid external deposit lock session");
1608
+ const current = loadExternalDepositLockSession(session.owner);
1609
+ if (expectedSession === null && current || expectedSession !== null && (!current || !isSameSessionSnapshot(current, expectedSession))) {
1610
+ throw new ExternalDepositLockSessionChangedError();
1611
+ }
1612
+ const nextId = externalDepositSessionId(session.chainId, session.tokenId);
1613
+ const previousId = activeSessionId(session.owner);
1614
+ if (!writeSessionRecord(session)) {
1615
+ throw new Error("Unable to persist external deposit lock session");
1616
+ }
1617
+ if (previousId !== nextId) {
1618
+ if (!chunkFGWMLLEC_cjs.setSharedBrowserStorageItem(activeSessionKey(session.owner), nextId)) {
1619
+ chunkFGWMLLEC_cjs.removeSharedBrowserStorageItem(sessionKey(session.owner, nextId));
1620
+ throw new Error("Unable to persist external deposit lock session");
1621
+ }
1622
+ if (previousId) {
1623
+ chunkFGWMLLEC_cjs.removeSharedBrowserStorageItem(sessionKey(session.owner, previousId));
1624
+ }
1625
+ }
1626
+ }
1627
+ function loadExternalDepositLockSession(owner) {
1628
+ const id = activeSessionId(owner);
1629
+ if (!id) return void 0;
1630
+ const key = sessionKey(owner, id);
1631
+ try {
1632
+ const raw = chunkFGWMLLEC_cjs.getSharedBrowserStorageItem(key);
1633
+ const parsed = raw ? JSON.parse(raw) : void 0;
1634
+ if (!isSessionRecord(parsed) || parsed.owner.toLowerCase() !== owner.toLowerCase() || externalDepositSessionId(parsed.chainId, parsed.tokenId) !== id) {
1635
+ chunkFGWMLLEC_cjs.removeSharedBrowserStorageItem(key);
1636
+ chunkFGWMLLEC_cjs.removeSharedBrowserStorageItem(activeSessionKey(owner));
1637
+ return void 0;
1638
+ }
1639
+ return parsed;
1640
+ } catch {
1641
+ chunkFGWMLLEC_cjs.removeSharedBrowserStorageItem(key);
1642
+ chunkFGWMLLEC_cjs.removeSharedBrowserStorageItem(activeSessionKey(owner));
1643
+ return void 0;
1644
+ }
1645
+ }
1646
+ function subscribeExternalDepositLockSession(owner, onChange) {
1647
+ if (typeof window === "undefined") return () => void 0;
1648
+ let localStorage;
1649
+ try {
1650
+ localStorage = window.localStorage;
1651
+ } catch {
1652
+ return () => void 0;
1653
+ }
1654
+ const activeKey = activeSessionKey(owner);
1655
+ const ownerSessionPrefix = `${SESSION_PREFIX}${owner.toLowerCase()}:`;
1656
+ const handleStorage = (event) => {
1657
+ if (event.storageArea !== localStorage) return;
1658
+ if (event.key !== null && event.key !== activeKey && !event.key.startsWith(ownerSessionPrefix)) {
1659
+ return;
1660
+ }
1661
+ onChange(loadExternalDepositLockSession(owner));
1662
+ };
1663
+ window.addEventListener("storage", handleStorage);
1664
+ return () => window.removeEventListener("storage", handleStorage);
1665
+ }
1666
+ function clearExternalDepositLockSession(owner, expectedSessionId, expectedGeneration) {
1667
+ const id = activeSessionId(owner);
1668
+ if (!id || expectedSessionId && id !== expectedSessionId) return;
1669
+ if (expectedGeneration) {
1670
+ const current = loadExternalDepositLockSession(owner);
1671
+ if (!current || current.generation !== expectedGeneration) return;
1672
+ }
1673
+ chunkFGWMLLEC_cjs.removeSharedBrowserStorageItem(sessionKey(owner, id));
1674
+ chunkFGWMLLEC_cjs.removeSharedBrowserStorageItem(activeSessionKey(owner));
1675
+ }
1676
+ function isSameVerification(left, right) {
1677
+ if (!left || !right) return left === right;
1678
+ return left.hash.toLowerCase() === right.hash.toLowerCase() && left.chainId === right.chainId && left.amount === right.amount && (left.logIndex ?? 0) === (right.logIndex ?? 0);
1679
+ }
1680
+ function isSamePayload(left, right) {
1681
+ if (!left || !right) return left === right;
1682
+ return left.service_address.toLowerCase() === right.service_address.toLowerCase() && left.token_id.toLowerCase() === right.token_id.toLowerCase() && left.amount === right.amount && left.expiry === right.expiry && left.nonce === right.nonce && left.signature === right.signature;
1683
+ }
1684
+ function isSameSessionSnapshot(left, right) {
1685
+ return left.version === right.version && left.owner.toLowerCase() === right.owner.toLowerCase() && left.serviceAddress.toLowerCase() === right.serviceAddress.toLowerCase() && left.chainId === right.chainId && left.tokenId.toLowerCase() === right.tokenId.toLowerCase() && left.startBlock === right.startBlock && left.depositAmount === right.depositAmount && left.maxLockAmount === right.maxLockAmount && left.lockDuration === right.lockDuration && left.generation === right.generation && left.creditedAmount === right.creditedAmount && left.submissionAmbiguous === right.submissionAmbiguous && isSameVerification(left.verification, right.verification) && isSamePayload(left.payload, right.payload);
1686
+ }
1687
+ function isSameExternalDepositLockSession(left, right) {
1688
+ return isSameSessionSnapshot(left, right);
1689
+ }
1690
+ function clearExternalDepositVerification(session) {
1691
+ if (!session.verification || session.creditedAmount) return void 0;
1692
+ const current = loadExternalDepositLockSession(session.owner);
1693
+ if (!current || current.generation !== session.generation || current.creditedAmount || !isSameVerification(current.verification, session.verification)) {
1694
+ return void 0;
1695
+ }
1696
+ const next = { ...current, verification: void 0 };
1697
+ if (!writeSessionRecord(next)) {
1698
+ throw new Error("Unable to clear failed deposit verification");
1699
+ }
1700
+ return next;
1701
+ }
1702
+ function discardExternalDepositLockSession(session) {
1703
+ const current = loadExternalDepositLockSession(session.owner);
1704
+ if (!current) return true;
1705
+ if (!isSameSessionSnapshot(current, session)) return false;
1706
+ clearExternalDepositLockSession(
1707
+ current.owner,
1708
+ externalDepositSessionId(current.chainId, current.tokenId),
1709
+ current.generation
1710
+ );
1711
+ return loadExternalDepositLockSession(current.owner) === void 0;
1712
+ }
1713
+ function clearSubmittedPayload(session, signature, clearAmbiguous = false) {
1714
+ const current = loadExternalDepositLockSession(session.owner);
1715
+ if (!current?.payload || current.payload.signature !== signature || current.submissionAmbiguous && !clearAmbiguous) {
1716
+ return false;
1717
+ }
1718
+ return writeSessionRecord({ ...current, submissionAmbiguous: void 0, payload: void 0 });
1719
+ }
1720
+ function markSubmissionAmbiguous(session, signature) {
1721
+ const current = loadExternalDepositLockSession(session.owner);
1722
+ if (!current?.payload || current.payload.signature !== signature) return false;
1723
+ if (current.submissionAmbiguous) return true;
1724
+ return writeSessionRecord({ ...current, submissionAmbiguous: true });
1725
+ }
1726
+ function ambiguousSubmissionError(error) {
1727
+ return new chunkFGWMLLEC_cjs.PostDepositLockError(
1728
+ "Lock submission could not be confirmed. Retry only the saved signature, or check locked funds before stopping recovery.",
1729
+ error.reason,
1730
+ error.signedAmount,
1731
+ error.creditedAmount,
1732
+ {
1733
+ cause: error.cause,
1734
+ submissionMayHaveSucceeded: true
1735
+ }
1736
+ );
1737
+ }
1738
+ function isDefinitiveSubmissionFailure(error) {
1739
+ const cause = error.cause;
1740
+ return cause instanceof chunkFGWMLLEC_cjs.AccountingApiError && cause.statusCode !== 408 && cause.statusCode < 500;
1741
+ }
1742
+ function submissionLockName(session) {
1743
+ return `privana:external-deposit-lock:submit:${session.owner.toLowerCase()}:${externalDepositSessionId(session.chainId, session.tokenId)}`;
1744
+ }
1745
+ async function withSubmissionLock(session, task) {
1746
+ const locks = typeof navigator === "undefined" ? void 0 : navigator.locks;
1747
+ if (!locks) return task(false);
1748
+ return locks.request(submissionLockName(session), () => task(true));
1749
+ }
1750
+ function externalDepositRetryAmount(session) {
1751
+ if (!session.creditedAmount) throw new Error("No credited external deposit to recover");
1752
+ const creditedAmount = BigInt(session.creditedAmount);
1753
+ const maxLockAmount = BigInt(session.maxLockAmount);
1754
+ return creditedAmount < maxLockAmount ? creditedAmount : maxLockAmount;
1755
+ }
1756
+ async function submitExternalDepositLock(client, session) {
1757
+ return withSubmissionLock(session, async (crossTabExclusive) => {
1758
+ const current = loadExternalDepositLockSession(session.owner);
1759
+ if (!current || current.generation !== session.generation) {
1760
+ throw new chunkFGWMLLEC_cjs.PostDepositLockError(
1761
+ "External deposit lock session changed before submission",
1762
+ "not-found",
1763
+ BigInt(session.maxLockAmount),
1764
+ session.creditedAmount ? BigInt(session.creditedAmount) : void 0
1765
+ );
1766
+ }
1767
+ const result = await submitExternalDepositLockAttempt(client, current, crossTabExclusive);
1768
+ clearExternalDepositLockSession(
1769
+ current.owner,
1770
+ externalDepositSessionId(current.chainId, current.tokenId),
1771
+ current.generation
1772
+ );
1773
+ return result;
1774
+ });
1775
+ }
1776
+ async function submitExternalDepositLockAttempt(client, session, crossTabExclusive) {
1777
+ const creditedAmount = session.creditedAmount ? BigInt(session.creditedAmount) : void 0;
1778
+ if (!creditedAmount) {
1779
+ throw new chunkFGWMLLEC_cjs.PostDepositLockError(
1780
+ "External deposit has not been credited",
1781
+ "submission-failed",
1782
+ BigInt(session.maxLockAmount)
1783
+ );
1784
+ }
1785
+ const payload = session.payload;
1786
+ if (!payload) {
1787
+ throw new chunkFGWMLLEC_cjs.PostDepositLockError(
1788
+ "No persisted signed policy found for this deposit session",
1789
+ "not-found",
1790
+ BigInt(session.maxLockAmount),
1791
+ creditedAmount
1792
+ );
1793
+ }
1794
+ try {
1795
+ return await chunkFGWMLLEC_cjs.submitPendingLock({
1796
+ client,
1797
+ payload,
1798
+ creditedAmount,
1799
+ beforeSubmit: () => {
1800
+ if (!markSubmissionAmbiguous(session, payload.signature)) {
1801
+ throw new Error("Unable to persist lock submission recovery state");
1802
+ }
1803
+ }
1804
+ });
1805
+ } catch (err) {
1806
+ if (err instanceof chunkFGWMLLEC_cjs.PostDepositLockError && err.reason === "submission-failed" && crossTabExclusive && !session.submissionAmbiguous && isDefinitiveSubmissionFailure(err)) {
1807
+ if (!clearSubmittedPayload(session, payload.signature, true)) {
1808
+ const latest = loadExternalDepositLockSession(session.owner);
1809
+ if (latest?.submissionAmbiguous) throw ambiguousSubmissionError(err);
1810
+ }
1811
+ } else if (err instanceof chunkFGWMLLEC_cjs.PostDepositLockError && err.reason === "submission-failed") {
1812
+ const ambiguous = markSubmissionAmbiguous(session, payload.signature) || loadExternalDepositLockSession(session.owner)?.submissionAmbiguous === true;
1813
+ if (ambiguous) throw ambiguousSubmissionError(err);
1814
+ } else {
1815
+ const current = loadExternalDepositLockSession(session.owner);
1816
+ if (session.submissionAmbiguous || current?.submissionAmbiguous) {
1817
+ if (err instanceof chunkFGWMLLEC_cjs.PostDepositLockError) throw ambiguousSubmissionError(err);
1818
+ throw err;
1819
+ }
1820
+ if (!clearSubmittedPayload(session, payload.signature)) {
1821
+ const latest = loadExternalDepositLockSession(session.owner);
1822
+ if (latest?.submissionAmbiguous && err instanceof chunkFGWMLLEC_cjs.PostDepositLockError) {
1823
+ throw ambiguousSubmissionError(err);
1824
+ }
1825
+ }
1826
+ }
1827
+ throw err;
1828
+ }
1829
+ }
1830
+ function useExternalDepositLock({
1831
+ allowance,
1832
+ onLockSubmitted,
1833
+ onLockFailed
1834
+ }) {
1835
+ const { client, networkConfig, serviceAddress, getTokenById, tokensStatus } = chunkFGWMLLEC_cjs.usePrivanaContext();
1836
+ const config = wagmi.useConfig();
1837
+ const queryClient = reactQuery.useQueryClient();
1838
+ const { address } = wagmi.useAccount();
1839
+ const { privateReadAddress } = chunkFGWMLLEC_cjs.usePrivateReadRequest();
1840
+ const { ensureCorrectChain } = chunkFGWMLLEC_cjs.useEnsureCorrectChain();
1841
+ const [isSigning, setIsSigning] = react.useState(false);
1842
+ const [isSubmittingLock, setIsSubmittingLock] = react.useState(false);
1843
+ const [session, setSession] = react.useState(null);
1844
+ const sessionRef = react.useRef(null);
1845
+ const signingRef = react.useRef(false);
1846
+ const settlingRef = react.useRef(false);
1847
+ const pendingCreditedTransitionRef = react.useRef(null);
1848
+ const hydratedScopeRef = react.useRef(null);
1849
+ const beneficiaryRef = react.useRef(privateReadAddress);
1850
+ beneficiaryRef.current = privateReadAddress;
1851
+ const onLockSubmittedRef = react.useRef(onLockSubmitted);
1852
+ const onLockFailedRef = react.useRef(onLockFailed);
1853
+ react.useEffect(() => {
1854
+ onLockSubmittedRef.current = onLockSubmitted;
1855
+ onLockFailedRef.current = onLockFailed;
1856
+ }, [onLockSubmitted, onLockFailed]);
1857
+ const installSession = react.useCallback((next) => {
1858
+ sessionRef.current = next;
1859
+ setSession(next);
1860
+ }, []);
1861
+ const preserveCreditedFallback = react.useCallback(
1862
+ (durable) => {
1863
+ const pending = pendingCreditedTransitionRef.current;
1864
+ if (pending && durable && isSameExternalDepositLockSession(durable, pending.predecessor)) {
1865
+ return pending.credited;
1866
+ }
1867
+ pendingCreditedTransitionRef.current = null;
1868
+ return durable;
1869
+ },
1870
+ []
1871
+ );
1872
+ const notifyFailure = react.useCallback((error) => {
1873
+ onLockFailedRef.current?.(error);
1874
+ }, []);
1875
+ const submitSession = react.useCallback(
1876
+ async (active) => {
1877
+ if (settlingRef.current) return;
1878
+ settlingRef.current = true;
1879
+ setIsSubmittingLock(true);
1880
+ let result;
1881
+ try {
1882
+ let submission = active;
1883
+ const storedBeforeSubmit = loadExternalDepositLockSession(active.owner);
1884
+ if (storedBeforeSubmit?.generation === active.generation) {
1885
+ if (active.creditedAmount && !storedBeforeSubmit.creditedAmount) {
1886
+ const pending = pendingCreditedTransitionRef.current;
1887
+ if (!pending || !isSameExternalDepositLockSession(active, pending.credited) || !isSameExternalDepositLockSession(storedBeforeSubmit, pending.predecessor)) {
1888
+ throw new ExternalDepositLockSessionChangedError();
1889
+ }
1890
+ saveExternalDepositLockSession(pending.credited, pending.predecessor);
1891
+ pendingCreditedTransitionRef.current = null;
1892
+ submission = pending.credited;
1893
+ } else {
1894
+ submission = storedBeforeSubmit;
1895
+ }
1896
+ }
1897
+ result = await submitExternalDepositLock(client, submission);
1898
+ } catch (err) {
1899
+ const stored = loadExternalDepositLockSession(active.owner);
1900
+ const error = err instanceof chunkFGWMLLEC_cjs.PostDepositLockError ? err : new chunkFGWMLLEC_cjs.PostDepositLockError(
1901
+ err instanceof Error ? err.message : "Lock submission failed",
1902
+ "submission-failed",
1903
+ BigInt(active.maxLockAmount),
1904
+ active.creditedAmount ? BigInt(active.creditedAmount) : void 0,
1905
+ { cause: err }
1906
+ );
1907
+ if (err instanceof ExternalDepositLockSessionChangedError) {
1908
+ pendingCreditedTransitionRef.current = null;
1909
+ installSession(stored ?? null);
1910
+ return;
1911
+ }
1912
+ if (!stored || stored.generation !== active.generation) {
1913
+ pendingCreditedTransitionRef.current = null;
1914
+ installSession(stored ?? null);
1915
+ return;
1916
+ }
1917
+ if (active.creditedAmount && !stored.creditedAmount) {
1918
+ const pending = pendingCreditedTransitionRef.current;
1919
+ if (pending && isSameExternalDepositLockSession(active, pending.credited) && isSameExternalDepositLockSession(stored, pending.predecessor)) {
1920
+ installSession(pending.credited);
1921
+ notifyFailure(error);
1922
+ return;
1923
+ }
1924
+ pendingCreditedTransitionRef.current = null;
1925
+ installSession(stored);
1926
+ return;
1927
+ }
1928
+ installSession(active.creditedAmount && !stored.creditedAmount ? active : stored);
1929
+ notifyFailure(error);
1930
+ return;
1931
+ } finally {
1932
+ settlingRef.current = false;
1933
+ setIsSubmittingLock(false);
1934
+ }
1935
+ installSession(loadExternalDepositLockSession(active.owner) ?? null);
1936
+ queryClient.invalidateQueries({ queryKey: ["accounting-balance"] });
1937
+ queryClient.invalidateQueries({ queryKey: ["accounting-locked-funds"] });
1938
+ queryClient.invalidateQueries({ queryKey: ["accounting-total-locked-balance"] });
1939
+ queryClient.invalidateQueries({ queryKey: ["accounting-history"] });
1940
+ onLockSubmittedRef.current?.(result);
1941
+ },
1942
+ [client, installSession, notifyFailure, queryClient]
1943
+ );
1944
+ const validateRestoredSession = react.useCallback(
1945
+ (restored) => {
1946
+ if (!restored || !serviceAddress) return null;
1947
+ const token = getTokenById(restored.tokenId);
1948
+ const invalid = restored.serviceAddress.toLowerCase() !== serviceAddress.toLowerCase() || !token || token.chainId !== restored.chainId || token.contract === viem.zeroAddress || !restored.creditedAmount && !restored.payload;
1949
+ if (!invalid) return restored;
1950
+ clearExternalDepositLockSession(
1951
+ restored.owner,
1952
+ externalDepositSessionId(restored.chainId, restored.tokenId),
1953
+ restored.generation
1954
+ );
1955
+ return null;
1956
+ },
1957
+ [getTokenById, serviceAddress]
1958
+ );
1959
+ react.useEffect(() => {
1960
+ if (!privateReadAddress || !serviceAddress || tokensStatus !== "ready") {
1961
+ setSession(null);
1962
+ return;
1963
+ }
1964
+ const hydrationKey = `${privateReadAddress.toLowerCase()}:${serviceAddress.toLowerCase()}`;
1965
+ const shouldResume = hydratedScopeRef.current !== hydrationKey;
1966
+ hydratedScopeRef.current = hydrationKey;
1967
+ const restored = preserveCreditedFallback(
1968
+ validateRestoredSession(loadExternalDepositLockSession(privateReadAddress))
1969
+ );
1970
+ installSession(restored);
1971
+ if (!restored) {
1972
+ return;
1973
+ }
1974
+ if (!shouldResume) return;
1975
+ if (restored.creditedAmount && restored.payload) {
1976
+ void submitSession(restored);
1977
+ } else if (restored.creditedAmount) {
1978
+ notifyFailure(
1979
+ new chunkFGWMLLEC_cjs.PostDepositLockError(
1980
+ "Deposit credited; sign a fresh policy to lock the funds",
1981
+ "not-found",
1982
+ BigInt(restored.maxLockAmount),
1983
+ BigInt(restored.creditedAmount)
1984
+ )
1985
+ );
1986
+ }
1987
+ }, [
1988
+ installSession,
1989
+ notifyFailure,
1990
+ privateReadAddress,
1991
+ preserveCreditedFallback,
1992
+ serviceAddress,
1993
+ submitSession,
1994
+ tokensStatus,
1995
+ validateRestoredSession
1996
+ ]);
1997
+ react.useEffect(() => {
1998
+ if (!privateReadAddress || !serviceAddress || tokensStatus !== "ready") return;
1999
+ const reconcile = (restored) => {
2000
+ installSession(preserveCreditedFallback(validateRestoredSession(restored)));
2001
+ };
2002
+ const unsubscribe = subscribeExternalDepositLockSession(privateReadAddress, reconcile);
2003
+ reconcile(loadExternalDepositLockSession(privateReadAddress));
2004
+ return unsubscribe;
2005
+ }, [
2006
+ installSession,
2007
+ preserveCreditedFallback,
2008
+ privateReadAddress,
2009
+ serviceAddress,
2010
+ tokensStatus,
2011
+ validateRestoredSession
2012
+ ]);
2013
+ const signAndPersist = react.useCallback(
2014
+ async ({ tokenId, amount }) => {
2015
+ if (!allowance) throw new Error("No allowance configured for this deposit");
2016
+ if (signingRef.current || settlingRef.current) {
2017
+ throw new Error("A policy operation is already in progress");
2018
+ }
2019
+ if (!chunkFGWMLLEC_cjs.canUseSharedBrowserStorage()) {
2020
+ throw new Error("Browser storage is required for locked deposit recovery");
2021
+ }
2022
+ const owner = chunkFGWMLLEC_cjs.requireDepositLockOwner(address, privateReadAddress);
2023
+ if (sessionRef.current || loadExternalDepositLockSession(owner)) {
2024
+ throw new Error("Finish or cancel the active external deposit before starting another");
2025
+ }
2026
+ const token = getTokenById(tokenId);
2027
+ if (!token) throw new Error(`Unknown token ID: ${tokenId}`);
2028
+ if (token.contract === viem.zeroAddress) {
2029
+ throw new Error("External deposits support ERC20 tokens only");
2030
+ }
2031
+ const targetService = chunkFGWMLLEC_cjs.requireServiceAddress(serviceAddress);
2032
+ const lockDuration = allowance.lockDuration ?? chunkFGWMLLEC_cjs.DEFAULT_LOCK_DURATION_SECONDS;
2033
+ signingRef.current = true;
2034
+ setIsSigning(true);
2035
+ try {
2036
+ await ensureCorrectChain(networkConfig.chainId);
2037
+ const signingWalletClient = await chunkFGWMLLEC_cjs.getWalletClient(config, {
2038
+ chainId: networkConfig.chainId
2039
+ });
2040
+ const payload = await chunkFGWMLLEC_cjs.createSignedLockRequest({
2041
+ client,
2042
+ walletClient: signingWalletClient,
2043
+ userAddress: owner,
2044
+ networkConfig,
2045
+ serviceAddress: targetService,
2046
+ tokenId: token.id,
2047
+ amount: chunkFGWMLLEC_cjs.clampLockAmount(amount, BigInt(allowance.value)),
2048
+ lockDuration
2049
+ });
2050
+ const startBlock = await chunkFGWMLLEC_cjs.getBlockNumber(config, { chainId: token.chainId });
2051
+ if (startBlock > BigInt(Number.MAX_SAFE_INTEGER)) {
2052
+ throw new Error("Source-chain block number exceeds the supported range");
2053
+ }
2054
+ if (beneficiaryRef.current?.toLowerCase() !== owner.toLowerCase()) {
2055
+ throw new Error("Authenticated deposit account changed while signing");
2056
+ }
2057
+ const next = {
2058
+ version: 1,
2059
+ owner,
2060
+ serviceAddress: targetService,
2061
+ chainId: token.chainId,
2062
+ tokenId: token.id,
2063
+ startBlock: Number(startBlock),
2064
+ depositAmount: amount.toString(),
2065
+ maxLockAmount: String(payload.amount),
2066
+ lockDuration,
2067
+ generation: payload.signature,
2068
+ payload
2069
+ };
2070
+ saveExternalDepositLockSession(next, null);
2071
+ installSession(next);
2072
+ } finally {
2073
+ signingRef.current = false;
2074
+ setIsSigning(false);
2075
+ }
2076
+ },
2077
+ [
2078
+ address,
2079
+ allowance,
2080
+ client,
2081
+ config,
2082
+ ensureCorrectChain,
2083
+ getTokenById,
2084
+ installSession,
2085
+ networkConfig,
2086
+ privateReadAddress,
2087
+ serviceAddress
2088
+ ]
2089
+ );
2090
+ const settleAfterCredit = react.useCallback(
2091
+ async (txHash, creditedAmount) => {
2092
+ const active = sessionRef.current;
2093
+ if (!active || settlingRef.current) return;
2094
+ if (!isCurrentExternalDepositVerification(active, txHash)) {
2095
+ return;
2096
+ }
2097
+ if (creditedAmount <= 0n) throw new Error("Credited amount must be positive");
2098
+ const credited = {
2099
+ ...active,
2100
+ verification: void 0,
2101
+ creditedAmount: creditedAmount.toString()
2102
+ };
2103
+ try {
2104
+ saveExternalDepositLockSession(credited, active);
2105
+ pendingCreditedTransitionRef.current = null;
2106
+ } catch (err) {
2107
+ const stored = loadExternalDepositLockSession(active.owner);
2108
+ if (err instanceof ExternalDepositLockSessionChangedError || !stored || !isSameExternalDepositLockSession(stored, active)) {
2109
+ pendingCreditedTransitionRef.current = null;
2110
+ installSession(stored ?? null);
2111
+ return;
2112
+ }
2113
+ pendingCreditedTransitionRef.current = { predecessor: active, credited };
2114
+ installSession(credited);
2115
+ notifyFailure(
2116
+ new chunkFGWMLLEC_cjs.PostDepositLockError(
2117
+ err instanceof Error ? err.message : "Unable to persist credited deposit state",
2118
+ "submission-failed",
2119
+ BigInt(active.maxLockAmount),
2120
+ creditedAmount,
2121
+ { cause: err }
2122
+ )
2123
+ );
2124
+ return;
2125
+ }
2126
+ installSession(credited);
2127
+ await submitSession(credited);
2128
+ },
2129
+ [installSession, notifyFailure, submitSession]
2130
+ );
2131
+ const recordVerification = react.useCallback(
2132
+ (context) => {
2133
+ const active = sessionRef.current;
2134
+ if (!active || active.creditedAmount) {
2135
+ throw new Error("No external deposit session is awaiting verification");
2136
+ }
2137
+ if (active.verification) {
2138
+ const sameTransfer = active.verification.hash.toLowerCase() === context.hash.toLowerCase() && active.verification.chainId === context.chainId && active.verification.amount === context.amount.toString() && (active.verification.logIndex ?? 0) === (context.logIndex ?? 0);
2139
+ if (sameTransfer) return;
2140
+ throw new Error("Another transfer is already being verified for this deposit session");
2141
+ }
2142
+ if (context.chainId !== active.chainId || context.amount <= 0n) {
2143
+ throw new Error("Discovered transfer does not match the signed deposit session");
2144
+ }
2145
+ const current = loadExternalDepositLockSession(active.owner);
2146
+ if (!current || current.generation !== active.generation) {
2147
+ throw new Error("The signed deposit session changed before verification");
2148
+ }
2149
+ const next = {
2150
+ ...active,
2151
+ verification: {
2152
+ hash: context.hash,
2153
+ chainId: context.chainId,
2154
+ amount: context.amount.toString(),
2155
+ logIndex: context.logIndex
2156
+ }
2157
+ };
2158
+ saveExternalDepositLockSession(next, active);
2159
+ installSession(next);
2160
+ },
2161
+ [installSession]
2162
+ );
2163
+ const retryAfterCredit = react.useCallback(async () => {
2164
+ const active = sessionRef.current;
2165
+ if (!active?.creditedAmount) throw new Error("No credited external deposit to recover");
2166
+ if (signingRef.current || settlingRef.current) {
2167
+ throw new Error("A policy operation is already in progress");
2168
+ }
2169
+ if (privateReadAddress?.toLowerCase() !== active.owner.toLowerCase()) {
2170
+ throw new Error("Authenticated deposit account does not match the credited deposit");
2171
+ }
2172
+ const token = getTokenById(active.tokenId);
2173
+ if (!token || token.chainId !== active.chainId || token.contract === viem.zeroAddress) {
2174
+ throw new Error("The credited token is no longer available");
2175
+ }
2176
+ const targetService = chunkFGWMLLEC_cjs.requireServiceAddress(serviceAddress);
2177
+ if (targetService.toLowerCase() !== active.serviceAddress.toLowerCase()) {
2178
+ throw new Error("The service for this credited deposit has changed");
2179
+ }
2180
+ if (active.payload) {
2181
+ await submitSession(active);
2182
+ return;
2183
+ }
2184
+ if (active.submissionAmbiguous) {
2185
+ throw new Error(
2186
+ "The previous lock submission may have succeeded; a fresh signature is unsafe"
2187
+ );
2188
+ }
2189
+ const owner = chunkFGWMLLEC_cjs.requireDepositLockOwner(address, privateReadAddress);
2190
+ const amount = externalDepositRetryAmount(active);
2191
+ let retrySession;
2192
+ signingRef.current = true;
2193
+ setIsSigning(true);
2194
+ try {
2195
+ await ensureCorrectChain(networkConfig.chainId);
2196
+ const signingWalletClient = await chunkFGWMLLEC_cjs.getWalletClient(config, {
2197
+ chainId: networkConfig.chainId
2198
+ });
2199
+ const payload = await chunkFGWMLLEC_cjs.createSignedLockRequest({
2200
+ client,
2201
+ walletClient: signingWalletClient,
2202
+ userAddress: owner,
2203
+ networkConfig,
2204
+ serviceAddress: targetService,
2205
+ tokenId: active.tokenId,
2206
+ amount,
2207
+ lockDuration: active.lockDuration
2208
+ });
2209
+ if (beneficiaryRef.current?.toLowerCase() !== owner.toLowerCase()) {
2210
+ throw new Error("Authenticated deposit account changed while signing");
2211
+ }
2212
+ retrySession = {
2213
+ ...active,
2214
+ depositAmount: amount.toString(),
2215
+ generation: payload.signature,
2216
+ verification: void 0,
2217
+ submissionAmbiguous: void 0,
2218
+ payload
2219
+ };
2220
+ saveExternalDepositLockSession(retrySession, active);
2221
+ installSession(retrySession);
2222
+ } finally {
2223
+ signingRef.current = false;
2224
+ setIsSigning(false);
2225
+ }
2226
+ await submitSession(retrySession);
2227
+ }, [
2228
+ address,
2229
+ client,
2230
+ config,
2231
+ ensureCorrectChain,
2232
+ getTokenById,
2233
+ installSession,
2234
+ networkConfig,
2235
+ privateReadAddress,
2236
+ serviceAddress,
2237
+ submitSession
2238
+ ]);
2239
+ const clearVerification = react.useCallback(() => {
2240
+ const active = sessionRef.current;
2241
+ if (!active?.verification || active.creditedAmount) return false;
2242
+ const next = clearExternalDepositVerification(active);
2243
+ if (!next) {
2244
+ installSession(loadExternalDepositLockSession(active.owner) ?? null);
2245
+ return false;
2246
+ }
2247
+ installSession(next);
2248
+ return true;
2249
+ }, [installSession]);
2250
+ const discardSession = react.useCallback(() => {
2251
+ const active = sessionRef.current;
2252
+ if (!active) return true;
2253
+ if (signingRef.current || settlingRef.current) return false;
2254
+ const pending = pendingCreditedTransitionRef.current;
2255
+ const discardTarget = pending && isSameExternalDepositLockSession(active, pending.credited) ? pending.predecessor : active;
2256
+ const discarded = discardExternalDepositLockSession(discardTarget);
2257
+ const restored = loadExternalDepositLockSession(active.owner) ?? null;
2258
+ if (discarded) pendingCreditedTransitionRef.current = null;
2259
+ installSession(restored);
2260
+ return discarded && !restored;
2261
+ }, [installSession]);
2262
+ return {
2263
+ isSigning,
2264
+ isSubmittingLock,
2265
+ session,
2266
+ signAndPersist,
2267
+ recordVerification,
2268
+ settleAfterCredit,
2269
+ retryAfterCredit,
2270
+ clearVerification,
2271
+ discardSession
2272
+ };
2273
+ }
1541
2274
  function USDCIcon({ className, size = 24 }) {
1542
2275
  return /* @__PURE__ */ jsxRuntime.jsxs(
1543
2276
  "svg",
@@ -1679,134 +2412,99 @@ function getChainIcon(chainId, size) {
1679
2412
  );
1680
2413
  }
1681
2414
  }
1682
- function CloseIcon() {
1683
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "10", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
1684
- "path",
1685
- {
1686
- d: "M11.99997 11.99997l-5.99995-5.99995-6.00002-6.00002m6.00002 6.00002l6.00001-6.00002m-12.00003 12.00003l6.00002-6.00001",
1687
- stroke: "currentColor",
1688
- strokeWidth: "1.5",
1689
- strokeLinecap: "round",
1690
- strokeLinejoin: "round"
1691
- }
1692
- ) });
1693
- }
1694
- function ChevronRightIcon() {
1695
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "5", viewBox: "0 0 12 6", className: "-rotate-90", children: /* @__PURE__ */ jsxRuntime.jsx(
1696
- "path",
1697
- {
1698
- d: "M0 0l6 6 6-6",
1699
- stroke: "currentColor",
1700
- strokeWidth: "1.5",
1701
- strokeLinecap: "round",
1702
- strokeLinejoin: "round",
1703
- fill: "none"
1704
- }
1705
- ) });
1706
- }
1707
- function ChevronLeftIcon() {
1708
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "5", viewBox: "0 0 12 6", className: "rotate-90", children: /* @__PURE__ */ jsxRuntime.jsx(
1709
- "path",
1710
- {
1711
- d: "M0 0l6 6 6-6",
1712
- stroke: "currentColor",
1713
- strokeWidth: "1.5",
1714
- strokeLinecap: "round",
1715
- strokeLinejoin: "round",
1716
- fill: "none"
1717
- }
1718
- ) });
1719
- }
1720
- function ChevronDownIcon({
1721
- direction = "down",
1722
- className
1723
- }) {
1724
- return /* @__PURE__ */ jsxRuntime.jsx(
1725
- "svg",
1726
- {
1727
- width: "16",
1728
- height: "16",
1729
- viewBox: "0 0 16 16",
1730
- fill: "none",
1731
- className: chunkUHXVYWTF_cjs.cn(
1732
- "transition-transform",
1733
- direction === "right" && "-rotate-90",
1734
- direction === "up" && "rotate-180",
1735
- className
1736
- ),
1737
- children: /* @__PURE__ */ jsxRuntime.jsx(
1738
- "path",
2415
+ function TokenSelectorView({ selectedTokenId, onSelect }) {
2416
+ const { enabledTokens } = chunkFGWMLLEC_cjs.usePrivanaContext();
2417
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-muted flex flex-col rounded-[10px] p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-h-72 flex-col gap-1 overflow-y-auto", children: [
2418
+ enabledTokens.map((token) => {
2419
+ const isSelected = selectedTokenId === token.id;
2420
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2421
+ "button",
1739
2422
  {
1740
- d: "M4 6l4 4 4-4",
1741
- stroke: "currentColor",
1742
- strokeWidth: "1.5",
1743
- strokeLinecap: "round",
1744
- strokeLinejoin: "round"
1745
- }
1746
- )
1747
- }
1748
- );
1749
- }
1750
- function CopyIcon() {
1751
- return /* @__PURE__ */ jsxRuntime.jsxs(
1752
- "svg",
1753
- {
1754
- width: "16",
1755
- height: "16",
1756
- viewBox: "0 0 24 24",
1757
- fill: "none",
1758
- stroke: "currentColor",
1759
- strokeWidth: "2",
1760
- strokeLinecap: "round",
1761
- strokeLinejoin: "round",
1762
- children: [
1763
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
1764
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
1765
- ]
1766
- }
1767
- );
1768
- }
1769
- function CircleCheckIcon() {
1770
- return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
1771
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
1772
- /* @__PURE__ */ jsxRuntime.jsx(
1773
- "path",
1774
- {
1775
- d: "M6 10l2.5 2.5L14 7.5",
1776
- stroke: "currentColor",
1777
- strokeWidth: "1.5",
1778
- strokeLinecap: "round",
1779
- strokeLinejoin: "round"
1780
- }
1781
- )
1782
- ] });
2423
+ type: "button",
2424
+ onClick: () => onSelect(token.id),
2425
+ className: chunkFGWMLLEC_cjs.cn(
2426
+ "hover:bg-secondary flex w-full cursor-pointer items-center gap-3 rounded-lg px-3 py-2 text-left transition-colors",
2427
+ isSelected && "bg-secondary"
2428
+ ),
2429
+ children: [
2430
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 w-6 shrink-0 overflow-hidden rounded-full", children: getTokenIcon(token.symbol, 24) }),
2431
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
2432
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-foreground text-sm font-medium", children: token.symbol }),
2433
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground text-[11px]", children: token.name })
2434
+ ] }),
2435
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-primary flex h-4 w-4 shrink-0 items-center justify-center rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx(
2436
+ "svg",
2437
+ {
2438
+ width: "10",
2439
+ height: "10",
2440
+ viewBox: "0 0 10 10",
2441
+ fill: "none",
2442
+ className: "text-primary-foreground",
2443
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2444
+ "path",
2445
+ {
2446
+ d: "M2 5L4 7L8 3",
2447
+ stroke: "currentColor",
2448
+ strokeWidth: "1.5",
2449
+ strokeLinecap: "round",
2450
+ strokeLinejoin: "round"
2451
+ }
2452
+ )
2453
+ }
2454
+ ) })
2455
+ ]
2456
+ },
2457
+ token.id
2458
+ );
2459
+ }),
2460
+ enabledTokens.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground px-3 py-6 text-center text-sm", children: "No tokens available" })
2461
+ ] }) });
1783
2462
  }
1784
- function CircleXIcon() {
1785
- return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
1786
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
1787
- /* @__PURE__ */ jsxRuntime.jsx(
1788
- "path",
2463
+ function CreditCardWidgetView({
2464
+ token,
2465
+ amount,
2466
+ allowance,
2467
+ onCredited,
2468
+ onLockSubmitted,
2469
+ onLockFailed
2470
+ }) {
2471
+ const moonpayCurrencyCode = token?.moonpayCurrencyCode;
2472
+ const containerRef = react.useRef(null);
2473
+ const [widgetTheme, setWidgetTheme] = react.useState();
2474
+ react.useEffect(() => {
2475
+ if (containerRef.current) setWidgetTheme(resolveSdkTheme(containerRef.current));
2476
+ }, []);
2477
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: [
2478
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: "Complete your purchase" }),
2479
+ token && moonpayCurrencyCode ? /* @__PURE__ */ jsxRuntime.jsx(
2480
+ chunkFGWMLLEC_cjs.FiatOnRampForm,
1789
2481
  {
1790
- d: "M7 7l6 6M13 7l-6 6",
1791
- stroke: "currentColor",
1792
- strokeWidth: "1.5",
1793
- strokeLinecap: "round",
1794
- strokeLinejoin: "round"
2482
+ tokenId: token.id,
2483
+ currencyCode: moonpayCurrencyCode,
2484
+ quoteCurrencyAmount: amount || void 0,
2485
+ lockAmount: true,
2486
+ variant: "embedded",
2487
+ autoStart: true,
2488
+ theme: widgetTheme,
2489
+ postDepositLock: allowance ? {
2490
+ maxAmount: BigInt(allowance.value),
2491
+ lockDuration: allowance.lockDuration
2492
+ } : void 0,
2493
+ onCredited,
2494
+ onLockSubmitted,
2495
+ onLockFailed
1795
2496
  }
1796
- )
2497
+ ) : /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-muted-foreground text-sm", children: [
2498
+ token?.symbol ?? "This token",
2499
+ " isn\u2019t available for card purchases yet."
2500
+ ] })
1797
2501
  ] });
1798
2502
  }
1799
- function ArrowRightIcon({ className }) {
1800
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "8", viewBox: "0 0 24 8", fill: "none", className, children: /* @__PURE__ */ jsxRuntime.jsx(
1801
- "path",
1802
- {
1803
- d: "M0 4h22m0 0l-4-4m4 4l-4 4",
1804
- stroke: "currentColor",
1805
- strokeWidth: "1.5",
1806
- strokeLinecap: "round",
1807
- strokeLinejoin: "round"
1808
- }
1809
- ) });
2503
+ function resolveSdkTheme(el) {
2504
+ const scheme = getComputedStyle(el).colorScheme;
2505
+ if (scheme === "dark") return "dark";
2506
+ if (scheme === "light") return "light";
2507
+ return el.closest(".dark") ? "dark" : "light";
1810
2508
  }
1811
2509
  function CheckIcon() {
1812
2510
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -1925,7 +2623,16 @@ function WarningIcon() {
1925
2623
  }
1926
2624
  ) });
1927
2625
  }
1928
- function TransactionWarningView({ title, message, onDone }) {
2626
+ function TransactionWarningView({
2627
+ title,
2628
+ message,
2629
+ onDone,
2630
+ actionLabel = "Done",
2631
+ pendingLabel = actionLabel,
2632
+ isPending = false,
2633
+ onDismiss,
2634
+ dismissLabel = "Dismiss"
2635
+ }) {
1929
2636
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-4", children: [
1930
2637
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1931
2638
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-amber-500/10 text-amber-400", children: /* @__PURE__ */ jsxRuntime.jsx(WarningIcon, {}) }),
@@ -1934,14 +2641,26 @@ function TransactionWarningView({ title, message, onDone }) {
1934
2641
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs", children: message })
1935
2642
  ] })
1936
2643
  ] }),
1937
- /* @__PURE__ */ jsxRuntime.jsx(
1938
- "button",
1939
- {
1940
- onClick: onDone,
1941
- className: "bg-primary text-primary-foreground hover:bg-primary/90 flex h-10 w-full cursor-pointer items-center justify-center rounded-[10px] px-3 py-2 text-sm font-medium transition-colors",
1942
- children: "Done"
1943
- }
1944
- )
2644
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
2645
+ onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
2646
+ "button",
2647
+ {
2648
+ onClick: onDismiss,
2649
+ disabled: isPending,
2650
+ className: "border-border text-foreground hover:bg-secondary flex h-10 flex-1 cursor-pointer items-center justify-center rounded-[10px] border px-3 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2651
+ children: dismissLabel
2652
+ }
2653
+ ),
2654
+ /* @__PURE__ */ jsxRuntime.jsx(
2655
+ "button",
2656
+ {
2657
+ onClick: onDone,
2658
+ disabled: isPending,
2659
+ className: "bg-primary text-primary-foreground hover:bg-primary/90 flex h-10 flex-1 cursor-pointer items-center justify-center rounded-[10px] px-3 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
2660
+ children: isPending ? pendingLabel : actionLabel
2661
+ }
2662
+ )
2663
+ ] })
1945
2664
  ] });
1946
2665
  }
1947
2666
  function TransactionErrorView({
@@ -1952,7 +2671,8 @@ function TransactionErrorView({
1952
2671
  onRetry,
1953
2672
  onDismiss,
1954
2673
  isRetrying,
1955
- retryLabel = "Retry Verification"
2674
+ retryLabel = "Retry Verification",
2675
+ dismissLabel = "Close"
1956
2676
  }) {
1957
2677
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-4", children: [
1958
2678
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
@@ -1976,13 +2696,13 @@ function TransactionErrorView({
1976
2696
  }
1977
2697
  ),
1978
2698
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
1979
- /* @__PURE__ */ jsxRuntime.jsx(
2699
+ onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
1980
2700
  "button",
1981
2701
  {
1982
2702
  onClick: onDismiss,
1983
2703
  disabled: isRetrying,
1984
2704
  className: "border-border text-foreground hover:bg-secondary flex h-10 flex-1 cursor-pointer items-center justify-center rounded-[10px] border px-3 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
1985
- children: "Close"
2705
+ children: dismissLabel
1986
2706
  }
1987
2707
  ),
1988
2708
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1991,1130 +2711,141 @@ function TransactionErrorView({
1991
2711
  onClick: onRetry,
1992
2712
  disabled: isRetrying,
1993
2713
  className: "bg-primary text-primary-foreground hover:bg-primary/90 flex h-10 flex-1 cursor-pointer items-center justify-center rounded-[10px] px-3 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
1994
- children: isRetrying ? "Retrying..." : retryLabel
2714
+ children: isRetrying ? "Retrying\u2026" : retryLabel
1995
2715
  }
1996
2716
  )
1997
2717
  ] })
1998
2718
  ] });
1999
2719
  }
2000
- function DepositForm({
2001
- selectedToken,
2002
- onTokenSelect,
2003
- onPendingChange,
2004
- onUnsafeToCloseChange,
2005
- onSuccess
2006
- }) {
2007
- const { isConnected, address } = wagmi.useAccount();
2008
- const { chains, getChainById: getChainById2 } = chunkUHXVYWTF_cjs.usePrivanaContext();
2009
- const [amount, setAmount] = react.useState("");
2010
- const [showSuccess, setShowSuccess] = react.useState(false);
2011
- const [showTimeout, setShowTimeout] = react.useState(false);
2012
- const [cancelled, setCancelled] = react.useState(false);
2013
- const targetChain = getChainById2(selectedToken.chainId) ?? chains[0];
2014
- const isNative = selectedToken.contract === viem.zeroAddress;
2015
- const { data: nativeBalanceData } = wagmi.useBalance({
2016
- address,
2017
- chainId: targetChain?.id,
2018
- query: {
2019
- enabled: !!address && isNative
2720
+ function CloseIcon() {
2721
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "10", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
2722
+ "path",
2723
+ {
2724
+ d: "M11.99997 11.99997l-5.99995-5.99995-6.00002-6.00002m6.00002 6.00002l6.00001-6.00002m-12.00003 12.00003l6.00002-6.00001",
2725
+ stroke: "currentColor",
2726
+ strokeWidth: "1.5",
2727
+ strokeLinecap: "round",
2728
+ strokeLinejoin: "round"
2020
2729
  }
2021
- });
2022
- const { data: erc20Balance } = wagmi.useReadContract({
2023
- address: selectedToken.contract,
2024
- abi: viem.erc20Abi,
2025
- functionName: "balanceOf",
2026
- args: address ? [address] : void 0,
2027
- chainId: targetChain?.id,
2028
- query: {
2029
- enabled: !!address && !isNative
2730
+ ) });
2731
+ }
2732
+ function ChevronRightIcon() {
2733
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "5", viewBox: "0 0 12 6", className: "-rotate-90", children: /* @__PURE__ */ jsxRuntime.jsx(
2734
+ "path",
2735
+ {
2736
+ d: "M0 0l6 6 6-6",
2737
+ stroke: "currentColor",
2738
+ strokeWidth: "1.5",
2739
+ strokeLinecap: "round",
2740
+ strokeLinejoin: "round",
2741
+ fill: "none"
2030
2742
  }
2031
- });
2032
- const walletBalance = isNative ? nativeBalanceData?.value : erc20Balance;
2033
- const formattedWalletBalance = walletBalance ? chunkUHXVYWTF_cjs.formatTokenAmount(walletBalance.toString(), selectedToken.decimals) : "0.00";
2034
- const handleMaxClick = () => {
2035
- if (formattedWalletBalance && parseFloat(formattedWalletBalance) > 0) {
2036
- setAmount(formattedWalletBalance.replace(/[\s\u2009]/g, ""));
2743
+ ) });
2744
+ }
2745
+ function ChevronLeftIcon() {
2746
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "5", viewBox: "0 0 12 6", className: "rotate-90", children: /* @__PURE__ */ jsxRuntime.jsx(
2747
+ "path",
2748
+ {
2749
+ d: "M0 0l6 6 6-6",
2750
+ stroke: "currentColor",
2751
+ strokeWidth: "1.5",
2752
+ strokeLinecap: "round",
2753
+ strokeLinejoin: "round",
2754
+ fill: "none"
2037
2755
  }
2038
- };
2039
- const hasValidAmount = amount && parseFloat(amount) > 0;
2040
- const tooManyDecimals = hasValidAmount && amount.includes(".") && amount.split(".")[1].length > selectedToken.decimals;
2041
- const exceedsBalance = hasValidAmount && !tooManyDecimals && walletBalance != null && chunkUHXVYWTF_cjs.parseTokenAmount(amount, selectedToken.decimals) > walletBalance;
2042
- const {
2043
- txHash,
2044
- isGettingAddress,
2045
- isSwitchingChain,
2046
- isSendingTransaction,
2047
- isWaitingForConfirmation,
2048
- isWaitingForProcessing,
2049
- verificationFailed,
2050
- isPending,
2051
- error,
2052
- deposit,
2053
- retryVerification,
2054
- reset
2055
- } = useDeposit({
2056
- onCredited: () => {
2057
- setAmount("");
2058
- if (onSuccess) {
2059
- reset();
2060
- onSuccess();
2061
- } else {
2062
- setShowSuccess(true);
2063
- }
2064
- },
2065
- onCheckTimeout: () => {
2066
- setAmount("");
2067
- setShowTimeout(true);
2068
- }
2069
- });
2070
- const depositSteps = [
2071
- {
2072
- label: "Getting deposit address",
2073
- status: isGettingAddress ? "active" : isSwitchingChain || isSendingTransaction || isWaitingForConfirmation || isWaitingForProcessing ? "completed" : "pending"
2074
- },
2075
- {
2076
- label: `Switching to ${targetChain?.name ?? "deposit chain"}`,
2077
- status: isSwitchingChain ? "active" : isSendingTransaction || isWaitingForConfirmation || isWaitingForProcessing ? "completed" : "pending"
2078
- },
2079
- {
2080
- label: "Confirm in wallet",
2081
- status: isSendingTransaction ? "active" : isWaitingForConfirmation || isWaitingForProcessing ? "completed" : "pending"
2082
- },
2083
- {
2084
- label: "Confirming transaction",
2085
- status: isWaitingForConfirmation ? "active" : isWaitingForProcessing ? "completed" : "pending"
2086
- },
2087
- {
2088
- label: "Verifying deposit \u2014 may take up to a few minutes",
2089
- status: isWaitingForProcessing ? "active" : "pending"
2090
- }
2091
- ];
2092
- react.useEffect(() => {
2093
- if (error && !verificationFailed) {
2094
- sonner.toast.error(error.message.length > 100 ? `${error.message.slice(0, 100)}...` : error.message);
2095
- }
2096
- }, [error, verificationFailed]);
2097
- react.useEffect(() => {
2098
- onPendingChange?.(isPending && !cancelled);
2099
- }, [isPending, cancelled, onPendingChange]);
2100
- react.useEffect(() => {
2101
- onUnsafeToCloseChange?.((isGettingAddress || isSendingTransaction) && !cancelled);
2102
- }, [isGettingAddress, isSendingTransaction, cancelled, onUnsafeToCloseChange]);
2103
- const handleCancel = () => {
2104
- setCancelled(true);
2105
- reset();
2106
- };
2107
- const handleDone = () => {
2108
- setShowSuccess(false);
2109
- setShowTimeout(false);
2110
- setCancelled(false);
2111
- reset();
2112
- };
2113
- const handleDismissVerificationError = () => {
2114
- setAmount("");
2115
- setCancelled(false);
2116
- reset();
2117
- };
2118
- const handleRetryVerification = () => {
2119
- retryVerification().catch(() => {
2120
- });
2121
- };
2122
- const explorerTxUrl = txHash && targetChain?.explorerUrl ? `${targetChain.explorerUrl}/tx/${txHash}` : void 0;
2123
- const handleSubmit = async () => {
2124
- if (!amount || !selectedToken || exceedsBalance) return;
2125
- setCancelled(false);
2126
- const amountInWei = chunkUHXVYWTF_cjs.parseTokenAmount(amount, selectedToken.decimals);
2127
- await deposit({
2128
- tokenId: selectedToken.id,
2129
- amount: amountInWei
2130
- });
2131
- };
2132
- const getButtonText = () => {
2133
- if (!isConnected) return "Connect Wallet";
2134
- if (isSwitchingChain) return "Switching...";
2135
- return "Deposit";
2136
- };
2137
- if (showSuccess) {
2138
- return /* @__PURE__ */ jsxRuntime.jsx(
2139
- TransactionSuccessView,
2140
- {
2141
- title: "Deposit Successful",
2142
- message: `Your ${selectedToken.symbol} deposit has been processed.`,
2143
- onDone: handleDone
2144
- }
2145
- );
2146
- }
2147
- if (showTimeout) {
2148
- return /* @__PURE__ */ jsxRuntime.jsx(
2149
- TransactionWarningView,
2150
- {
2151
- title: "Deposit Processing",
2152
- message: `Your transaction was confirmed but the deposit is still being processed. Please check your balance - it should update shortly.`,
2153
- onDone: handleDone
2154
- }
2155
- );
2156
- }
2157
- if (verificationFailed) {
2158
- const baseMessage = "Your transfer was sent on-chain but we could not verify the deposit. The funds are already at the deposit address \u2014 retry verification instead of starting a new deposit.";
2159
- const detail = error?.message;
2160
- const message = detail ? `${baseMessage} (${detail})` : baseMessage;
2161
- return /* @__PURE__ */ jsxRuntime.jsx(
2162
- TransactionErrorView,
2163
- {
2164
- title: "Verification failed",
2165
- message,
2166
- explorerUrl: explorerTxUrl,
2167
- explorerLabel: "View transaction",
2168
- onRetry: handleRetryVerification,
2169
- onDismiss: handleDismissVerificationError
2170
- }
2171
- );
2172
- }
2173
- if (isPending && !cancelled) {
2174
- const canCancel = isGettingAddress || isSendingTransaction;
2175
- return /* @__PURE__ */ jsxRuntime.jsx(
2176
- TransactionProgressView,
2177
- {
2178
- title: "Depositing...",
2179
- steps: depositSteps,
2180
- onCancel: canCancel ? handleCancel : void 0
2181
- }
2182
- );
2183
- }
2184
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-6", children: [
2185
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-3", children: [
2186
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-muted-foreground text-sm", children: "Token" }),
2187
- /* @__PURE__ */ jsxRuntime.jsxs(
2188
- "button",
2189
- {
2190
- onClick: onTokenSelect,
2191
- className: "border-border bg-input flex w-full cursor-pointer items-center gap-3 rounded-lg border p-3",
2192
- children: [
2193
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 w-8 shrink-0 overflow-hidden rounded-full", children: getTokenIcon(selectedToken.symbol, 32) }),
2194
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-start gap-1", children: [
2195
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-sm font-medium", children: selectedToken.symbol }),
2196
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-xs", children: [
2197
- "on ",
2198
- targetChain?.name ?? "Base Sepolia"
2199
- ] })
2200
- ] }),
2201
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground flex h-5 w-5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, {}) })
2202
- ]
2203
- }
2204
- )
2205
- ] }),
2206
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-3", children: [
2207
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2208
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-muted-foreground text-sm", children: "Amount" }),
2209
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-sm", children: [
2210
- formattedWalletBalance,
2211
- " ",
2212
- selectedToken.symbol
2213
- ] })
2214
- ] }),
2215
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-border bg-input flex items-center gap-2 rounded-[10px] border py-1 pr-1 pl-3", children: [
2216
- /* @__PURE__ */ jsxRuntime.jsx(
2217
- "input",
2218
- {
2219
- type: "text",
2220
- inputMode: "decimal",
2221
- placeholder: "Enter Amount",
2222
- value: amount,
2223
- onChange: (e) => {
2224
- const value = e.target.value.replace(/[^0-9.,]/g, "").replace(/,/g, ".");
2225
- if (value.split(".").length <= 2) {
2226
- setAmount(value);
2227
- }
2228
- },
2229
- className: chunkUHXVYWTF_cjs.cn(
2230
- "text-foreground flex-1 bg-transparent text-sm outline-none",
2231
- "placeholder:text-muted-foreground/50"
2232
- )
2233
- }
2234
- ),
2235
- /* @__PURE__ */ jsxRuntime.jsx(
2236
- "button",
2237
- {
2238
- onClick: handleMaxClick,
2239
- className: "bg-secondary text-foreground hover:bg-secondary/80 cursor-pointer rounded px-3 py-2.5 text-xs font-semibold transition-colors",
2240
- children: "MAX"
2241
- }
2242
- )
2243
- ] }),
2244
- tooManyDecimals && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-destructive text-sm", children: [
2245
- "Too many decimal places (max: ",
2246
- selectedToken.decimals,
2247
- ")"
2248
- ] }),
2249
- exceedsBalance && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-destructive text-sm", children: "Insufficient balance" })
2250
- ] }),
2251
- /* @__PURE__ */ jsxRuntime.jsx(
2252
- "button",
2253
- {
2254
- onClick: handleSubmit,
2255
- disabled: !isConnected || !hasValidAmount || tooManyDecimals || !!exceedsBalance || isPending,
2256
- className: chunkUHXVYWTF_cjs.cn(
2257
- "flex h-10 w-full cursor-pointer items-center justify-center rounded-[10px] px-3 py-2 text-sm font-medium transition-colors",
2258
- "bg-primary text-primary-foreground hover:bg-primary/90",
2259
- "disabled:cursor-not-allowed disabled:opacity-50"
2260
- ),
2261
- children: getButtonText()
2262
- }
2263
- )
2264
- ] });
2265
- }
2266
- function WithdrawForm({
2267
- selectedToken,
2268
- onTokenSelect,
2269
- onPendingChange,
2270
- onUnsafeToCloseChange
2271
- }) {
2272
- const { isConnected, address } = wagmi.useAccount();
2273
- const { chains, getChainById: getChainById2 } = chunkUHXVYWTF_cjs.usePrivanaContext();
2274
- const [amount, setAmount] = react.useState("");
2275
- const [showSuccess, setShowSuccess] = react.useState(false);
2276
- const [showTimeout, setShowTimeout] = react.useState(false);
2277
- const [cancelled, setCancelled] = react.useState(false);
2278
- const targetChain = getChainById2(selectedToken.chainId) ?? chains[0];
2279
- const {
2280
- balanceWei,
2281
- isLoading: isBalanceLoading,
2282
- isError: isBalanceError
2283
- } = useBalance({
2284
- tokenId: selectedToken.id
2285
- });
2286
- const formattedBalance = chunkUHXVYWTF_cjs.formatTokenAmount(balanceWei, selectedToken.decimals);
2287
- const { withdraw, isPending, currentStep, error, reset } = useWithdraw({
2288
- onProcessingSuccess: () => {
2289
- setAmount("");
2290
- setShowSuccess(true);
2291
- },
2292
- onProcessingTimeout: () => {
2293
- setAmount("");
2294
- setShowTimeout(true);
2295
- }
2296
- });
2297
- const explorerUrl = address && targetChain ? chunkUHXVYWTF_cjs.getExplorerAddressUrl(targetChain.id, address) : void 0;
2298
- const getStepStatus = (step, after) => {
2299
- if (currentStep === step) return "active";
2300
- if (after.includes(currentStep)) return "completed";
2301
- return "pending";
2302
- };
2303
- const withdrawSteps = [
2304
- {
2305
- label: "Switching to signing chain",
2306
- status: getStepStatus("switching-chain", ["signing", "submitting", "processing"])
2307
- },
2308
- { label: "Sign in wallet", status: getStepStatus("signing", ["submitting", "processing"]) },
2309
- {
2310
- label: "Submitting withdrawal",
2311
- status: getStepStatus("submitting", ["processing"])
2312
- },
2313
- {
2314
- label: "Processing \u2014 may take a minute or two",
2315
- status: getStepStatus("processing", [])
2316
- }
2317
- ];
2318
- react.useEffect(() => {
2319
- if (error) {
2320
- sonner.toast.error(error.message.length > 100 ? `${error.message.slice(0, 100)}...` : error.message);
2321
- }
2322
- }, [error]);
2323
- react.useEffect(() => {
2324
- const pending = isPending && !cancelled;
2325
- onPendingChange?.(pending);
2326
- onUnsafeToCloseChange?.(pending);
2327
- }, [isPending, cancelled, onPendingChange, onUnsafeToCloseChange]);
2328
- const handleCancel = () => {
2329
- setCancelled(true);
2330
- reset();
2331
- };
2332
- const handleDone = () => {
2333
- setShowSuccess(false);
2334
- setShowTimeout(false);
2335
- setCancelled(false);
2336
- reset();
2337
- };
2338
- const handleWithdraw = async () => {
2339
- if (!amount || !selectedToken || exceedsBalance) return;
2340
- setCancelled(false);
2341
- const amountInWei = chunkUHXVYWTF_cjs.parseTokenAmount(amount, selectedToken.decimals);
2342
- await withdraw({
2343
- tokenId: selectedToken.id,
2344
- amount: amountInWei
2345
- });
2346
- };
2347
- const handleMaxClick = () => {
2348
- if (formattedBalance && parseFloat(formattedBalance) > 0) {
2349
- setAmount(formattedBalance.replace(/[\s\u2009]/g, ""));
2350
- }
2351
- };
2352
- const hasValidAmount = amount && parseFloat(amount) > 0;
2353
- const tooManyDecimals = hasValidAmount && amount.includes(".") && amount.split(".")[1].length > selectedToken.decimals;
2354
- const exceedsBalance = hasValidAmount && !tooManyDecimals && !isBalanceLoading && !isBalanceError && chunkUHXVYWTF_cjs.parseTokenAmount(amount, selectedToken.decimals) > BigInt(balanceWei);
2355
- const getButtonText = () => {
2356
- if (!isConnected) return "Connect Wallet";
2357
- return "Withdraw";
2358
- };
2359
- if (showSuccess) {
2360
- return /* @__PURE__ */ jsxRuntime.jsx(
2361
- TransactionSuccessView,
2362
- {
2363
- title: "Withdrawal Complete",
2364
- message: `Your ${selectedToken.symbol} withdrawal has been processed. Funds should appear in your wallet shortly.`,
2365
- explorerUrl,
2366
- explorerLabel: targetChain ? chunkUHXVYWTF_cjs.getExplorerLabel(targetChain.id) : void 0,
2367
- onDone: handleDone
2368
- }
2369
- );
2370
- }
2371
- if (showTimeout) {
2372
- return /* @__PURE__ */ jsxRuntime.jsx(
2373
- TransactionWarningView,
2374
- {
2375
- title: "Withdrawal Processing",
2376
- message: `Your withdrawal is still being processed. Please check your balance \u2014 it should update shortly.`,
2377
- onDone: handleDone
2378
- }
2379
- );
2380
- }
2381
- if (isPending && !cancelled) {
2382
- const canCancel = currentStep === "idle" || currentStep === "switching-chain" || currentStep === "signing";
2383
- return /* @__PURE__ */ jsxRuntime.jsx(
2384
- TransactionProgressView,
2385
- {
2386
- title: "Withdrawing...",
2387
- steps: withdrawSteps,
2388
- onCancel: canCancel ? handleCancel : void 0
2389
- }
2390
- );
2391
- }
2392
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-6", children: [
2393
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-3", children: [
2394
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-muted-foreground text-sm", children: "Token" }),
2395
- /* @__PURE__ */ jsxRuntime.jsxs(
2396
- "button",
2397
- {
2398
- onClick: onTokenSelect,
2399
- className: "border-border bg-input flex w-full cursor-pointer items-center gap-3 rounded-lg border p-3",
2400
- children: [
2401
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 w-8 shrink-0 overflow-hidden rounded-full", children: getTokenIcon(selectedToken.symbol, 32) }),
2402
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-start gap-1", children: [
2403
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-sm font-medium", children: selectedToken.symbol }),
2404
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-xs", children: [
2405
- "on ",
2406
- targetChain?.name ?? "Base Sepolia"
2407
- ] })
2408
- ] }),
2409
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground flex h-5 w-5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, {}) })
2410
- ]
2411
- }
2412
- )
2413
- ] }),
2414
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col gap-3", children: [
2415
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2416
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-muted-foreground text-sm", children: "Amount" }),
2417
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-sm", children: [
2418
- formattedBalance,
2419
- " ",
2420
- selectedToken.symbol
2421
- ] })
2422
- ] }),
2423
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-border bg-input flex items-center gap-2 rounded-[10px] border py-1 pr-1 pl-3", children: [
2424
- /* @__PURE__ */ jsxRuntime.jsx(
2425
- "input",
2426
- {
2427
- type: "text",
2428
- inputMode: "decimal",
2429
- placeholder: "Enter Amount",
2430
- value: amount,
2431
- onChange: (e) => {
2432
- const value = e.target.value.replace(/[^0-9.,]/g, "").replace(/,/g, ".");
2433
- if (value.split(".").length <= 2) {
2434
- setAmount(value);
2435
- }
2436
- },
2437
- className: chunkUHXVYWTF_cjs.cn(
2438
- "text-foreground flex-1 bg-transparent text-sm outline-none",
2439
- "placeholder:text-muted-foreground/50"
2440
- )
2441
- }
2442
- ),
2443
- /* @__PURE__ */ jsxRuntime.jsx(
2444
- "button",
2445
- {
2446
- onClick: handleMaxClick,
2447
- className: "bg-secondary text-foreground hover:bg-secondary/80 cursor-pointer rounded px-3 py-2.5 text-xs font-semibold transition-colors",
2448
- children: "MAX"
2449
- }
2450
- )
2451
- ] }),
2452
- tooManyDecimals && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-destructive text-sm", children: [
2453
- "Too many decimal places (max: ",
2454
- selectedToken.decimals,
2455
- ")"
2456
- ] }),
2457
- exceedsBalance && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-destructive text-sm", children: "Insufficient balance" })
2458
- ] }),
2459
- /* @__PURE__ */ jsxRuntime.jsx(
2460
- "button",
2461
- {
2462
- onClick: handleWithdraw,
2463
- disabled: !isConnected || !hasValidAmount || tooManyDecimals || !!exceedsBalance || isPending,
2464
- className: chunkUHXVYWTF_cjs.cn(
2465
- "flex h-10 w-full cursor-pointer items-center justify-center rounded-[10px] px-3 py-2 text-sm font-medium transition-colors",
2466
- "bg-primary text-primary-foreground hover:bg-primary/90",
2467
- "disabled:cursor-not-allowed disabled:opacity-50"
2468
- ),
2469
- children: getButtonText()
2470
- }
2471
- )
2472
- ] });
2473
- }
2474
- function BalanceCards({
2475
- selectedToken,
2476
- onLockedFundsClick,
2477
- onBalanceClick,
2478
- showLockedFunds = true,
2479
- disabled
2480
- }) {
2481
- const { balanceWei, isLoading: balanceLoading } = useBalance({
2482
- tokenId: selectedToken.id
2483
- });
2484
- const { totalLocked, isLoading: lockedLoading } = useLockedFunds({ enabled: showLockedFunds });
2485
- const formattedBalance = chunkUHXVYWTF_cjs.formatTokenAmount(balanceWei, selectedToken.decimals);
2486
- const formattedLocked = showLockedFunds ? chunkUHXVYWTF_cjs.formatTokenAmount(String(totalLocked), selectedToken.decimals) : "0.00";
2487
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkUHXVYWTF_cjs.cn("flex gap-2", disabled && "opacity-50"), children: [
2488
- /* @__PURE__ */ jsxRuntime.jsxs(
2489
- "button",
2490
- {
2491
- onClick: onBalanceClick,
2492
- disabled,
2493
- className: chunkUHXVYWTF_cjs.cn(
2494
- "bg-muted flex flex-1 flex-col gap-2 rounded-[10px] p-5 text-left transition-colors",
2495
- disabled ? "cursor-not-allowed" : "hover:bg-muted/80 cursor-pointer"
2496
- ),
2497
- children: [
2498
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center justify-between", children: [
2499
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
2500
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: "Balance" }),
2501
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-secondary text-muted-foreground rounded-full px-2 py-[5px] text-[10px] font-bold", children: selectedToken.symbol })
2502
- ] }),
2503
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground flex h-6 w-6 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, {}) })
2504
- ] }),
2505
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-foreground text-xl font-medium", children: balanceLoading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-secondary inline-block h-6 w-24 animate-pulse rounded" }) : formattedBalance })
2506
- ]
2507
- }
2508
- ),
2509
- showLockedFunds && /* @__PURE__ */ jsxRuntime.jsxs(
2510
- "button",
2511
- {
2512
- onClick: onLockedFundsClick,
2513
- disabled,
2514
- className: chunkUHXVYWTF_cjs.cn(
2515
- "bg-muted flex flex-1 flex-col gap-2 rounded-[10px] p-5 text-left transition-colors",
2516
- disabled ? "cursor-not-allowed" : "hover:bg-muted/80 cursor-pointer"
2517
- ),
2518
- children: [
2519
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center justify-between", children: [
2520
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
2521
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: "Locked Funds" }),
2522
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-secondary text-muted-foreground rounded-full px-2 py-[5px] text-[10px] font-bold", children: selectedToken.symbol })
2523
- ] }),
2524
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground flex h-6 w-6 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, {}) })
2525
- ] }),
2526
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-foreground text-xl font-medium", children: lockedLoading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-secondary inline-block h-6 w-20 animate-pulse rounded" }) : formattedLocked })
2527
- ]
2528
- }
2529
- )
2530
- ] });
2531
- }
2532
- function Tabs({
2533
- activeTab,
2534
- onTabChange,
2535
- disabled
2536
- }) {
2537
- return /* @__PURE__ */ jsxRuntime.jsxs(
2538
- "div",
2539
- {
2540
- className: chunkUHXVYWTF_cjs.cn(
2541
- "bg-muted relative flex gap-2 overflow-hidden rounded-[10px] p-1",
2542
- disabled && "opacity-50"
2543
- ),
2544
- children: [
2545
- /* @__PURE__ */ jsxRuntime.jsx(
2546
- "div",
2547
- {
2548
- className: chunkUHXVYWTF_cjs.cn(
2549
- "bg-input absolute top-1 bottom-1 left-1 w-[calc(50%-8px)] rounded-md transition-transform duration-200",
2550
- activeTab === "withdraw" && "translate-x-[calc(100%+8px)]"
2551
- )
2552
- }
2553
- ),
2554
- /* @__PURE__ */ jsxRuntime.jsx(
2555
- "button",
2556
- {
2557
- onClick: () => !disabled && onTabChange("deposit"),
2558
- disabled,
2559
- className: chunkUHXVYWTF_cjs.cn(
2560
- "relative z-10 flex-1 rounded-md px-3 py-[9px] text-sm transition-colors",
2561
- activeTab === "deposit" ? "text-foreground" : "text-muted-foreground",
2562
- disabled ? "cursor-not-allowed" : "cursor-pointer"
2563
- ),
2564
- children: "Deposit"
2565
- }
2566
- ),
2567
- /* @__PURE__ */ jsxRuntime.jsx(
2568
- "button",
2569
- {
2570
- onClick: () => !disabled && onTabChange("withdraw"),
2571
- disabled,
2572
- className: chunkUHXVYWTF_cjs.cn(
2573
- "relative z-10 flex-1 rounded-md px-3 py-[9px] text-sm transition-colors",
2574
- activeTab === "withdraw" ? "text-foreground" : "text-muted-foreground",
2575
- disabled ? "cursor-not-allowed" : "cursor-pointer"
2576
- ),
2577
- children: "Withdraw"
2578
- }
2579
- )
2580
- ]
2581
- }
2582
- );
2583
- }
2584
- function LockedFundsView({ onBack }) {
2585
- const { getTokenById } = chunkUHXVYWTF_cjs.usePrivanaContext();
2586
- const { locks, isLoading } = useLockedFunds();
2587
- const { unlockFunds, unlockAllExpired, isPending } = useUnlockFunds();
2588
- const [collapsedSections, setCollapsedSections] = react.useState({});
2589
- const sections = react.useMemo(() => {
2590
- const sectionMap = {};
2591
- locks.forEach((lock) => {
2592
- const serviceName = chunkUHXVYWTF_cjs.shortenAddress(lock.service_address);
2593
- if (!sectionMap[lock.service_address]) {
2594
- sectionMap[lock.service_address] = {
2595
- title: `Service ${serviceName}`,
2596
- items: []
2597
- };
2598
- }
2599
- sectionMap[lock.service_address].items.push({
2600
- lockId: lock.lock_id,
2601
- amount: chunkUHXVYWTF_cjs.formatTokenAmount(String(lock.amount), getTokenById(lock.token_id)?.decimals ?? 18),
2602
- serviceAddress: lock.service_address,
2603
- time: lock.is_expired ? "Click to unlock" : chunkUHXVYWTF_cjs.formatTimeRemaining(lock.expiry),
2604
- isExpired: lock.is_expired
2605
- });
2606
- });
2607
- return Object.values(sectionMap);
2608
- }, [getTokenById, locks]);
2609
- const toggleSection = (title) => {
2610
- setCollapsedSections((prev) => ({
2611
- ...prev,
2612
- [title]: !prev[title]
2613
- }));
2614
- };
2615
- const expiredCount = locks.filter((l) => l.is_expired).length;
2616
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2617
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between px-5 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2618
- /* @__PURE__ */ jsxRuntime.jsx(
2619
- "button",
2620
- {
2621
- onClick: onBack,
2622
- className: "text-muted-foreground hover:text-foreground -ml-2 flex h-6 w-6 cursor-pointer items-center justify-center transition-colors",
2623
- children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeftIcon, {})
2624
- }
2625
- ),
2626
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-xl leading-6 font-medium", children: "Locked Funds" })
2627
- ] }) }),
2628
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted flex min-h-0 flex-1 flex-col rounded-[10px] p-2", children: [
2629
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2 p-3", children: [1, 2].map((i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex animate-pulse items-center gap-3 rounded-lg p-3", children: [
2630
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-secondary h-10 w-10 rounded-full" }),
2631
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
2632
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-secondary mb-2 h-3.5 w-24 rounded" }),
2633
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-secondary h-3 w-32 rounded" })
2634
- ] })
2635
- ] }, i)) }) : sections.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center p-8", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: "No locked funds" }) }) : sections.map((section) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2636
- /* @__PURE__ */ jsxRuntime.jsxs(
2637
- "button",
2638
- {
2639
- onClick: () => toggleSection(section.title),
2640
- className: "text-muted-foreground hover:bg-secondary flex w-full cursor-pointer items-center justify-between rounded-lg px-4 py-4 transition-colors",
2641
- children: [
2642
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: section.title }),
2643
- /* @__PURE__ */ jsxRuntime.jsx(
2644
- ChevronDownIcon,
2645
- {
2646
- direction: collapsedSections[section.title] ? "right" : "down"
2647
- }
2648
- )
2649
- ]
2650
- }
2651
- ),
2652
- !collapsedSections[section.title] && section.items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
2653
- "div",
2654
- {
2655
- className: chunkUHXVYWTF_cjs.cn(
2656
- "flex items-center justify-between gap-3 rounded-lg p-3",
2657
- item.isExpired && "bg-secondary"
2658
- ),
2659
- children: [
2660
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 items-center gap-3", children: [
2661
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-secondary h-10 w-10 rounded-full" }),
2662
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
2663
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-foreground text-sm font-medium", children: [
2664
- item.amount,
2665
- " USDC"
2666
- ] }),
2667
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground text-xs", children: [
2668
- "Service: ",
2669
- chunkUHXVYWTF_cjs.shortenAddress(item.serviceAddress)
2670
- ] })
2671
- ] })
2672
- ] }),
2673
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-end gap-2", children: [
2674
- item.isExpired ? /* @__PURE__ */ jsxRuntime.jsx(
2675
- "button",
2676
- {
2677
- onClick: () => unlockFunds({ lockId: Number(item.lockId) }),
2678
- disabled: isPending,
2679
- className: "text-foreground hover:text-foreground/80 cursor-pointer text-sm transition-colors disabled:opacity-50",
2680
- children: "Click to unlock"
2681
- }
2682
- ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-amber-500", children: item.time }),
2683
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs", children: "on Base Sepolia" })
2684
- ] })
2685
- ]
2686
- },
2687
- `${item.serviceAddress}-${item.lockId}`
2688
- ))
2689
- ] }, section.title)) }),
2690
- expiredCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
2691
- "button",
2692
- {
2693
- onClick: () => unlockAllExpired(),
2694
- disabled: isPending,
2695
- className: "border-border text-foreground hover:bg-secondary flex h-10 w-full cursor-pointer items-center justify-center rounded-[10px] border px-3 py-2 text-sm font-medium transition-colors disabled:opacity-50",
2696
- children: [
2697
- "Unlock All (",
2698
- expiredCount,
2699
- ")"
2700
- ]
2701
- }
2702
- ) })
2703
- ] })
2704
- ] });
2705
- }
2706
- function BalanceTokenRow({ token }) {
2707
- const { balanceWei, isLoading } = useBalance({
2708
- tokenId: token.id
2709
- });
2710
- const formattedBalance = chunkUHXVYWTF_cjs.formatTokenAmount(balanceWei, token.decimals);
2711
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2 rounded-lg px-3 py-2.5", children: [
2712
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[18px] w-[18px] overflow-hidden rounded-full", children: getTokenIcon(token.symbol, 18) }),
2713
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground flex-1 text-sm", children: token.symbol }),
2714
- isLoading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-secondary h-4 w-16 animate-pulse rounded" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: formattedBalance })
2715
- ] });
2716
- }
2717
- function BalanceDetailsView({ onBack }) {
2718
- const { enabledTokens, chains } = chunkUHXVYWTF_cjs.usePrivanaContext();
2719
- const [selectedChainId, setSelectedChainId] = react.useState(chains[0]?.id ?? 84532);
2720
- const chainTokens = react.useMemo(() => {
2721
- return enabledTokens.filter((t) => t.chainId === selectedChainId);
2722
- }, [enabledTokens, selectedChainId]);
2723
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2724
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between px-5 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2725
- /* @__PURE__ */ jsxRuntime.jsx(
2726
- "button",
2727
- {
2728
- onClick: onBack,
2729
- className: "text-muted-foreground hover:text-foreground -ml-2 flex h-6 w-6 cursor-pointer items-center justify-center transition-colors",
2730
- children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeftIcon, {})
2731
- }
2732
- ),
2733
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-xl leading-6 font-medium", children: "Token Balances" })
2734
- ] }) }),
2735
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 gap-2", children: [
2736
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted flex flex-1 flex-col overflow-hidden rounded-[10px] p-2", children: [
2737
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pt-4 pb-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: "Network" }) }),
2738
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex-1 overflow-y-auto", children: chains.map((chain) => {
2739
- const isSelected = selectedChainId === chain.id;
2740
- return /* @__PURE__ */ jsxRuntime.jsxs(
2741
- "button",
2742
- {
2743
- onClick: () => setSelectedChainId(chain.id),
2744
- className: chunkUHXVYWTF_cjs.cn(
2745
- "hover:bg-secondary flex w-full cursor-pointer items-center gap-2 rounded-lg px-3 py-2.5 text-left transition-colors",
2746
- isSelected && "bg-secondary"
2747
- ),
2748
- children: [
2749
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[18px] w-[18px] overflow-hidden rounded-full", children: getChainIcon(chain.id, 18) }),
2750
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground flex-1 text-sm", children: chain.name })
2751
- ]
2752
- },
2753
- chain.id
2754
- );
2755
- }) })
2756
- ] }),
2757
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted flex flex-[2] flex-col overflow-hidden rounded-[10px] p-2", children: [
2758
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pt-4 pb-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: "Token Balance" }) }),
2759
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 flex-1 overflow-y-auto", children: chainTokens.map((token) => /* @__PURE__ */ jsxRuntime.jsx(BalanceTokenRow, { token }, token.id)) })
2760
- ] })
2761
- ] })
2762
- ] });
2763
- }
2764
- function TokenRow({
2765
- token,
2766
- isSelected,
2767
- onClick
2768
- }) {
2769
- const { address } = wagmi.useAccount();
2770
- const isNative = token.contract === viem.zeroAddress;
2771
- const { data: nativeBalanceData } = wagmi.useBalance({
2772
- address,
2773
- chainId: token.chainId,
2774
- query: { enabled: !!address && isNative }
2775
- });
2776
- const { data: erc20Balance } = wagmi.useReadContract({
2777
- address: token.contract,
2778
- abi: viem.erc20Abi,
2779
- functionName: "balanceOf",
2780
- args: address ? [address] : void 0,
2781
- chainId: token.chainId,
2782
- query: { enabled: !!address && !isNative }
2783
- });
2784
- const walletBalance = isNative ? nativeBalanceData?.value : erc20Balance;
2785
- const formattedBalance = walletBalance ? chunkUHXVYWTF_cjs.formatTokenAmount(walletBalance.toString(), token.decimals) : "0.00";
2786
- return /* @__PURE__ */ jsxRuntime.jsxs(
2787
- "button",
2788
- {
2789
- onClick,
2790
- className: chunkUHXVYWTF_cjs.cn(
2791
- "hover:bg-secondary flex w-full cursor-pointer items-center gap-2 rounded-lg px-3 py-2.5 text-left transition-colors",
2792
- isSelected && "bg-secondary"
2793
- ),
2794
- children: [
2795
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[18px] w-[18px] overflow-hidden rounded-full", children: getTokenIcon(token.symbol, 18) }),
2796
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground flex-1 text-sm", children: token.symbol }),
2797
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: formattedBalance })
2798
- ]
2799
- }
2800
- );
2801
- }
2802
- function TokenSelectorView({
2803
- onBack,
2804
- onSelect,
2805
- selectedTokenId
2806
- }) {
2807
- const { enabledTokens, chains } = chunkUHXVYWTF_cjs.usePrivanaContext();
2808
- const [selectedChainId, setSelectedChainId] = react.useState(chains[0]?.id ?? 84532);
2809
- const chainTokens = react.useMemo(() => {
2810
- return enabledTokens.filter((t) => t.chainId === selectedChainId);
2811
- }, [enabledTokens, selectedChainId]);
2812
- const handleTokenSelect = (token) => {
2813
- onSelect(token);
2814
- onBack();
2815
- };
2816
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2817
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between px-5 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2818
- /* @__PURE__ */ jsxRuntime.jsx(
2819
- "button",
2820
- {
2821
- onClick: onBack,
2822
- className: "text-muted-foreground hover:text-foreground -ml-2 flex h-6 w-6 cursor-pointer items-center justify-center transition-colors",
2823
- children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeftIcon, {})
2824
- }
2825
- ),
2826
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-xl leading-6 font-medium", children: "Select Token" })
2827
- ] }) }),
2828
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 gap-2", children: [
2829
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted flex flex-1 flex-col overflow-hidden rounded-[10px] p-2", children: [
2830
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pt-4 pb-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: "Network" }) }),
2831
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex-1 overflow-y-auto", children: chains.map((chain) => {
2832
- const isSelected = selectedChainId === chain.id;
2833
- return /* @__PURE__ */ jsxRuntime.jsxs(
2834
- "button",
2835
- {
2836
- onClick: () => setSelectedChainId(chain.id),
2837
- className: chunkUHXVYWTF_cjs.cn(
2838
- "hover:bg-secondary flex w-full cursor-pointer items-center gap-2 rounded-lg px-3 py-2.5 text-left transition-colors",
2839
- isSelected && "bg-secondary"
2840
- ),
2841
- children: [
2842
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[18px] w-[18px] overflow-hidden rounded-full", children: getChainIcon(chain.id, 18) }),
2843
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground flex-1 text-sm", children: chain.name })
2844
- ]
2845
- },
2846
- chain.id
2847
- );
2848
- }) })
2849
- ] }),
2850
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted flex flex-[2] flex-col overflow-hidden rounded-[10px] p-2", children: [
2851
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pt-4 pb-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: "Token" }) }),
2852
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 flex-1 overflow-y-auto", children: chainTokens.map((token) => /* @__PURE__ */ jsxRuntime.jsx(
2853
- TokenRow,
2854
- {
2855
- token,
2856
- isSelected: selectedTokenId === token.id,
2857
- onClick: () => handleTokenSelect(token)
2858
- },
2859
- token.id
2860
- )) })
2861
- ] })
2862
- ] })
2863
- ] });
2864
- }
2865
- function ModalBody({
2866
- onViewChange,
2867
- onCloseBlockedChange,
2868
- showLockedFunds = true,
2869
- defaultTab = "deposit",
2870
- onDepositSuccess
2871
- }) {
2872
- const { defaultToken, tokensStatus } = chunkUHXVYWTF_cjs.usePrivanaContext();
2873
- const [selectedToken, setSelectedToken] = react.useState(defaultToken);
2874
- const [activeTab, setActiveTab] = react.useState(defaultTab);
2875
- const [currentView, setCurrentView] = react.useState("main");
2876
- const [isInteractionPending, setIsInteractionPending] = react.useState(false);
2877
- react.useEffect(() => {
2878
- if (!selectedToken && defaultToken) {
2879
- setSelectedToken(defaultToken);
2880
- }
2881
- }, [selectedToken, defaultToken]);
2882
- const handlePendingChange = (isPending) => {
2883
- setIsInteractionPending(isPending);
2884
- };
2885
- const handleCloseBlockedChange = (isBlocked) => {
2886
- onCloseBlockedChange?.(isBlocked);
2887
- };
2888
- const handleViewChange = (view) => {
2889
- const update = () => {
2890
- setCurrentView(view);
2891
- onViewChange?.(view);
2892
- };
2893
- if (typeof document !== "undefined" && typeof document.startViewTransition === "function") {
2894
- document.documentElement.dataset.privanaVtDir = view === "main" ? "back" : "forward";
2895
- const transition = document.startViewTransition(update);
2896
- transition.finished.then(() => {
2897
- delete document.documentElement.dataset.privanaVtDir;
2898
- });
2899
- } else {
2900
- update();
2901
- }
2902
- };
2903
- const handleTokenSelect = (token) => {
2904
- setSelectedToken(token);
2905
- };
2906
- if (tokensStatus === "loading" || !selectedToken) {
2907
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
2908
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-secondary h-25 animate-pulse rounded-[10px]" }),
2909
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-secondary h-11 animate-pulse rounded-[10px]" }),
2910
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-secondary h-50 animate-pulse rounded-[10px]" })
2911
- ] });
2912
- }
2913
- if (currentView === "locked-funds") {
2914
- return /* @__PURE__ */ jsxRuntime.jsx(LockedFundsView, { onBack: () => handleViewChange("main") });
2915
- }
2916
- if (currentView === "balance-details") {
2917
- return /* @__PURE__ */ jsxRuntime.jsx(BalanceDetailsView, { onBack: () => handleViewChange("main") });
2918
- }
2919
- if (currentView === "select-token") {
2920
- return /* @__PURE__ */ jsxRuntime.jsx(
2921
- TokenSelectorView,
2922
- {
2923
- onBack: () => handleViewChange("main"),
2924
- onSelect: handleTokenSelect,
2925
- selectedTokenId: selectedToken.id
2926
- }
2927
- );
2928
- }
2929
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 pb-4", children: [
2930
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkUHXVYWTF_cjs.cn(isInteractionPending && "pointer-events-none"), children: /* @__PURE__ */ jsxRuntime.jsx(
2931
- BalanceCards,
2932
- {
2933
- selectedToken,
2934
- onLockedFundsClick: () => handleViewChange("locked-funds"),
2935
- onBalanceClick: () => handleViewChange("balance-details"),
2936
- showLockedFunds,
2937
- disabled: isInteractionPending
2938
- }
2939
- ) }),
2940
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkUHXVYWTF_cjs.cn(isInteractionPending && "pointer-events-none"), children: /* @__PURE__ */ jsxRuntime.jsx(Tabs, { activeTab, onTabChange: setActiveTab, disabled: isInteractionPending }) }),
2941
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-muted rounded-[10px] p-5", children: activeTab === "deposit" ? /* @__PURE__ */ jsxRuntime.jsx(
2942
- DepositForm,
2943
- {
2944
- selectedToken,
2945
- onTokenSelect: () => handleViewChange("select-token"),
2946
- onPendingChange: handlePendingChange,
2947
- onUnsafeToCloseChange: handleCloseBlockedChange,
2948
- onSuccess: onDepositSuccess
2949
- }
2950
- ) : /* @__PURE__ */ jsxRuntime.jsx(
2951
- WithdrawForm,
2952
- {
2953
- selectedToken,
2954
- onTokenSelect: () => handleViewChange("select-token"),
2955
- onPendingChange: handlePendingChange,
2956
- onUnsafeToCloseChange: handleCloseBlockedChange
2957
- }
2958
- ) })
2959
- ] }) });
2960
- }
2961
- function PrivanaModal({
2962
- open,
2963
- onClose,
2964
- showLockedFunds,
2965
- defaultTab,
2966
- onDepositSuccess
2967
- }) {
2968
- const [currentView, setCurrentView] = react.useState("main");
2969
- const titleId = react.useId();
2970
- const descId = react.useId();
2971
- const [isCloseBlocked, setIsCloseBlocked] = react.useState(false);
2972
- const handleClose = () => {
2973
- if (!isCloseBlocked) onClose();
2974
- };
2975
- return /* @__PURE__ */ jsxRuntime.jsx(
2976
- Dialog,
2977
- {
2978
- open,
2979
- onOpenChange: (isOpen) => {
2980
- if (!isOpen) handleClose();
2981
- },
2982
- children: /* @__PURE__ */ jsxRuntime.jsxs(
2983
- DialogContent,
2984
- {
2985
- "data-privana": true,
2986
- "data-view": currentView,
2987
- showCloseButton: false,
2988
- onInteractOutside: isCloseBlocked ? (e) => e.preventDefault() : void 0,
2989
- onEscapeKeyDown: isCloseBlocked ? (e) => e.preventDefault() : void 0,
2990
- className: "bg-card flex h-[596px] max-h-[95dvh] w-[560px] max-w-[95vw] flex-col gap-2 overflow-hidden rounded-2xl border-0 p-2 pb-[2.75rem]",
2991
- "aria-labelledby": titleId,
2992
- "aria-describedby": descId,
2993
- children: [
2994
- /* @__PURE__ */ jsxRuntime.jsx(
2995
- "button",
2996
- {
2997
- "data-privana-close": true,
2998
- onClick: handleClose,
2999
- disabled: isCloseBlocked,
3000
- "aria-label": "Close",
3001
- className: chunkUHXVYWTF_cjs.cn(
3002
- "absolute top-6 right-5 z-20 flex h-6 w-6 items-center justify-center transition-colors",
3003
- isCloseBlocked ? "text-muted-foreground/40 cursor-not-allowed" : "text-muted-foreground hover:text-foreground cursor-pointer"
3004
- ),
3005
- children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {})
3006
- }
3007
- ),
3008
- /* @__PURE__ */ jsxRuntime.jsxs(
3009
- "div",
3010
- {
3011
- "data-privana-content": true,
3012
- "data-view": currentView,
3013
- className: "flex min-h-0 flex-1 flex-col gap-2",
3014
- children: [
3015
- /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { id: titleId, className: "sr-only", children: "Privana" }),
3016
- /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { id: descId, className: "sr-only", children: "Deposit or withdraw tokens from your Privana" }),
3017
- currentView === "main" && /* @__PURE__ */ jsxRuntime.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center px-5 py-4", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-xl leading-6 font-medium", children: "Privana" }) }) }),
3018
- /* @__PURE__ */ jsxRuntime.jsx(
3019
- ModalBody,
3020
- {
3021
- onCloseBlockedChange: setIsCloseBlocked,
3022
- onViewChange: setCurrentView,
3023
- showLockedFunds,
3024
- defaultTab,
3025
- onDepositSuccess
3026
- }
3027
- )
3028
- ]
3029
- }
3030
- ),
3031
- /* @__PURE__ */ jsxRuntime.jsx(
3032
- "a",
3033
- {
3034
- "data-privana-footer": true,
3035
- href: "https://privana.finance",
3036
- target: "_blank",
3037
- rel: "noopener noreferrer",
3038
- "aria-label": "Powered by Privana"
3039
- }
3040
- )
3041
- ]
3042
- }
3043
- )
3044
- }
3045
- );
2756
+ ) });
3046
2757
  }
3047
- function PrivanaInlineModal({
3048
- className,
3049
- showLockedFunds,
3050
- defaultTab,
3051
- onDepositSuccess
2758
+ function ChevronDownIcon({
2759
+ direction = "down",
2760
+ className
3052
2761
  }) {
3053
2762
  return /* @__PURE__ */ jsxRuntime.jsx(
3054
- "div",
2763
+ "svg",
3055
2764
  {
3056
- "data-privana": true,
3057
- className: chunkUHXVYWTF_cjs.cn(
3058
- "bg-card flex w-[560px] max-w-full flex-col gap-2 overflow-hidden rounded-2xl p-2 shadow-lg",
2765
+ width: "16",
2766
+ height: "16",
2767
+ viewBox: "0 0 16 16",
2768
+ fill: "none",
2769
+ className: chunkFGWMLLEC_cjs.cn(
2770
+ "transition-transform",
2771
+ direction === "right" && "-rotate-90",
2772
+ direction === "up" && "rotate-180",
3059
2773
  className
3060
2774
  ),
3061
2775
  children: /* @__PURE__ */ jsxRuntime.jsx(
3062
- ModalBody,
2776
+ "path",
3063
2777
  {
3064
- showLockedFunds,
3065
- defaultTab,
3066
- onDepositSuccess
2778
+ d: "M4 6l4 4 4-4",
2779
+ stroke: "currentColor",
2780
+ strokeWidth: "1.5",
2781
+ strokeLinecap: "round",
2782
+ strokeLinejoin: "round"
3067
2783
  }
3068
2784
  )
3069
2785
  }
3070
2786
  );
3071
2787
  }
3072
- function PrivanaButton({
3073
- children,
3074
- className,
3075
- variant = "outline",
3076
- size = "default",
3077
- asChild = false,
3078
- renderButton,
3079
- hideWhenDisconnected = true,
3080
- showLockedFunds = true,
3081
- defaultTab,
3082
- onDepositSuccess,
3083
- ...buttonProps
3084
- }) {
3085
- const [modalOpen, setModalOpen] = react.useState(false);
3086
- const { isConnected } = wagmi.useAccount();
3087
- if (hideWhenDisconnected && !isConnected) {
3088
- return null;
3089
- }
3090
- const handleClick = () => setModalOpen(true);
3091
- const buttonElement = renderButton ? renderButton({ onClick: handleClick, isOpen: modalOpen }) : /* @__PURE__ */ jsxRuntime.jsx(
3092
- chunkUHXVYWTF_cjs.Button,
2788
+ function CopyIcon() {
2789
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2790
+ "svg",
3093
2791
  {
3094
- variant,
3095
- size,
3096
- asChild,
3097
- className: chunkUHXVYWTF_cjs.cn(className),
3098
- onClick: handleClick,
3099
- disabled: !isConnected,
3100
- ...buttonProps,
3101
- children: children ?? "Privana"
2792
+ width: "16",
2793
+ height: "16",
2794
+ viewBox: "0 0 24 24",
2795
+ fill: "none",
2796
+ stroke: "currentColor",
2797
+ strokeWidth: "2",
2798
+ strokeLinecap: "round",
2799
+ strokeLinejoin: "round",
2800
+ children: [
2801
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
2802
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
2803
+ ]
3102
2804
  }
3103
2805
  );
3104
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-privana": true, className: "contents", children: [
3105
- buttonElement,
2806
+ }
2807
+ function CircleCheckIcon() {
2808
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
2809
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
2810
+ /* @__PURE__ */ jsxRuntime.jsx(
2811
+ "path",
2812
+ {
2813
+ d: "M6 10l2.5 2.5L14 7.5",
2814
+ stroke: "currentColor",
2815
+ strokeWidth: "1.5",
2816
+ strokeLinecap: "round",
2817
+ strokeLinejoin: "round"
2818
+ }
2819
+ )
2820
+ ] });
2821
+ }
2822
+ function CircleXIcon() {
2823
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
2824
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "9", stroke: "currentColor", strokeWidth: "1.5" }),
3106
2825
  /* @__PURE__ */ jsxRuntime.jsx(
3107
- PrivanaModal,
2826
+ "path",
3108
2827
  {
3109
- open: modalOpen,
3110
- onClose: () => setModalOpen(false),
3111
- showLockedFunds,
3112
- defaultTab,
3113
- onDepositSuccess
2828
+ d: "M7 7l6 6M13 7l-6 6",
2829
+ stroke: "currentColor",
2830
+ strokeWidth: "1.5",
2831
+ strokeLinecap: "round",
2832
+ strokeLinejoin: "round"
3114
2833
  }
3115
2834
  )
3116
2835
  ] });
3117
2836
  }
2837
+ function ArrowRightIcon({ className }) {
2838
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "8", viewBox: "0 0 24 8", fill: "none", className, children: /* @__PURE__ */ jsxRuntime.jsx(
2839
+ "path",
2840
+ {
2841
+ d: "M0 4h22m0 0l-4-4m4 4l-4 4",
2842
+ stroke: "currentColor",
2843
+ strokeWidth: "1.5",
2844
+ strokeLinecap: "round",
2845
+ strokeLinejoin: "round"
2846
+ }
2847
+ ) });
2848
+ }
3118
2849
  var DEFAULT_MOONPAY_API_URL = "https://api.moonpay.com/v3";
3119
2850
  function useMoonpayLimits({
3120
2851
  currencyCode,
@@ -3137,119 +2868,25 @@ function useMoonpayLimits({
3137
2868
  areFeesIncluded: "true"
3138
2869
  });
3139
2870
  const res = await fetch(
3140
- `${apiBaseUrl}/currencies/${currencyCode}/limits?${params.toString()}`
3141
- );
3142
- if (!res.ok) {
3143
- throw new Error(`MoonPay limits request failed: ${res.status}`);
3144
- }
3145
- const data = await res.json();
3146
- const asNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
3147
- return {
3148
- minBuyAmount: asNumber(data.baseCurrency?.minBuyAmount),
3149
- maxBuyAmount: asNumber(data.baseCurrency?.maxBuyAmount)
3150
- };
3151
- }
3152
- });
3153
- return {
3154
- minBuyAmount: query.data?.minBuyAmount,
3155
- maxBuyAmount: query.data?.maxBuyAmount,
3156
- isLoading: query.isLoading,
3157
- error: query.error ?? null
3158
- };
3159
- }
3160
- function TokenSelectorView2({ selectedTokenId, onSelect }) {
3161
- const { enabledTokens } = chunkUHXVYWTF_cjs.usePrivanaContext();
3162
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-muted flex flex-col rounded-[10px] p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-h-72 flex-col gap-1 overflow-y-auto", children: [
3163
- enabledTokens.map((token) => {
3164
- const isSelected = selectedTokenId === token.id;
3165
- return /* @__PURE__ */ jsxRuntime.jsxs(
3166
- "button",
3167
- {
3168
- type: "button",
3169
- onClick: () => onSelect(token.id),
3170
- className: chunkUHXVYWTF_cjs.cn(
3171
- "hover:bg-secondary flex w-full cursor-pointer items-center gap-3 rounded-lg px-3 py-2 text-left transition-colors",
3172
- isSelected && "bg-secondary"
3173
- ),
3174
- children: [
3175
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 w-6 shrink-0 overflow-hidden rounded-full", children: getTokenIcon(token.symbol, 24) }),
3176
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
3177
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-foreground text-sm font-medium", children: token.symbol }),
3178
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground text-[11px]", children: token.name })
3179
- ] }),
3180
- isSelected && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-primary flex h-4 w-4 shrink-0 items-center justify-center rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx(
3181
- "svg",
3182
- {
3183
- width: "10",
3184
- height: "10",
3185
- viewBox: "0 0 10 10",
3186
- fill: "none",
3187
- className: "text-primary-foreground",
3188
- children: /* @__PURE__ */ jsxRuntime.jsx(
3189
- "path",
3190
- {
3191
- d: "M2 5L4 7L8 3",
3192
- stroke: "currentColor",
3193
- strokeWidth: "1.5",
3194
- strokeLinecap: "round",
3195
- strokeLinejoin: "round"
3196
- }
3197
- )
3198
- }
3199
- ) })
3200
- ]
3201
- },
3202
- token.id
3203
- );
3204
- }),
3205
- enabledTokens.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground px-3 py-6 text-center text-sm", children: "No tokens available" })
3206
- ] }) });
3207
- }
3208
- function CreditCardWidgetView({
3209
- token,
3210
- amount,
3211
- allowance,
3212
- onCredited,
3213
- onLockSubmitted,
3214
- onLockFailed
3215
- }) {
3216
- const moonpayCurrencyCode = token?.moonpayCurrencyCode;
3217
- const containerRef = react.useRef(null);
3218
- const [widgetTheme, setWidgetTheme] = react.useState();
3219
- react.useEffect(() => {
3220
- if (containerRef.current) setWidgetTheme(resolveSdkTheme(containerRef.current));
3221
- }, []);
3222
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: [
3223
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: "Complete your purchase" }),
3224
- token && moonpayCurrencyCode ? /* @__PURE__ */ jsxRuntime.jsx(
3225
- chunkUHXVYWTF_cjs.FiatOnRampForm,
3226
- {
3227
- tokenId: token.id,
3228
- currencyCode: moonpayCurrencyCode,
3229
- quoteCurrencyAmount: amount || void 0,
3230
- lockAmount: true,
3231
- variant: "embedded",
3232
- autoStart: true,
3233
- theme: widgetTheme,
3234
- postDepositLock: allowance ? {
3235
- maxAmount: BigInt(allowance.value),
3236
- lockDuration: allowance.lockDuration
3237
- } : void 0,
3238
- onCredited,
3239
- onLockSubmitted,
3240
- onLockFailed
3241
- }
3242
- ) : /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-muted-foreground text-sm", children: [
3243
- token?.symbol ?? "This token",
3244
- " isn\u2019t available for card purchases yet."
3245
- ] })
3246
- ] });
3247
- }
3248
- function resolveSdkTheme(el) {
3249
- const scheme = getComputedStyle(el).colorScheme;
3250
- if (scheme === "dark") return "dark";
3251
- if (scheme === "light") return "light";
3252
- return el.closest(".dark") ? "dark" : "light";
2871
+ `${apiBaseUrl}/currencies/${currencyCode}/limits?${params.toString()}`
2872
+ );
2873
+ if (!res.ok) {
2874
+ throw new Error(`MoonPay limits request failed: ${res.status}`);
2875
+ }
2876
+ const data = await res.json();
2877
+ const asNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
2878
+ return {
2879
+ minBuyAmount: asNumber(data.baseCurrency?.minBuyAmount),
2880
+ maxBuyAmount: asNumber(data.baseCurrency?.maxBuyAmount)
2881
+ };
2882
+ }
2883
+ });
2884
+ return {
2885
+ minBuyAmount: query.data?.minBuyAmount,
2886
+ maxBuyAmount: query.data?.maxBuyAmount,
2887
+ isLoading: query.isLoading,
2888
+ error: query.error ?? null
2889
+ };
3253
2890
  }
3254
2891
  function PrivanaIcon({ className, size = 32 }) {
3255
2892
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -3282,7 +2919,7 @@ function PolicyTermRow({
3282
2919
  /* @__PURE__ */ jsxRuntime.jsx(
3283
2920
  "div",
3284
2921
  {
3285
- className: chunkUHXVYWTF_cjs.cn(
2922
+ className: chunkFGWMLLEC_cjs.cn(
3286
2923
  "mt-0.5 shrink-0",
3287
2924
  kind === "permission" ? "text-emerald-500" : "text-orange-500"
3288
2925
  ),
@@ -3343,91 +2980,26 @@ function AllowancePolicySection({
3343
2980
  ] })
3344
2981
  ] });
3345
2982
  }
3346
- function MoonPayGate({ enabled, children }) {
3347
- const { networkConfig } = chunkUHXVYWTF_cjs.usePrivanaContext();
3348
- const apiKey = networkConfig.moonpayApiKey;
3349
- if (!enabled || !apiKey) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
3350
- return /* @__PURE__ */ jsxRuntime.jsx(moonpayReact.MoonPayProvider, { apiKey, children });
3351
- }
3352
- function MethodTabs({
3353
- activeTab,
3354
- onTabChange
3355
- }) {
3356
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-secondary relative flex gap-2 overflow-hidden rounded-[10px] p-1", children: [
3357
- /* @__PURE__ */ jsxRuntime.jsx(
3358
- "div",
3359
- {
3360
- className: chunkUHXVYWTF_cjs.cn(
3361
- "bg-input absolute top-1 bottom-1 left-1 w-[calc(50%-8px)] rounded-md transition-transform duration-200",
3362
- activeTab === "credit-card" && "translate-x-[calc(100%+8px)]"
3363
- )
3364
- }
3365
- ),
3366
- /* @__PURE__ */ jsxRuntime.jsx(
3367
- "button",
3368
- {
3369
- type: "button",
3370
- onClick: () => onTabChange("crypto"),
3371
- className: chunkUHXVYWTF_cjs.cn(
3372
- "relative z-10 flex-1 cursor-pointer rounded-md px-3 py-[9px] text-sm font-medium transition-colors",
3373
- activeTab === "crypto" ? "text-foreground" : "text-muted-foreground"
3374
- ),
3375
- children: "Crypto"
3376
- }
3377
- ),
3378
- /* @__PURE__ */ jsxRuntime.jsx(
3379
- "button",
3380
- {
3381
- type: "button",
3382
- onClick: () => onTabChange("credit-card"),
3383
- className: chunkUHXVYWTF_cjs.cn(
3384
- "relative z-10 flex-1 cursor-pointer rounded-md px-3 py-[9px] text-sm font-medium transition-colors",
3385
- activeTab === "credit-card" ? "text-foreground" : "text-muted-foreground"
3386
- ),
3387
- children: "Credit Card"
3388
- }
3389
- )
3390
- ] });
3391
- }
3392
- function MethodOption({
3393
- title,
3394
- description,
3395
- onClick
3396
- }) {
3397
- return /* @__PURE__ */ jsxRuntime.jsxs(
3398
- "button",
3399
- {
3400
- type: "button",
3401
- onClick,
3402
- className: "bg-input hover:bg-input/70 border-border flex w-full cursor-pointer items-center gap-3 rounded-lg border p-3 text-left transition-colors",
3403
- children: [
3404
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
3405
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-sm leading-[14px] font-medium", children: title }),
3406
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs leading-3", children: description })
3407
- ] }),
3408
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground flex h-5 w-5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, {}) })
3409
- ]
3410
- }
3411
- );
3412
- }
3413
2983
  function DepositView({
3414
2984
  source,
3415
2985
  selectedToken,
3416
2986
  amount,
3417
2987
  allowance,
2988
+ externalMinimum,
3418
2989
  onAmountChange,
3419
2990
  onSelectToken,
3420
2991
  onConnectWallet,
3421
2992
  onSubmit,
3422
2993
  isSubmitting = false
3423
2994
  }) {
3424
- const { getChainById: getChainById2, chains, serviceName, serviceIcon, networkConfig } = chunkUHXVYWTF_cjs.usePrivanaContext();
2995
+ const { getChainById: getChainById2, chains, serviceName, serviceIcon, networkConfig, hostedAuthConfig } = chunkFGWMLLEC_cjs.usePrivanaContext();
3425
2996
  const { address, isConnected } = wagmi.useAccount();
3426
2997
  const appName = serviceName ?? "Privana";
3427
2998
  const chain = selectedToken ? getChainById2(selectedToken.chainId) : void 0;
3428
2999
  const targetChain = chain ?? chains[0];
3429
3000
  const sourceLabel = source === "connected" ? "Connected Wallet" : "External Wallet";
3430
3001
  const isConnectedSource = source === "connected";
3002
+ const isExternal = source === "external";
3431
3003
  const isCreditCard = source === "credit-card";
3432
3004
  const isNative = selectedToken?.contract === viem.zeroAddress;
3433
3005
  const { data: nativeBalanceData } = wagmi.useBalance({
@@ -3444,7 +3016,7 @@ function DepositView({
3444
3016
  query: { enabled: isConnectedSource && !!address && !!selectedToken && !isNative }
3445
3017
  });
3446
3018
  const walletBalance = isNative ? nativeBalanceData?.value : erc20Balance;
3447
- const formattedWalletBalance = walletBalance != null && selectedToken ? chunkUHXVYWTF_cjs.formatTokenAmount(walletBalance.toString(), selectedToken.decimals) : "0.00";
3019
+ const formattedWalletBalance = walletBalance != null && selectedToken ? chunkFGWMLLEC_cjs.formatTokenAmount(walletBalance.toString(), selectedToken.decimals) : "0.00";
3448
3020
  const {
3449
3021
  minBuyAmount: moonpayMinBuy,
3450
3022
  isLoading: moonpayLimitsLoading,
@@ -3457,12 +3029,18 @@ function DepositView({
3457
3029
  const hasValidAmount = !!amount && parseFloat(amount) > 0;
3458
3030
  const maxAmountDecimals = isCreditCard ? 2 : selectedToken?.decimals;
3459
3031
  const tooManyDecimals = hasValidAmount && maxAmountDecimals != null && amount.includes(".") && amount.split(".")[1].length > maxAmountDecimals;
3460
- const exceedsBalance = isConnectedSource && hasValidAmount && !tooManyDecimals && !!selectedToken && walletBalance != null && chunkUHXVYWTF_cjs.parseTokenAmount(amount, selectedToken.decimals) > walletBalance;
3032
+ const exceedsBalance = isConnectedSource && hasValidAmount && !tooManyDecimals && !!selectedToken && walletBalance != null && chunkFGWMLLEC_cjs.parseTokenAmount(amount, selectedToken.decimals) > walletBalance;
3461
3033
  const belowMoonpayMin = isCreditCard && hasValidAmount && moonpayMinBuy != null && parseFloat(amount) < moonpayMinBuy;
3462
3034
  const moonpayLimitsUnready = isCreditCard && !!selectedToken?.moonpayCurrencyCode && moonpayMinBuy == null;
3463
3035
  const creditCardUnavailable = isCreditCard && !!selectedToken && !selectedToken.moonpayCurrencyCode;
3464
- const needsConnect = isConnectedSource && !isConnected;
3465
- const canDeposit = hasValidAmount && !!selectedToken && !tooManyDecimals && !exceedsBalance && !belowMoonpayMin && !moonpayLimitsUnready && !creditCardUnavailable && !needsConnect;
3036
+ const externalTokenUnavailable = isExternal && !!selectedToken && isNative;
3037
+ const externalMinimumRequired = isExternal && !!allowance && !!selectedToken;
3038
+ const externalMinimumLoading = externalMinimumRequired && externalMinimum === void 0;
3039
+ const externalMinimumUnavailable = externalMinimumRequired && externalMinimum === null;
3040
+ const belowExternalMinimum = externalMinimumRequired && hasValidAmount && !tooManyDecimals && !!selectedToken && typeof externalMinimum === "bigint" && chunkFGWMLLEC_cjs.parseTokenAmount(amount, selectedToken.decimals) < externalMinimum;
3041
+ const externalNeedsWallet = isExternal && (!!allowance || !hostedAuthConfig);
3042
+ const needsConnect = (isConnectedSource || externalNeedsWallet) && !isConnected;
3043
+ const canDeposit = hasValidAmount && !!selectedToken && !tooManyDecimals && !exceedsBalance && !belowMoonpayMin && !moonpayLimitsUnready && !creditCardUnavailable && !externalTokenUnavailable && !externalMinimumLoading && !externalMinimumUnavailable && !belowExternalMinimum && !needsConnect;
3466
3044
  const handleMax = () => {
3467
3045
  const max = formattedWalletBalance.replace(/\s/g, "");
3468
3046
  if (parseFloat(max) > 0) onAmountChange(max);
@@ -3471,9 +3049,12 @@ function DepositView({
3471
3049
  isCreditCard ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
3472
3050
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: "Buy with credit card and deposit" }),
3473
3051
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: "Enter your deposit amount and proceed to sign a policy." })
3474
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: [
3475
- "Deposit from ",
3476
- sourceLabel
3052
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
3053
+ /* @__PURE__ */ jsxRuntime.jsxs("h2", { className: "text-foreground text-[28px] leading-8 font-medium", children: [
3054
+ "Deposit from ",
3055
+ sourceLabel
3056
+ ] }),
3057
+ allowance && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: "Enter your deposit amount and proceed to sign a policy." })
3477
3058
  ] }),
3478
3059
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
3479
3060
  /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-muted-foreground text-sm", children: "Token" }),
@@ -3482,7 +3063,8 @@ function DepositView({
3482
3063
  {
3483
3064
  type: "button",
3484
3065
  onClick: onSelectToken,
3485
- className: "border-border bg-input flex w-full cursor-pointer items-center gap-3 rounded-lg border p-3 text-left",
3066
+ disabled: isSubmitting,
3067
+ className: "border-border bg-input flex w-full cursor-pointer items-center gap-3 rounded-lg border p-3 text-left disabled:cursor-not-allowed disabled:opacity-50",
3486
3068
  children: [
3487
3069
  selectedToken ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3488
3070
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 w-8 shrink-0 overflow-hidden rounded-full", children: getTokenIcon(selectedToken.symbol, 32) }),
@@ -3512,7 +3094,7 @@ function DepositView({
3512
3094
  /* @__PURE__ */ jsxRuntime.jsxs(
3513
3095
  "div",
3514
3096
  {
3515
- className: chunkUHXVYWTF_cjs.cn(
3097
+ className: chunkFGWMLLEC_cjs.cn(
3516
3098
  "border-border bg-input flex items-center gap-2 rounded-[10px] border",
3517
3099
  isConnectedSource ? "py-1 pr-1 pl-3" : "px-3 py-3"
3518
3100
  ),
@@ -3523,6 +3105,7 @@ function DepositView({
3523
3105
  type: "text",
3524
3106
  inputMode: "decimal",
3525
3107
  placeholder: "Enter Amount",
3108
+ disabled: isSubmitting,
3526
3109
  value: amount,
3527
3110
  onChange: (e) => {
3528
3111
  const value = e.target.value.replace(/[^0-9.,]/g, "").replace(/,/g, ".");
@@ -3554,11 +3137,24 @@ function DepositView({
3554
3137
  moonpayMinBuy,
3555
3138
  " USD."
3556
3139
  ] }),
3140
+ belowExternalMinimum && selectedToken && typeof externalMinimum === "bigint" && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-destructive text-sm", children: [
3141
+ "Minimum deposit is ",
3142
+ viem.formatUnits(externalMinimum, selectedToken.decimals),
3143
+ " ",
3144
+ selectedToken.symbol,
3145
+ "."
3146
+ ] }),
3147
+ externalMinimumLoading && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: "Checking minimum deposit\u2026" }),
3148
+ externalMinimumUnavailable && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-destructive text-sm", children: "Couldn\u2019t load the minimum deposit. Please try again." }),
3557
3149
  isCreditCard && moonpayLimitsError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-destructive text-sm", children: "Couldn\u2019t load purchase limits. Please try again." }),
3558
3150
  isCreditCard && moonpayLimitsLoading && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: "Checking purchase limits\u2026" }),
3559
3151
  creditCardUnavailable && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-destructive text-sm", children: [
3560
3152
  selectedToken?.symbol ?? "This token",
3561
3153
  " isn\u2019t available for card purchases yet."
3154
+ ] }),
3155
+ externalTokenUnavailable && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-destructive text-sm", children: [
3156
+ selectedToken?.symbol ?? "This token",
3157
+ " can\u2019t be used for external deposits. Choose an ERC20 token."
3562
3158
  ] })
3563
3159
  ] }),
3564
3160
  allowance && /* @__PURE__ */ jsxRuntime.jsx(
@@ -3633,19 +3229,33 @@ function AwaitingDepositStatus({
3633
3229
  function ExternalDepositView({
3634
3230
  token,
3635
3231
  amount,
3636
- onCredited
3232
+ depositAddressState,
3233
+ onCredited,
3234
+ onDiscardLock,
3235
+ lock
3637
3236
  }) {
3638
- const { getChainById: getChainById2 } = chunkUHXVYWTF_cjs.usePrivanaContext();
3639
- const { depositAddress, isReady, isLoading } = useDepositAddress();
3237
+ const { getChainById: getChainById2, getTokenById, serviceName } = chunkFGWMLLEC_cjs.usePrivanaContext();
3238
+ const appName = serviceName ?? "Privana";
3239
+ const { depositAddress, isReady, isLoading } = depositAddressState;
3640
3240
  const chain = token ? getChainById2(token.chainId) : void 0;
3241
+ const lockSession = lock?.session;
3242
+ const recordVerification = lock?.recordVerification;
3243
+ const settleAfterCredit = lock?.settleAfterCredit;
3244
+ const retryAfterCredit = lock?.retryAfterCredit;
3245
+ const discoveryToken = lockSession ? getTokenById(lockSession.tokenId) : token;
3641
3246
  const [copied, setCopied] = react.useState(false);
3642
3247
  const [deadline] = react.useState(() => Date.now() + LISTENING_WINDOW_MS);
3643
3248
  const secondsLeft = useCountdown(deadline);
3644
3249
  const listening = secondsLeft > 0;
3645
3250
  const [nothingFound, setNothingFound] = react.useState(false);
3646
3251
  const [credited, setCredited] = react.useState(null);
3647
- const verification = chunkUHXVYWTF_cjs.useDepositVerification({
3648
- onCredited: (txHash) => {
3252
+ const [showCancelWarning, setShowCancelWarning] = react.useState(false);
3253
+ const verification = chunkFGWMLLEC_cjs.useDepositVerification({
3254
+ onCredited: (txHash, _response, creditedAmount) => {
3255
+ if (settleAfterCredit) {
3256
+ void settleAfterCredit(txHash, creditedAmount);
3257
+ return;
3258
+ }
3649
3259
  if (onCredited) {
3650
3260
  onCredited();
3651
3261
  return;
@@ -3653,8 +3263,9 @@ function ExternalDepositView({
3653
3263
  setCredited({ txHash });
3654
3264
  }
3655
3265
  });
3656
- const { isVerifying, verificationFailed, didTimeout, verify } = verification;
3657
- const scanPaused = isVerifying || verificationFailed || didTimeout || !!credited;
3266
+ const { isVerifying, verificationFailed, canCheckAnotherTransfer, didTimeout, verify } = verification;
3267
+ const scanPaused = isVerifying || verificationFailed || didTimeout || !!credited || !!lock?.isSigning || !!lock?.isSubmittingLock || !!lockSession?.verification || !!lockSession?.creditedAmount;
3268
+ const showDepositInstructions = !credited && !lockSession?.creditedAmount;
3658
3269
  const {
3659
3270
  pending,
3660
3271
  isFetching: isScanning,
@@ -3663,23 +3274,58 @@ function ExternalDepositView({
3663
3274
  isUnavailable,
3664
3275
  refetch: refetchPendingDeposits
3665
3276
  } = usePendingDeposits({
3666
- chainId: token?.chainId,
3667
- enabled: isReady && !!depositAddress && !!token,
3277
+ chainId: discoveryToken?.chainId,
3278
+ tokenAddress: discoveryToken?.contract === viem.zeroAddress ? void 0 : discoveryToken?.contract,
3279
+ enabled: isReady && !!depositAddress && !!discoveryToken && discoveryToken.contract !== viem.zeroAddress,
3668
3280
  refetchInterval: listening && !scanPaused ? 3e4 : false
3669
3281
  });
3670
3282
  const processedRef = react.useRef(/* @__PURE__ */ new Set());
3283
+ const verificationRunRef = react.useRef(null);
3284
+ react.useEffect(
3285
+ () => () => {
3286
+ verificationRunRef.current = null;
3287
+ },
3288
+ []
3289
+ );
3290
+ react.useEffect(() => {
3291
+ const stored = lockSession?.verification;
3292
+ if (!stored || lockSession.creditedAmount || isVerifying || verificationFailed || didTimeout) {
3293
+ return;
3294
+ }
3295
+ const key = `${lockSession.generation}:${stored.chainId}:${stored.hash}:${stored.logIndex ?? 0}`;
3296
+ if (verificationRunRef.current === key) return;
3297
+ verificationRunRef.current = key;
3298
+ processedRef.current.add(`${stored.hash}:${stored.logIndex ?? 0}`);
3299
+ void verify({
3300
+ hash: stored.hash,
3301
+ chainId: stored.chainId,
3302
+ amount: BigInt(stored.amount),
3303
+ logIndex: stored.logIndex
3304
+ });
3305
+ }, [didTimeout, isVerifying, lockSession, verificationFailed, verify]);
3671
3306
  react.useEffect(() => {
3672
3307
  if (scanPaused) return;
3673
- const next = [...pending].sort((a, b) => a.block_number - b.block_number).find((d) => !processedRef.current.has(`${d.tx_hash}:${d.log_index}`));
3308
+ const next = [...pending].sort((a, b) => a.block_number - b.block_number).find(
3309
+ (deposit) => (!lockSession || isExternalDepositBlockInSession(lockSession, deposit.block_number)) && !processedRef.current.has(`${deposit.tx_hash}:${deposit.log_index}`)
3310
+ );
3674
3311
  if (!next) return;
3675
- processedRef.current.add(`${next.tx_hash}:${next.log_index}`);
3676
- void verify({
3312
+ const context = {
3677
3313
  hash: next.tx_hash,
3678
3314
  chainId: next.chain_id,
3679
3315
  amount: BigInt(next.amount),
3680
3316
  logIndex: next.log_index
3681
- });
3682
- }, [pending, scanPaused, verify]);
3317
+ };
3318
+ if (recordVerification) {
3319
+ try {
3320
+ recordVerification(context);
3321
+ } catch (err) {
3322
+ sonner.toast.error(err instanceof Error ? err.message : "Unable to save deposit recovery state");
3323
+ return;
3324
+ }
3325
+ }
3326
+ processedRef.current.add(`${next.tx_hash}:${next.log_index}`);
3327
+ if (!recordVerification) void verify(context);
3328
+ }, [lockSession, pending, recordVerification, scanPaused, verify]);
3683
3329
  const nothingFoundTimerRef = react.useRef(void 0);
3684
3330
  react.useEffect(() => () => clearTimeout(nothingFoundTimerRef.current), []);
3685
3331
  const handleRefresh = () => {
@@ -3692,11 +3338,27 @@ function ExternalDepositView({
3692
3338
  }
3693
3339
  });
3694
3340
  };
3695
- const handleCopy = () => {
3341
+ const handleCopy = async () => {
3696
3342
  if (!depositAddress) return;
3697
- void navigator.clipboard.writeText(depositAddress);
3698
- setCopied(true);
3699
- setTimeout(() => setCopied(false), 2e3);
3343
+ try {
3344
+ await navigator.clipboard.writeText(depositAddress);
3345
+ setCopied(true);
3346
+ setTimeout(() => setCopied(false), 2e3);
3347
+ } catch {
3348
+ sonner.toast.error("Unable to copy the deposit address");
3349
+ }
3350
+ };
3351
+ const handleCheckAnotherTransfer = () => {
3352
+ try {
3353
+ if (!lock?.clearVerification()) {
3354
+ sonner.toast.error("Deposit recovery changed in another tab. Please review the current state.");
3355
+ return;
3356
+ }
3357
+ verificationRunRef.current = null;
3358
+ verification.reset();
3359
+ } catch (err) {
3360
+ sonner.toast.error(err instanceof Error ? err.message : "Unable to continue deposit discovery");
3361
+ }
3700
3362
  };
3701
3363
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: [
3702
3364
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
@@ -3710,31 +3372,68 @@ function ExternalDepositView({
3710
3372
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-border h-px w-full" }),
3711
3373
  /* @__PURE__ */ jsxRuntime.jsx(SummaryRow, { value: amount || "\u2014", label: "Value" })
3712
3374
  ] }),
3713
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-secondary flex h-50 items-center justify-center rounded-[10px]", children: !isReady ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground px-6 text-center text-sm", children: "Connect your wallet to generate a deposit address." }) : depositAddress ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-[10px] bg-white p-3", children: /* @__PURE__ */ jsxRuntime.jsx(qrcode_react.QRCodeSVG, { value: depositAddress, size: 160 }) }) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(chunkUHXVYWTF_cjs.Skeleton, { className: "h-full w-full rounded-[10px]" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: "Deposit address unavailable" }) }),
3714
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
3715
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: "Deposit Address" }),
3716
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
3717
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-border flex h-10 min-w-0 flex-1 items-center rounded-[10px] border px-3", children: depositAddress ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground min-w-0 flex-1 truncate text-sm", children: depositAddress }) : isReady && isLoading ? /* @__PURE__ */ jsxRuntime.jsx(chunkUHXVYWTF_cjs.Skeleton, { className: "h-4 w-3/4" }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: "\u2014" }) }),
3718
- /* @__PURE__ */ jsxRuntime.jsxs(
3719
- "button",
3720
- {
3721
- type: "button",
3722
- onClick: handleCopy,
3723
- disabled: !depositAddress,
3724
- className: "bg-primary text-primary-foreground hover:bg-primary/90 flex h-10 shrink-0 cursor-pointer items-center gap-2 rounded-[10px] px-3 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
3725
- children: [
3726
- /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, {}),
3727
- copied ? "Copied" : "Copy"
3728
- ]
3729
- }
3730
- )
3375
+ showDepositInstructions && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3376
+ !scanPaused && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: "Send the displayed amount in one transfer. Transfers below the minimum are not combined or automatically returned." }),
3377
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-secondary flex h-50 items-center justify-center rounded-[10px]", children: !isReady ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground px-6 text-center text-sm", children: "Connect your wallet to generate a deposit address." }) : depositAddress ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-[10px] bg-white p-3", children: /* @__PURE__ */ jsxRuntime.jsx(qrcode_react.QRCodeSVG, { value: depositAddress, size: 160 }) }) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(chunkFGWMLLEC_cjs.Skeleton, { className: "h-full w-full rounded-[10px]" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: "Deposit address unavailable" }) }),
3378
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
3379
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: "Deposit Address" }),
3380
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
3381
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-border flex h-10 min-w-0 flex-1 items-center rounded-[10px] border px-3", children: depositAddress ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground min-w-0 flex-1 truncate text-sm", children: depositAddress }) : isReady && isLoading ? /* @__PURE__ */ jsxRuntime.jsx(chunkFGWMLLEC_cjs.Skeleton, { className: "h-4 w-3/4" }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-sm", children: "\u2014" }) }),
3382
+ /* @__PURE__ */ jsxRuntime.jsxs(
3383
+ "button",
3384
+ {
3385
+ type: "button",
3386
+ onClick: handleCopy,
3387
+ disabled: !depositAddress,
3388
+ className: "bg-primary text-primary-foreground hover:bg-primary/90 flex h-10 shrink-0 cursor-pointer items-center gap-2 rounded-[10px] px-3 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
3389
+ children: [
3390
+ /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, {}),
3391
+ copied ? "Copied" : "Copy"
3392
+ ]
3393
+ }
3394
+ )
3395
+ ] })
3731
3396
  ] })
3732
3397
  ] }),
3733
- credited ? /* @__PURE__ */ jsxRuntime.jsx(
3398
+ showCancelWarning && lockSession && !lockSession.verification && !lockSession.creditedAmount ? /* @__PURE__ */ jsxRuntime.jsx(
3399
+ TransactionWarningView,
3400
+ {
3401
+ title: "Cancel this deposit?",
3402
+ message: "Only cancel if you have not sent funds. Canceling after a transfer was sent stops recovery and can leave the transfer uncredited or unlocked.",
3403
+ onDone: () => onDiscardLock?.(),
3404
+ actionLabel: "I haven\u2019t sent funds",
3405
+ onDismiss: () => setShowCancelWarning(false),
3406
+ dismissLabel: "Keep waiting"
3407
+ }
3408
+ ) : lock?.isSigning ? /* @__PURE__ */ jsxRuntime.jsx(
3409
+ AwaitingDepositStatus,
3410
+ {
3411
+ title: "Confirm policy in your wallet",
3412
+ subtitle: "Sign a fresh policy for the funds already credited."
3413
+ }
3414
+ ) : lock?.isSubmittingLock ? /* @__PURE__ */ jsxRuntime.jsx(
3415
+ AwaitingDepositStatus,
3416
+ {
3417
+ title: `Locking funds for ${appName}`,
3418
+ subtitle: "Deposit credited. Applying your signed policy\u2026"
3419
+ }
3420
+ ) : lock?.session?.creditedAmount ? /* @__PURE__ */ jsxRuntime.jsx(
3421
+ TransactionWarningView,
3422
+ {
3423
+ title: lock.session.submissionAmbiguous ? "Lock status unknown" : "Deposit credited",
3424
+ message: lock.session.submissionAmbiguous ? "The lock may already have succeeded. Retry only the saved signature, or check locked funds before stopping recovery." : "The deposit is credited, but its signed lock still needs to be submitted.",
3425
+ onDone: () => {
3426
+ void retryAfterCredit?.().catch((err) => {
3427
+ sonner.toast.error(err instanceof Error ? err.message : "Policy recovery failed");
3428
+ });
3429
+ },
3430
+ actionLabel: lock.session.payload ? "Retry lock submission" : "Sign policy and lock funds"
3431
+ }
3432
+ ) : credited ? /* @__PURE__ */ jsxRuntime.jsx(
3734
3433
  TransactionSuccessView,
3735
3434
  {
3736
3435
  title: "Deposit Credited",
3737
- message: `Transfer ${chunkUHXVYWTF_cjs.shortenAddress(credited.txHash)} has been credited to your Privana balance.`,
3436
+ message: `Transfer ${chunkFGWMLLEC_cjs.shortenAddress(credited.txHash)} has been credited to your Privana balance.`,
3738
3437
  onDone: () => {
3739
3438
  setCredited(null);
3740
3439
  verification.reset();
@@ -3747,14 +3446,15 @@ function ExternalDepositView({
3747
3446
  title: "Could not verify deposit",
3748
3447
  message: didTimeout ? "Verification timed out \u2014 your deposit may still be credited in the background." : verification.error?.message ?? "Your transfer was found but could not be verified.",
3749
3448
  onRetry: () => void verification.retryVerification(),
3750
- onDismiss: () => verification.reset(),
3449
+ onDismiss: lock ? canCheckAnotherTransfer ? handleCheckAnotherTransfer : void 0 : () => verification.reset(),
3450
+ dismissLabel: lock && canCheckAnotherTransfer ? "Check another transfer" : void 0,
3751
3451
  isRetrying: isVerifying
3752
3452
  }
3753
3453
  ) : isVerifying ? /* @__PURE__ */ jsxRuntime.jsx(
3754
3454
  AwaitingDepositStatus,
3755
3455
  {
3756
3456
  title: "Deposit detected",
3757
- subtitle: "Crediting the incoming transaction to your Privana balance..."
3457
+ subtitle: "Crediting the incoming transaction to your Privana balance\u2026"
3758
3458
  }
3759
3459
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3760
3460
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -3762,7 +3462,7 @@ function ExternalDepositView({
3762
3462
  {
3763
3463
  title: "Awaiting Deposit",
3764
3464
  subtitle: listening ? "We are listening for your incoming transaction for the next hour." : "We've stopped listening automatically. Use the button below to check for your deposit.",
3765
- remaining: listening ? chunkUHXVYWTF_cjs.formatCountdown(secondsLeft) : void 0
3465
+ remaining: listening ? chunkFGWMLLEC_cjs.formatCountdown(secondsLeft) : void 0
3766
3466
  }
3767
3467
  ),
3768
3468
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
@@ -3776,11 +3476,95 @@ function ExternalDepositView({
3776
3476
  children: "Refresh deposit status"
3777
3477
  }
3778
3478
  ),
3779
- isRateLimited ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Checked too recently \u2014 try again in a moment." }) : isUnavailable ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Deposit discovery is unavailable for this chain." }) : isScanError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Chain temporarily unreachable \u2014 retrying automatically." }) : nothingFound ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-center text-sm", children: "No incoming transaction found yet." }) : null
3479
+ lockSession && !lockSession.verification && !lockSession.creditedAmount && /* @__PURE__ */ jsxRuntime.jsx(
3480
+ "button",
3481
+ {
3482
+ type: "button",
3483
+ onClick: () => setShowCancelWarning(true),
3484
+ className: "border-border text-foreground hover:bg-secondary flex h-10 w-full cursor-pointer items-center justify-center rounded-[10px] border px-3 py-2 text-sm font-medium transition-colors",
3485
+ children: "Cancel deposit"
3486
+ }
3487
+ ),
3488
+ isRateLimited ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Checked too recently. Try again in a moment." }) : isUnavailable ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Deposit discovery is unavailable for this chain." }) : isScanError ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Chain temporarily unreachable. Retrying automatically." }) : nothingFound ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-center text-sm", children: "No incoming transaction found yet." }) : null
3780
3489
  ] })
3781
3490
  ] })
3782
3491
  ] });
3783
3492
  }
3493
+ function MoonPayGate({ enabled, children }) {
3494
+ const { networkConfig } = chunkFGWMLLEC_cjs.usePrivanaContext();
3495
+ const apiKey = networkConfig.moonpayApiKey;
3496
+ if (!enabled || !apiKey) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
3497
+ return /* @__PURE__ */ jsxRuntime.jsx(moonpayReact.MoonPayProvider, { apiKey, children });
3498
+ }
3499
+ function formatPostDepositLockFailure(error, token) {
3500
+ if (error?.reason === "credited-below-signed" && error.creditedAmount !== void 0 && error.signedAmount !== void 0 && token) {
3501
+ const creditedAmount = `${viem.formatUnits(error.creditedAmount, token.decimals)} ${token.symbol}`;
3502
+ const signedAmount = `${viem.formatUnits(error.signedAmount, token.decimals)} ${token.symbol}`;
3503
+ return `Credited amount (${creditedAmount}) is below the signed lock amount (${signedAmount})`;
3504
+ }
3505
+ return error?.message ?? "Lock submission failed";
3506
+ }
3507
+ function MethodTabs({
3508
+ activeTab,
3509
+ onTabChange
3510
+ }) {
3511
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-secondary relative flex gap-2 overflow-hidden rounded-[10px] p-1", children: [
3512
+ /* @__PURE__ */ jsxRuntime.jsx(
3513
+ "div",
3514
+ {
3515
+ className: chunkFGWMLLEC_cjs.cn(
3516
+ "bg-input absolute top-1 bottom-1 left-1 w-[calc(50%-8px)] rounded-md transition-transform duration-200",
3517
+ activeTab === "credit-card" && "translate-x-[calc(100%+8px)]"
3518
+ )
3519
+ }
3520
+ ),
3521
+ /* @__PURE__ */ jsxRuntime.jsx(
3522
+ "button",
3523
+ {
3524
+ type: "button",
3525
+ onClick: () => onTabChange("crypto"),
3526
+ className: chunkFGWMLLEC_cjs.cn(
3527
+ "relative z-10 flex-1 cursor-pointer rounded-md px-3 py-[9px] text-sm font-medium transition-colors",
3528
+ activeTab === "crypto" ? "text-foreground" : "text-muted-foreground"
3529
+ ),
3530
+ children: "Crypto"
3531
+ }
3532
+ ),
3533
+ /* @__PURE__ */ jsxRuntime.jsx(
3534
+ "button",
3535
+ {
3536
+ type: "button",
3537
+ onClick: () => onTabChange("credit-card"),
3538
+ className: chunkFGWMLLEC_cjs.cn(
3539
+ "relative z-10 flex-1 cursor-pointer rounded-md px-3 py-[9px] text-sm font-medium transition-colors",
3540
+ activeTab === "credit-card" ? "text-foreground" : "text-muted-foreground"
3541
+ ),
3542
+ children: "Credit Card"
3543
+ }
3544
+ )
3545
+ ] });
3546
+ }
3547
+ function MethodOption({
3548
+ title,
3549
+ description,
3550
+ onClick
3551
+ }) {
3552
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3553
+ "button",
3554
+ {
3555
+ type: "button",
3556
+ onClick,
3557
+ className: "bg-input hover:bg-input/70 border-border flex w-full cursor-pointer items-center gap-3 rounded-lg border p-3 text-left transition-colors",
3558
+ children: [
3559
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
3560
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-sm leading-[14px] font-medium", children: title }),
3561
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs leading-3", children: description })
3562
+ ] }),
3563
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground flex h-5 w-5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, {}) })
3564
+ ]
3565
+ }
3566
+ );
3567
+ }
3784
3568
  function DepositModalContent({
3785
3569
  defaultTab = "crypto",
3786
3570
  allowance,
@@ -3795,7 +3579,7 @@ function DepositModalContent({
3795
3579
  onCloseBlockedChange,
3796
3580
  onExit
3797
3581
  }) {
3798
- const { serviceName, enabledTokens, defaultToken, hostedAuthConfig, getChainById: getChainById2 } = chunkUHXVYWTF_cjs.usePrivanaContext();
3582
+ const { serviceName, enabledTokens, defaultToken, hostedAuthConfig, getChainById: getChainById2, getTokenById } = chunkFGWMLLEC_cjs.usePrivanaContext();
3799
3583
  const { address } = wagmi.useAccount();
3800
3584
  const appName = serviceName ?? "Privana";
3801
3585
  const [activeTab, setActiveTab] = react.useState(defaultTab);
@@ -3804,6 +3588,10 @@ function DepositModalContent({
3804
3588
  const [selectedTokenId, setSelectedTokenId] = react.useState(defaultToken?.id ?? "");
3805
3589
  const [amount, setAmount] = react.useState("");
3806
3590
  const selectedToken = enabledTokens.find((t) => t.id === selectedTokenId) ?? defaultToken;
3591
+ const externalDepositAddress = useDepositAddress({
3592
+ enabled: source === "external" && (view === "deposit" || view === "external-deposit")
3593
+ });
3594
+ const externalMinimum = source !== "external" || !selectedToken ? void 0 : externalDepositAddress.isError ? null : externalDepositAddress.response ? getExternalDepositMinimum(externalDepositAddress.response, selectedToken.chainId) ?? null : void 0;
3807
3595
  const prevAddressRef = react.useRef(address);
3808
3596
  react.useEffect(() => {
3809
3597
  const prev = prevAddressRef.current;
@@ -3823,9 +3611,10 @@ function DepositModalContent({
3823
3611
  const [showTimeout, setShowTimeout] = react.useState(false);
3824
3612
  const [cancelled, setCancelled] = react.useState(false);
3825
3613
  const [isSubmittingLock, setIsSubmittingLock] = react.useState(false);
3826
- const [lockFailedMessage, setLockFailedMessage] = react.useState(null);
3614
+ const [lockFailure, setLockFailure] = react.useState(null);
3827
3615
  const finishDeposit = () => {
3828
3616
  setAmount("");
3617
+ if (view === "external-deposit") setView("deposit");
3829
3618
  if (onDepositSuccess) {
3830
3619
  resetDeposit();
3831
3620
  onDepositSuccess();
@@ -3860,6 +3649,7 @@ function DepositModalContent({
3860
3649
  },
3861
3650
  onLockSubmitted: () => {
3862
3651
  setIsSubmittingLock(false);
3652
+ setLockFailure(null);
3863
3653
  finishDeposit();
3864
3654
  },
3865
3655
  // The deposit credited; only the policy lock failed. Success must not
@@ -3867,7 +3657,7 @@ function DepositModalContent({
3867
3657
  // error view and let the host re-prompt for a fresh lock.
3868
3658
  onLockFailed: (err) => {
3869
3659
  setIsSubmittingLock(false);
3870
- setLockFailedMessage(err.message);
3660
+ setLockFailure(err);
3871
3661
  onLockFailed?.(err);
3872
3662
  },
3873
3663
  onCheckTimeout: () => {
@@ -3875,7 +3665,37 @@ function DepositModalContent({
3875
3665
  setShowTimeout(true);
3876
3666
  }
3877
3667
  });
3878
- const isUnsafeToClose = (isGettingAddress || isSendingTransaction) && !cancelled;
3668
+ const externalLock = useExternalDepositLock({
3669
+ allowance,
3670
+ onLockSubmitted: () => {
3671
+ setLockFailure(null);
3672
+ finishDeposit();
3673
+ },
3674
+ // Same contract as the connected flow: the deposit credited, only the
3675
+ // lock failed — never report success, show the lock-error view instead.
3676
+ onLockFailed: (err) => {
3677
+ setLockFailure(err);
3678
+ onLockFailed?.(err);
3679
+ }
3680
+ });
3681
+ react.useEffect(() => {
3682
+ const restored = externalLock.session;
3683
+ if (!restored) return;
3684
+ const canRestore = view === "method" || source === "external" && (view === "deposit" || view === "external-deposit");
3685
+ if (!canRestore) return;
3686
+ const token = getTokenById(restored.tokenId);
3687
+ if (!token) return;
3688
+ setSource("external");
3689
+ setSelectedTokenId(token.id);
3690
+ setAmount(viem.formatUnits(BigInt(restored.depositAmount), token.decimals));
3691
+ setView("external-deposit");
3692
+ }, [externalLock.session, getTokenById, source, view]);
3693
+ react.useEffect(() => {
3694
+ if (view === "external-deposit" && allowance && !externalLock.session) {
3695
+ setView("deposit");
3696
+ }
3697
+ }, [allowance, externalLock.session, view]);
3698
+ const isUnsafeToClose = (isGettingAddress || isSendingTransaction) && !cancelled || externalLock.isSigning || externalLock.isSubmittingLock;
3879
3699
  react.useEffect(() => {
3880
3700
  onCloseBlockedChange?.(isUnsafeToClose);
3881
3701
  }, [isUnsafeToClose, onCloseBlockedChange]);
@@ -3888,7 +3708,33 @@ function DepositModalContent({
3888
3708
  }, [depositError, verificationFailed]);
3889
3709
  const handleSubmit = (args) => {
3890
3710
  if (args.source === "external") {
3891
- setView("external-deposit");
3711
+ const token2 = enabledTokens.find((candidate) => candidate.id === args.tokenId);
3712
+ if (!token2) return;
3713
+ if (token2.contract === viem.zeroAddress) {
3714
+ sonner.toast.error("External deposits support ERC20 tokens only");
3715
+ return;
3716
+ }
3717
+ const depositAmount = chunkFGWMLLEC_cjs.parseTokenAmount(args.amount, token2.decimals);
3718
+ if (!allowance) {
3719
+ setView("external-deposit");
3720
+ return;
3721
+ }
3722
+ if (typeof externalMinimum !== "bigint") {
3723
+ sonner.toast.error("Minimum deposit is unavailable. Please try again.");
3724
+ return;
3725
+ }
3726
+ if (depositAmount < externalMinimum) {
3727
+ sonner.toast.error(
3728
+ `Minimum deposit is ${viem.formatUnits(externalMinimum, token2.decimals)} ${token2.symbol}`
3729
+ );
3730
+ return;
3731
+ }
3732
+ externalLock.signAndPersist({
3733
+ tokenId: token2.id,
3734
+ amount: depositAmount
3735
+ }).then(() => setView("external-deposit")).catch((err) => {
3736
+ sonner.toast.error(err instanceof Error ? err.message : "Policy signing failed");
3737
+ });
3892
3738
  return;
3893
3739
  }
3894
3740
  if (args.source === "credit-card") {
@@ -3901,7 +3747,7 @@ function DepositModalContent({
3901
3747
  setCancelled(false);
3902
3748
  deposit({
3903
3749
  tokenId: token.id,
3904
- amount: chunkUHXVYWTF_cjs.parseTokenAmount(args.amount, token.decimals),
3750
+ amount: chunkFGWMLLEC_cjs.parseTokenAmount(args.amount, token.decimals),
3905
3751
  postDepositLock: allowance ? {
3906
3752
  maxAmount: BigInt(allowance.value),
3907
3753
  lockDuration: allowance.lockDuration
@@ -3940,7 +3786,14 @@ function DepositModalContent({
3940
3786
  }
3941
3787
  ] : []
3942
3788
  ];
3943
- const flowView = showSuccess ? "deposit-success" : lockFailedMessage ? "lock-error" : showTimeout ? "deposit-timeout" : verificationFailed ? "deposit-error" : isPending && !cancelled || isSubmittingLock ? "depositing" : null;
3789
+ const hasExternalLockRecovery = view === "external-deposit" && !!externalLock.session?.creditedAmount;
3790
+ const externalSubmissionAmbiguous = hasExternalLockRecovery && !!lockFailure?.submissionMayHaveSucceeded;
3791
+ const savedExternalPayloadUsable = !!externalLock.session?.payload && chunkFGWMLLEC_cjs.isSignedLockUsable(externalLock.session.payload);
3792
+ const ambiguousRecoveryMustBeAbandoned = externalSubmissionAmbiguous && !savedExternalPayloadUsable;
3793
+ const externalRecoveryExitLabel = externalSubmissionAmbiguous ? "Stop recovery" : "Keep funds unlocked";
3794
+ const lockFailureToken = hasExternalLockRecovery && externalLock.session ? getTokenById(externalLock.session.tokenId) ?? selectedToken : selectedToken;
3795
+ const lockFailureMessage = formatPostDepositLockFailure(lockFailure, lockFailureToken);
3796
+ const flowView = showSuccess ? "deposit-success" : lockFailure ? "lock-error" : showTimeout ? "deposit-timeout" : verificationFailed ? "deposit-error" : isPending && !cancelled || isSubmittingLock ? "depositing" : null;
3944
3797
  const activeView = flowView ?? view;
3945
3798
  const handleDepositDone = () => {
3946
3799
  setShowSuccess(false);
@@ -3953,10 +3806,28 @@ function DepositModalContent({
3953
3806
  resetDeposit();
3954
3807
  };
3955
3808
  const handleLockFailedDone = () => {
3956
- setLockFailedMessage(null);
3809
+ if (hasExternalLockRecovery && !externalLock.discardSession()) {
3810
+ sonner.toast.error("Deposit recovery changed in another tab. Please review the current state.");
3811
+ return;
3812
+ }
3813
+ setLockFailure(null);
3957
3814
  setAmount("");
3958
3815
  setCancelled(false);
3959
3816
  resetDeposit();
3817
+ if (view === "external-deposit") setView("deposit");
3818
+ };
3819
+ const handleExternalLockRetry = () => {
3820
+ externalLock.retryAfterCredit().catch((err) => {
3821
+ sonner.toast.error(err instanceof Error ? err.message : "Policy signing failed");
3822
+ });
3823
+ };
3824
+ const handleExternalVerificationDiscard = () => {
3825
+ if (!externalLock.discardSession()) {
3826
+ sonner.toast.error("Deposit recovery changed in another tab. Please review the current state.");
3827
+ return;
3828
+ }
3829
+ setAmount("");
3830
+ setView("deposit");
3960
3831
  };
3961
3832
  const handleDismissVerificationError = () => {
3962
3833
  setAmount("");
@@ -3969,6 +3840,10 @@ function DepositModalContent({
3969
3840
  };
3970
3841
  const back = view === "external-deposit" ? { to: "deposit", label: "Deposit from External Wallet" } : view === "credit-card-widget" ? { to: "deposit", label: "Buy with credit card and deposit" } : view === "select-token" ? { to: "deposit", label: "Deposit" } : { to: "method", label: "Deposit Method" };
3971
3842
  const goBack = () => {
3843
+ if (view === "external-deposit" && externalLock.session) {
3844
+ sonner.toast.error("Cancel the active deposit from the address screen before going back");
3845
+ return;
3846
+ }
3972
3847
  if (back.to === "method") {
3973
3848
  setAmount("");
3974
3849
  setSelectedTokenId("");
@@ -3983,7 +3858,7 @@ function DepositModalContent({
3983
3858
  onClick: onClose,
3984
3859
  disabled: isUnsafeToClose,
3985
3860
  "aria-label": "Close",
3986
- className: chunkUHXVYWTF_cjs.cn(
3861
+ className: chunkFGWMLLEC_cjs.cn(
3987
3862
  "absolute top-6 right-5 z-20 flex h-5 w-5 items-center justify-center transition-colors",
3988
3863
  isUnsafeToClose ? "text-muted-foreground/40 cursor-not-allowed" : "text-muted-foreground hover:text-foreground cursor-pointer"
3989
3864
  ),
@@ -4014,9 +3889,14 @@ function DepositModalContent({
4014
3889
  activeView === "lock-error" && /* @__PURE__ */ jsxRuntime.jsx(
4015
3890
  TransactionWarningView,
4016
3891
  {
4017
- title: "Deposit credited, lock failed",
4018
- message: `Your deposit was credited but locking the funds for ${appName} failed: ${lockFailedMessage}`,
4019
- onDone: handleLockFailedDone
3892
+ title: externalSubmissionAmbiguous ? "Deposit credited, lock status unknown" : "Deposit credited, lock failed",
3893
+ message: externalSubmissionAmbiguous ? `Your deposit was credited, but the lock for ${appName} may already have succeeded. Retry only the saved signature; if it has expired, check locked funds before stopping recovery.` : `Your deposit was credited but locking the funds for ${appName} failed: ${lockFailureMessage}`,
3894
+ onDone: hasExternalLockRecovery && !ambiguousRecoveryMustBeAbandoned ? handleExternalLockRetry : handleLockFailedDone,
3895
+ actionLabel: hasExternalLockRecovery ? ambiguousRecoveryMustBeAbandoned ? externalRecoveryExitLabel : externalLock.session?.payload ? "Retry lock submission" : "Sign policy and lock funds" : void 0,
3896
+ pendingLabel: externalLock.isSigning ? "Confirm policy in wallet\u2026" : "Locking funds\u2026",
3897
+ isPending: externalLock.isSigning || externalLock.isSubmittingLock,
3898
+ onDismiss: hasExternalLockRecovery && !ambiguousRecoveryMustBeAbandoned ? handleLockFailedDone : void 0,
3899
+ dismissLabel: externalRecoveryExitLabel
4020
3900
  }
4021
3901
  ),
4022
3902
  activeView === "deposit-timeout" && /* @__PURE__ */ jsxRuntime.jsx(
@@ -4031,7 +3911,7 @@ function DepositModalContent({
4031
3911
  TransactionErrorView,
4032
3912
  {
4033
3913
  title: "Verification failed",
4034
- message: depositError?.message ? `Your transfer was sent on-chain but we could not verify the deposit. The funds are already at the deposit address \u2014 retry verification instead of starting a new deposit. (${depositError.message})` : "Your transfer was sent on-chain but we could not verify the deposit. The funds are already at the deposit address \u2014 retry verification instead of starting a new deposit.",
3914
+ message: depositError?.message ? `Your transfer was sent on-chain but we could not verify the deposit. The funds are already at the deposit address. Retry verification instead of starting a new deposit. (${depositError.message})` : "Your transfer was sent on-chain but we could not verify the deposit. The funds are already at the deposit address. Retry verification instead of starting a new deposit.",
4035
3915
  explorerUrl: explorerTxUrl,
4036
3916
  explorerLabel: "View transaction",
4037
3917
  onRetry: handleRetryVerification,
@@ -4041,7 +3921,7 @@ function DepositModalContent({
4041
3921
  activeView === "depositing" && /* @__PURE__ */ jsxRuntime.jsx(
4042
3922
  TransactionProgressView,
4043
3923
  {
4044
- title: "Depositing...",
3924
+ title: "Depositing\u2026",
4045
3925
  steps: depositSteps,
4046
3926
  onCancel: isGettingAddress || isSendingTransaction ? handleDepositCancel : void 0
4047
3927
  }
@@ -4095,15 +3975,16 @@ function DepositModalContent({
4095
3975
  selectedToken,
4096
3976
  amount,
4097
3977
  allowance,
3978
+ externalMinimum,
4098
3979
  onAmountChange: setAmount,
4099
3980
  onSelectToken: () => setView("select-token"),
4100
3981
  onConnectWallet,
4101
3982
  onSubmit: handleSubmit,
4102
- isSubmitting: isPending
3983
+ isSubmitting: isPending || externalLock.isSigning || externalLock.isSubmittingLock
4103
3984
  }
4104
3985
  ) }),
4105
3986
  activeView === "select-token" && /* @__PURE__ */ jsxRuntime.jsx(
4106
- TokenSelectorView2,
3987
+ TokenSelectorView,
4107
3988
  {
4108
3989
  selectedTokenId: selectedToken?.id,
4109
3990
  onSelect: (id) => {
@@ -4112,12 +3993,15 @@ function DepositModalContent({
4112
3993
  }
4113
3994
  }
4114
3995
  ),
4115
- activeView === "external-deposit" && /* @__PURE__ */ jsxRuntime.jsx(
3996
+ activeView === "external-deposit" && (!allowance || externalLock.session) && /* @__PURE__ */ jsxRuntime.jsx(
4116
3997
  ExternalDepositView,
4117
3998
  {
4118
3999
  token: selectedToken,
4119
4000
  amount,
4120
- onCredited: allowance ? void 0 : onDepositSuccess
4001
+ depositAddressState: externalDepositAddress,
4002
+ onCredited: allowance ? void 0 : onDepositSuccess,
4003
+ onDiscardLock: handleExternalVerificationDiscard,
4004
+ lock: externalLock.session ? externalLock : void 0
4121
4005
  }
4122
4006
  ),
4123
4007
  activeView === "credit-card-widget" && /* @__PURE__ */ jsxRuntime.jsx(MoonPayGate, { enabled: true, children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -4129,7 +4013,7 @@ function DepositModalContent({
4129
4013
  onCredited: allowance ? void 0 : finishCardPurchase,
4130
4014
  onLockSubmitted: finishCardPurchase,
4131
4015
  onLockFailed: (err) => {
4132
- setLockFailedMessage(err.message);
4016
+ setLockFailure(err);
4133
4017
  onLockFailed?.(err);
4134
4018
  }
4135
4019
  }
@@ -4182,7 +4066,7 @@ function DepositInlineModal({ className, ...handlers }) {
4182
4066
  "div",
4183
4067
  {
4184
4068
  "data-privana": true,
4185
- className: chunkUHXVYWTF_cjs.cn(
4069
+ className: chunkFGWMLLEC_cjs.cn(
4186
4070
  "bg-card relative flex w-[560px] max-w-full flex-col gap-2 overflow-hidden rounded-2xl p-2 shadow-lg",
4187
4071
  className
4188
4072
  ),
@@ -4197,7 +4081,7 @@ function WithdrawView({
4197
4081
  onSelectToken,
4198
4082
  onPendingChange
4199
4083
  }) {
4200
- const { chains, getChainById: getChainById2 } = chunkUHXVYWTF_cjs.usePrivanaContext();
4084
+ const { chains, getChainById: getChainById2 } = chunkFGWMLLEC_cjs.usePrivanaContext();
4201
4085
  const { isConnected, address } = wagmi.useAccount();
4202
4086
  const [showSuccess, setShowSuccess] = react.useState(false);
4203
4087
  const [showTimeout, setShowTimeout] = react.useState(false);
@@ -4211,7 +4095,7 @@ function WithdrawView({
4211
4095
  tokenId: selectedToken?.id,
4212
4096
  enabled: !!selectedToken
4213
4097
  });
4214
- const formattedBalance = selectedToken ? chunkUHXVYWTF_cjs.formatTokenAmount(balanceWei, selectedToken.decimals) : "0.00";
4098
+ const formattedBalance = selectedToken ? chunkFGWMLLEC_cjs.formatTokenAmount(balanceWei, selectedToken.decimals) : "0.00";
4215
4099
  const { withdraw, isPending, currentStep, error, reset } = useWithdraw({
4216
4100
  onProcessingSuccess: () => {
4217
4101
  onAmountChange("");
@@ -4222,7 +4106,7 @@ function WithdrawView({
4222
4106
  setShowTimeout(true);
4223
4107
  }
4224
4108
  });
4225
- const explorerUrl = address && targetChain ? chunkUHXVYWTF_cjs.getExplorerAddressUrl(targetChain.id, address) : void 0;
4109
+ const explorerUrl = address && targetChain ? chunkFGWMLLEC_cjs.getExplorerAddressUrl(targetChain.id, address) : void 0;
4226
4110
  const getStepStatus = (step, after) => {
4227
4111
  if (currentStep === step) return "active";
4228
4112
  if (after.includes(currentStep)) return "completed";
@@ -4247,7 +4131,7 @@ function WithdrawView({
4247
4131
  }, [isPending, cancelled, onPendingChange]);
4248
4132
  const hasValidAmount = !!amount && parseFloat(amount) > 0;
4249
4133
  const tooManyDecimals = !!hasValidAmount && !!selectedToken && amount.includes(".") && amount.split(".")[1].length > selectedToken.decimals;
4250
- const exceedsBalance = !!hasValidAmount && !tooManyDecimals && !!selectedToken && !isBalanceLoading && !isBalanceError && chunkUHXVYWTF_cjs.parseTokenAmount(amount, selectedToken.decimals) > BigInt(balanceWei);
4134
+ const exceedsBalance = !!hasValidAmount && !tooManyDecimals && !!selectedToken && !isBalanceLoading && !isBalanceError && chunkFGWMLLEC_cjs.parseTokenAmount(amount, selectedToken.decimals) > BigInt(balanceWei);
4251
4135
  const canWithdraw = isConnected && hasValidAmount && !!selectedToken && !tooManyDecimals && !exceedsBalance;
4252
4136
  const handleMax = () => {
4253
4137
  if (!selectedToken) return;
@@ -4259,7 +4143,7 @@ function WithdrawView({
4259
4143
  setCancelled(false);
4260
4144
  await withdraw({
4261
4145
  tokenId: selectedToken.id,
4262
- amount: chunkUHXVYWTF_cjs.parseTokenAmount(amount, selectedToken.decimals)
4146
+ amount: chunkFGWMLLEC_cjs.parseTokenAmount(amount, selectedToken.decimals)
4263
4147
  });
4264
4148
  };
4265
4149
  const handleCancel = () => {
@@ -4279,7 +4163,7 @@ function WithdrawView({
4279
4163
  title: "Withdrawal Complete",
4280
4164
  message: `Your ${selectedToken.symbol} withdrawal has been processed. Funds should appear in your wallet shortly.`,
4281
4165
  explorerUrl,
4282
- explorerLabel: targetChain ? chunkUHXVYWTF_cjs.getExplorerLabel(targetChain.id) : void 0,
4166
+ explorerLabel: targetChain ? chunkFGWMLLEC_cjs.getExplorerLabel(targetChain.id) : void 0,
4283
4167
  onDone: handleDone
4284
4168
  }
4285
4169
  ) });
@@ -4390,7 +4274,7 @@ function WithdrawModalContent({
4390
4274
  onPendingChange,
4391
4275
  onBack
4392
4276
  }) {
4393
- const { serviceName, enabledTokens, defaultToken, hostedAuthConfig } = chunkUHXVYWTF_cjs.usePrivanaContext();
4277
+ const { serviceName, enabledTokens, defaultToken, hostedAuthConfig } = chunkFGWMLLEC_cjs.usePrivanaContext();
4394
4278
  const { address } = wagmi.useAccount();
4395
4279
  const appName = serviceName ?? "Privana";
4396
4280
  const [view, setView] = react.useState("form");
@@ -4458,7 +4342,7 @@ function WithdrawModalContent({
4458
4342
  }
4459
4343
  ),
4460
4344
  view === "select-token" && /* @__PURE__ */ jsxRuntime.jsx(
4461
- TokenSelectorView2,
4345
+ TokenSelectorView,
4462
4346
  {
4463
4347
  selectedTokenId: selectedToken?.id,
4464
4348
  onSelect: (id) => {
@@ -4508,7 +4392,7 @@ function WithdrawInlineModal({ className }) {
4508
4392
  "div",
4509
4393
  {
4510
4394
  "data-privana": true,
4511
- className: chunkUHXVYWTF_cjs.cn(
4395
+ className: chunkFGWMLLEC_cjs.cn(
4512
4396
  "bg-card relative flex w-[560px] max-w-full flex-col gap-2 overflow-hidden rounded-2xl p-2 shadow-lg",
4513
4397
  className
4514
4398
  ),
@@ -4552,14 +4436,14 @@ function SegmentedBalanceBar({
4552
4436
  showAvailable && /* @__PURE__ */ jsxRuntime.jsx(
4553
4437
  "div",
4554
4438
  {
4555
- className: chunkUHXVYWTF_cjs.cn(AVAILABLE_COLOR, "rounded-l-full", !showInUse && "rounded-r-full"),
4439
+ className: chunkFGWMLLEC_cjs.cn(AVAILABLE_COLOR, "rounded-l-full", !showInUse && "rounded-r-full"),
4556
4440
  style: { flexGrow: grow(availableWei) }
4557
4441
  }
4558
4442
  ),
4559
4443
  showInUse && /* @__PURE__ */ jsxRuntime.jsx(
4560
4444
  "div",
4561
4445
  {
4562
- className: chunkUHXVYWTF_cjs.cn(IN_USE_COLOR, "rounded-r-full", !showAvailable && "rounded-l-full"),
4446
+ className: chunkFGWMLLEC_cjs.cn(IN_USE_COLOR, "rounded-r-full", !showAvailable && "rounded-l-full"),
4563
4447
  style: { flexGrow: grow(inUseWei) }
4564
4448
  }
4565
4449
  )
@@ -4567,7 +4451,7 @@ function SegmentedBalanceBar({
4567
4451
  }
4568
4452
  function BalanceLegendItem({ color, label }) {
4569
4453
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
4570
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: chunkUHXVYWTF_cjs.cn("h-2.5 w-2.5 rounded-full", color) }),
4454
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: chunkFGWMLLEC_cjs.cn("h-2.5 w-2.5 rounded-full", color) }),
4571
4455
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-sm leading-5", children: label })
4572
4456
  ] });
4573
4457
  }
@@ -4580,7 +4464,7 @@ function WalletBalanceView({
4580
4464
  onAddFunds,
4581
4465
  onWithdraw
4582
4466
  }) {
4583
- const { serviceName, serviceIcon, defaultToken } = chunkUHXVYWTF_cjs.usePrivanaContext();
4467
+ const { serviceName, serviceIcon, defaultToken } = chunkFGWMLLEC_cjs.usePrivanaContext();
4584
4468
  const appName = serviceName ?? "Privana";
4585
4469
  const token = defaultToken;
4586
4470
  const {
@@ -4593,14 +4477,14 @@ function WalletBalanceView({
4593
4477
  const variant = !session ? "idle" : inUseWei === 0n ? "session-zero" : availableWei === 0n ? "fully-in-use" : "mixed";
4594
4478
  const expiry = session?.expiry;
4595
4479
  useNow(3e4, expiry != null);
4596
- const countdown = expiry != null ? chunkUHXVYWTF_cjs.formatTimeRemaining(expiry) : null;
4480
+ const countdown = expiry != null ? chunkFGWMLLEC_cjs.formatTimeRemaining(expiry) : null;
4597
4481
  const decimals = token?.decimals ?? 18;
4598
- const totalFormatted = chunkUHXVYWTF_cjs.formatTokenAmount((availableWei + inUseWei).toString(), decimals);
4599
- const availableFormatted = chunkUHXVYWTF_cjs.formatTokenAmount(availableWei.toString(), decimals);
4600
- const inUseFormatted = chunkUHXVYWTF_cjs.formatTokenAmount(inUseWei.toString(), decimals);
4482
+ const totalFormatted = chunkFGWMLLEC_cjs.formatTokenAmount((availableWei + inUseWei).toString(), decimals);
4483
+ const availableFormatted = chunkFGWMLLEC_cjs.formatTokenAmount(availableWei.toString(), decimals);
4484
+ const inUseFormatted = chunkFGWMLLEC_cjs.formatTokenAmount(inUseWei.toString(), decimals);
4601
4485
  const hasValidAmount = !!amount && parseFloat(amount) > 0;
4602
4486
  const tooManyDecimals = hasValidAmount && !!token && amount.includes(".") && amount.split(".")[1].length > token.decimals;
4603
- const exceedsBalance = hasValidAmount && !tooManyDecimals && !!token && !isBalanceLoading && !isBalanceError && chunkUHXVYWTF_cjs.parseTokenAmount(amount, token.decimals) > availableWei;
4487
+ const exceedsBalance = hasValidAmount && !tooManyDecimals && !!token && !isBalanceLoading && !isBalanceError && chunkFGWMLLEC_cjs.parseTokenAmount(amount, token.decimals) > availableWei;
4604
4488
  const canFundSession = hasValidAmount && !!token && !tooManyDecimals && !exceedsBalance && !isBalanceLoading && !isBalanceError;
4605
4489
  const handleMax = () => {
4606
4490
  const max = availableFormatted.replace(/\s/g, "");
@@ -4618,7 +4502,7 @@ function WalletBalanceView({
4618
4502
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm leading-[14px]", children: "Total" }),
4619
4503
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-secondary text-muted-foreground rounded-full px-2 py-[5px] text-[10px] leading-[10px] font-bold", children: token?.symbol ?? "\u2014" })
4620
4504
  ] }),
4621
- isBalanceLoading ? /* @__PURE__ */ jsxRuntime.jsx(chunkUHXVYWTF_cjs.Skeleton, { className: "h-9 w-40" }) : isBalanceError ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-[32px] leading-9 font-medium", children: "\u2014" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-[32px] leading-9 font-medium", children: totalFormatted })
4505
+ isBalanceLoading ? /* @__PURE__ */ jsxRuntime.jsx(chunkFGWMLLEC_cjs.Skeleton, { className: "h-9 w-40" }) : isBalanceError ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-[32px] leading-9 font-medium", children: "\u2014" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground text-[32px] leading-9 font-medium", children: totalFormatted })
4622
4506
  ] }),
4623
4507
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
4624
4508
  /* @__PURE__ */ jsxRuntime.jsx(SegmentedBalanceBar, { availableWei, inUseWei }),
@@ -4768,7 +4652,7 @@ function WalletModalContent({
4768
4652
  onCloseBlockedChange,
4769
4653
  ...depositHandlers
4770
4654
  }) {
4771
- const { serviceName, hostedAuthConfig } = chunkUHXVYWTF_cjs.usePrivanaContext();
4655
+ const { serviceName, hostedAuthConfig } = chunkFGWMLLEC_cjs.usePrivanaContext();
4772
4656
  const { address } = wagmi.useAccount();
4773
4657
  const appName = serviceName ?? "Privana";
4774
4658
  const [view, setView] = react.useState("balance");
@@ -4872,7 +4756,7 @@ function WalletModalContent({
4872
4756
  onClick: onClose,
4873
4757
  disabled: closeBlocked,
4874
4758
  "aria-label": "Close",
4875
- className: chunkUHXVYWTF_cjs.cn(
4759
+ className: chunkFGWMLLEC_cjs.cn(
4876
4760
  "absolute top-6 right-5 z-20 flex h-5 w-5 items-center justify-center transition-colors",
4877
4761
  closeBlocked ? "text-muted-foreground/40 cursor-not-allowed" : "text-muted-foreground hover:text-foreground cursor-pointer"
4878
4762
  ),
@@ -4889,7 +4773,7 @@ function WalletModalContent({
4889
4773
  onAmountChange: setAmount,
4890
4774
  onFundSession: onFundSession ? fundSession : void 0,
4891
4775
  onAddFunds: () => setView("deposit"),
4892
- onWithdraw: handleWithdraw
4776
+ onWithdraw: session && !onEndSession ? void 0 : handleWithdraw
4893
4777
  }
4894
4778
  ),
4895
4779
  view === "funding-session" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -4990,7 +4874,7 @@ function WalletInlineModal({ className, ...handlers }) {
4990
4874
  "div",
4991
4875
  {
4992
4876
  "data-privana": true,
4993
- className: chunkUHXVYWTF_cjs.cn(
4877
+ className: chunkFGWMLLEC_cjs.cn(
4994
4878
  "bg-card relative flex w-[560px] max-w-full flex-col gap-2 overflow-hidden rounded-2xl p-2 shadow-lg",
4995
4879
  className
4996
4880
  ),
@@ -5001,294 +4885,299 @@ function WalletInlineModal({ className, ...handlers }) {
5001
4885
 
5002
4886
  Object.defineProperty(exports, "AccountingApiError", {
5003
4887
  enumerable: true,
5004
- get: function () { return chunkUHXVYWTF_cjs.AccountingApiError; }
4888
+ get: function () { return chunkFGWMLLEC_cjs.AccountingApiError; }
5005
4889
  });
5006
4890
  Object.defineProperty(exports, "Button", {
5007
4891
  enumerable: true,
5008
- get: function () { return chunkUHXVYWTF_cjs.Button; }
4892
+ get: function () { return chunkFGWMLLEC_cjs.Button; }
5009
4893
  });
5010
4894
  Object.defineProperty(exports, "DEFAULT_LOCK_DURATION_SECONDS", {
5011
4895
  enumerable: true,
5012
- get: function () { return chunkUHXVYWTF_cjs.DEFAULT_LOCK_DURATION_SECONDS; }
4896
+ get: function () { return chunkFGWMLLEC_cjs.DEFAULT_LOCK_DURATION_SECONDS; }
5013
4897
  });
5014
4898
  Object.defineProperty(exports, "DEFAULT_ONRAMP_LOCK_BUFFER", {
5015
4899
  enumerable: true,
5016
- get: function () { return chunkUHXVYWTF_cjs.DEFAULT_ONRAMP_LOCK_BUFFER; }
4900
+ get: function () { return chunkFGWMLLEC_cjs.DEFAULT_ONRAMP_LOCK_BUFFER; }
5017
4901
  });
5018
4902
  Object.defineProperty(exports, "HOSTED_AUTH_CLOCK_SKEW_MS", {
5019
4903
  enumerable: true,
5020
- get: function () { return chunkUHXVYWTF_cjs.HOSTED_AUTH_CLOCK_SKEW_MS; }
4904
+ get: function () { return chunkFGWMLLEC_cjs.HOSTED_AUTH_CLOCK_SKEW_MS; }
5021
4905
  });
5022
4906
  Object.defineProperty(exports, "HostedAuthError", {
5023
4907
  enumerable: true,
5024
- get: function () { return chunkUHXVYWTF_cjs.HostedAuthError; }
4908
+ get: function () { return chunkFGWMLLEC_cjs.HostedAuthError; }
5025
4909
  });
5026
4910
  Object.defineProperty(exports, "HostedAuthRequiredError", {
5027
4911
  enumerable: true,
5028
- get: function () { return chunkUHXVYWTF_cjs.HostedAuthRequiredError; }
4912
+ get: function () { return chunkFGWMLLEC_cjs.HostedAuthRequiredError; }
5029
4913
  });
5030
4914
  Object.defineProperty(exports, "HostedAuthStateMismatchError", {
5031
4915
  enumerable: true,
5032
- get: function () { return chunkUHXVYWTF_cjs.HostedAuthStateMismatchError; }
4916
+ get: function () { return chunkFGWMLLEC_cjs.HostedAuthStateMismatchError; }
5033
4917
  });
5034
4918
  Object.defineProperty(exports, "HttpClient", {
5035
4919
  enumerable: true,
5036
- get: function () { return chunkUHXVYWTF_cjs.HttpClient; }
4920
+ get: function () { return chunkFGWMLLEC_cjs.HttpClient; }
5037
4921
  });
5038
4922
  Object.defineProperty(exports, "LOCK_TYPES", {
5039
4923
  enumerable: true,
5040
- get: function () { return chunkUHXVYWTF_cjs.LOCK_TYPES; }
4924
+ get: function () { return chunkFGWMLLEC_cjs.LOCK_TYPES; }
5041
4925
  });
5042
4926
  Object.defineProperty(exports, "MODIFY_LOCK_TYPES", {
5043
4927
  enumerable: true,
5044
- get: function () { return chunkUHXVYWTF_cjs.MODIFY_LOCK_TYPES; }
4928
+ get: function () { return chunkFGWMLLEC_cjs.MODIFY_LOCK_TYPES; }
5045
4929
  });
5046
4930
  Object.defineProperty(exports, "NETWORK_CONFIG", {
5047
4931
  enumerable: true,
5048
- get: function () { return chunkUHXVYWTF_cjs.NETWORK_CONFIG; }
4932
+ get: function () { return chunkFGWMLLEC_cjs.NETWORK_CONFIG; }
5049
4933
  });
5050
4934
  Object.defineProperty(exports, "NetworkError", {
5051
4935
  enumerable: true,
5052
- get: function () { return chunkUHXVYWTF_cjs.NetworkError; }
4936
+ get: function () { return chunkFGWMLLEC_cjs.NetworkError; }
5053
4937
  });
5054
4938
  Object.defineProperty(exports, "PostDepositLockError", {
5055
4939
  enumerable: true,
5056
- get: function () { return chunkUHXVYWTF_cjs.PostDepositLockError; }
4940
+ get: function () { return chunkFGWMLLEC_cjs.PostDepositLockError; }
5057
4941
  });
5058
4942
  Object.defineProperty(exports, "PrivanaClient", {
5059
4943
  enumerable: true,
5060
- get: function () { return chunkUHXVYWTF_cjs.PrivanaClient; }
4944
+ get: function () { return chunkFGWMLLEC_cjs.PrivanaClient; }
5061
4945
  });
5062
4946
  Object.defineProperty(exports, "PrivanaProvider", {
5063
4947
  enumerable: true,
5064
- get: function () { return chunkUHXVYWTF_cjs.PrivanaProvider; }
4948
+ get: function () { return chunkFGWMLLEC_cjs.PrivanaProvider; }
5065
4949
  });
5066
4950
  Object.defineProperty(exports, "SUPPORTED_CHAINS", {
5067
4951
  enumerable: true,
5068
- get: function () { return chunkUHXVYWTF_cjs.SUPPORTED_CHAINS; }
4952
+ get: function () { return chunkFGWMLLEC_cjs.SUPPORTED_CHAINS; }
5069
4953
  });
5070
4954
  Object.defineProperty(exports, "SiweAuthProvider", {
5071
4955
  enumerable: true,
5072
- get: function () { return chunkUHXVYWTF_cjs.SiweAuthProvider; }
4956
+ get: function () { return chunkFGWMLLEC_cjs.SiweAuthProvider; }
5073
4957
  });
5074
4958
  Object.defineProperty(exports, "Skeleton", {
5075
4959
  enumerable: true,
5076
- get: function () { return chunkUHXVYWTF_cjs.Skeleton; }
4960
+ get: function () { return chunkFGWMLLEC_cjs.Skeleton; }
5077
4961
  });
5078
4962
  Object.defineProperty(exports, "TRANSFER_LOCKED_TYPES", {
5079
4963
  enumerable: true,
5080
- get: function () { return chunkUHXVYWTF_cjs.TRANSFER_LOCKED_TYPES; }
4964
+ get: function () { return chunkFGWMLLEC_cjs.TRANSFER_LOCKED_TYPES; }
5081
4965
  });
5082
4966
  Object.defineProperty(exports, "TRANSFER_TYPES", {
5083
4967
  enumerable: true,
5084
- get: function () { return chunkUHXVYWTF_cjs.TRANSFER_TYPES; }
4968
+ get: function () { return chunkFGWMLLEC_cjs.TRANSFER_TYPES; }
5085
4969
  });
5086
4970
  Object.defineProperty(exports, "ValidationError", {
5087
4971
  enumerable: true,
5088
- get: function () { return chunkUHXVYWTF_cjs.ValidationError; }
4972
+ get: function () { return chunkFGWMLLEC_cjs.ValidationError; }
5089
4973
  });
5090
4974
  Object.defineProperty(exports, "WITHDRAW_FROM_LOCK_TYPES", {
5091
4975
  enumerable: true,
5092
- get: function () { return chunkUHXVYWTF_cjs.WITHDRAW_FROM_LOCK_TYPES; }
4976
+ get: function () { return chunkFGWMLLEC_cjs.WITHDRAW_FROM_LOCK_TYPES; }
5093
4977
  });
5094
4978
  Object.defineProperty(exports, "WITHDRAW_TYPES", {
5095
4979
  enumerable: true,
5096
- get: function () { return chunkUHXVYWTF_cjs.WITHDRAW_TYPES; }
4980
+ get: function () { return chunkFGWMLLEC_cjs.WITHDRAW_TYPES; }
5097
4981
  });
5098
4982
  Object.defineProperty(exports, "applyLockBuffer", {
5099
4983
  enumerable: true,
5100
- get: function () { return chunkUHXVYWTF_cjs.applyLockBuffer; }
4984
+ get: function () { return chunkFGWMLLEC_cjs.applyLockBuffer; }
5101
4985
  });
5102
4986
  Object.defineProperty(exports, "applyRefreshResponse", {
5103
4987
  enumerable: true,
5104
- get: function () { return chunkUHXVYWTF_cjs.applyRefreshResponse; }
4988
+ get: function () { return chunkFGWMLLEC_cjs.applyRefreshResponse; }
5105
4989
  });
5106
4990
  Object.defineProperty(exports, "buildHostedAuthSession", {
5107
4991
  enumerable: true,
5108
- get: function () { return chunkUHXVYWTF_cjs.buildHostedAuthSession; }
4992
+ get: function () { return chunkFGWMLLEC_cjs.buildHostedAuthSession; }
5109
4993
  });
5110
4994
  Object.defineProperty(exports, "buildSiweStatement", {
5111
4995
  enumerable: true,
5112
- get: function () { return chunkUHXVYWTF_cjs.buildSiweStatement; }
4996
+ get: function () { return chunkFGWMLLEC_cjs.buildSiweStatement; }
5113
4997
  });
5114
4998
  Object.defineProperty(exports, "buttonVariants", {
5115
4999
  enumerable: true,
5116
- get: function () { return chunkUHXVYWTF_cjs.buttonVariants; }
5000
+ get: function () { return chunkFGWMLLEC_cjs.buttonVariants; }
5117
5001
  });
5118
5002
  Object.defineProperty(exports, "clampLockAmount", {
5119
5003
  enumerable: true,
5120
- get: function () { return chunkUHXVYWTF_cjs.clampLockAmount; }
5004
+ get: function () { return chunkFGWMLLEC_cjs.clampLockAmount; }
5121
5005
  });
5122
5006
  Object.defineProperty(exports, "clearHostedAuthPendingTransaction", {
5123
5007
  enumerable: true,
5124
- get: function () { return chunkUHXVYWTF_cjs.clearHostedAuthPendingTransaction; }
5008
+ get: function () { return chunkFGWMLLEC_cjs.clearHostedAuthPendingTransaction; }
5125
5009
  });
5126
5010
  Object.defineProperty(exports, "clearPendingLock", {
5127
5011
  enumerable: true,
5128
- get: function () { return chunkUHXVYWTF_cjs.clearPendingLock; }
5012
+ get: function () { return chunkFGWMLLEC_cjs.clearPendingLock; }
5129
5013
  });
5130
5014
  Object.defineProperty(exports, "createDomain", {
5131
5015
  enumerable: true,
5132
- get: function () { return chunkUHXVYWTF_cjs.createDomain; }
5016
+ get: function () { return chunkFGWMLLEC_cjs.createDomain; }
5133
5017
  });
5134
5018
  Object.defineProperty(exports, "createHostedAuthPendingStorageKey", {
5135
5019
  enumerable: true,
5136
- get: function () { return chunkUHXVYWTF_cjs.createHostedAuthPendingStorageKey; }
5020
+ get: function () { return chunkFGWMLLEC_cjs.createHostedAuthPendingStorageKey; }
5137
5021
  });
5138
5022
  Object.defineProperty(exports, "createHostedAuthState", {
5139
5023
  enumerable: true,
5140
- get: function () { return chunkUHXVYWTF_cjs.createHostedAuthState; }
5024
+ get: function () { return chunkFGWMLLEC_cjs.createHostedAuthState; }
5141
5025
  });
5142
5026
  Object.defineProperty(exports, "createHostedAuthStorageKey", {
5143
5027
  enumerable: true,
5144
- get: function () { return chunkUHXVYWTF_cjs.createHostedAuthStorageKey; }
5028
+ get: function () { return chunkFGWMLLEC_cjs.createHostedAuthStorageKey; }
5145
5029
  });
5146
5030
  Object.defineProperty(exports, "createLockExpiry", {
5147
5031
  enumerable: true,
5148
- get: function () { return chunkUHXVYWTF_cjs.createLockExpiry; }
5032
+ get: function () { return chunkFGWMLLEC_cjs.createLockExpiry; }
5149
5033
  });
5150
5034
  Object.defineProperty(exports, "createPkceChallenge", {
5151
5035
  enumerable: true,
5152
- get: function () { return chunkUHXVYWTF_cjs.createPkceChallenge; }
5036
+ get: function () { return chunkFGWMLLEC_cjs.createPkceChallenge; }
5153
5037
  });
5154
5038
  Object.defineProperty(exports, "createPkceVerifier", {
5155
5039
  enumerable: true,
5156
- get: function () { return chunkUHXVYWTF_cjs.createPkceVerifier; }
5040
+ get: function () { return chunkFGWMLLEC_cjs.createPkceVerifier; }
5157
5041
  });
5158
5042
  Object.defineProperty(exports, "createSignedLockRequest", {
5159
5043
  enumerable: true,
5160
- get: function () { return chunkUHXVYWTF_cjs.createSignedLockRequest; }
5044
+ get: function () { return chunkFGWMLLEC_cjs.createSignedLockRequest; }
5161
5045
  });
5162
5046
  Object.defineProperty(exports, "getAccountingContract", {
5163
5047
  enumerable: true,
5164
- get: function () { return chunkUHXVYWTF_cjs.getAccountingContract; }
5048
+ get: function () { return chunkFGWMLLEC_cjs.getAccountingContract; }
5165
5049
  });
5166
5050
  Object.defineProperty(exports, "getApiUrl", {
5167
5051
  enumerable: true,
5168
- get: function () { return chunkUHXVYWTF_cjs.getApiUrl; }
5052
+ get: function () { return chunkFGWMLLEC_cjs.getApiUrl; }
5169
5053
  });
5170
5054
  Object.defineProperty(exports, "getChainById", {
5171
5055
  enumerable: true,
5172
- get: function () { return chunkUHXVYWTF_cjs.getChainById; }
5056
+ get: function () { return chunkFGWMLLEC_cjs.getChainById; }
5173
5057
  });
5174
5058
  Object.defineProperty(exports, "getChainId", {
5175
5059
  enumerable: true,
5176
- get: function () { return chunkUHXVYWTF_cjs.getChainId; }
5060
+ get: function () { return chunkFGWMLLEC_cjs.getChainId; }
5177
5061
  });
5178
5062
  Object.defineProperty(exports, "getExplorerAddressUrl", {
5179
5063
  enumerable: true,
5180
- get: function () { return chunkUHXVYWTF_cjs.getExplorerAddressUrl; }
5064
+ get: function () { return chunkFGWMLLEC_cjs.getExplorerAddressUrl; }
5181
5065
  });
5182
5066
  Object.defineProperty(exports, "getExplorerLabel", {
5183
5067
  enumerable: true,
5184
- get: function () { return chunkUHXVYWTF_cjs.getExplorerLabel; }
5068
+ get: function () { return chunkFGWMLLEC_cjs.getExplorerLabel; }
5185
5069
  });
5186
5070
  Object.defineProperty(exports, "isHostedAuthRefreshActive", {
5187
5071
  enumerable: true,
5188
- get: function () { return chunkUHXVYWTF_cjs.isHostedAuthRefreshActive; }
5072
+ get: function () { return chunkFGWMLLEC_cjs.isHostedAuthRefreshActive; }
5189
5073
  });
5190
5074
  Object.defineProperty(exports, "isHostedAuthSessionActive", {
5191
5075
  enumerable: true,
5192
- get: function () { return chunkUHXVYWTF_cjs.isHostedAuthSessionActive; }
5076
+ get: function () { return chunkFGWMLLEC_cjs.isHostedAuthSessionActive; }
5193
5077
  });
5194
5078
  Object.defineProperty(exports, "isSignedLockUsable", {
5195
5079
  enumerable: true,
5196
- get: function () { return chunkUHXVYWTF_cjs.isSignedLockUsable; }
5080
+ get: function () { return chunkFGWMLLEC_cjs.isSignedLockUsable; }
5197
5081
  });
5198
5082
  Object.defineProperty(exports, "loadPendingLock", {
5199
5083
  enumerable: true,
5200
- get: function () { return chunkUHXVYWTF_cjs.loadPendingLock; }
5084
+ get: function () { return chunkFGWMLLEC_cjs.loadPendingLock; }
5201
5085
  });
5202
5086
  Object.defineProperty(exports, "normalizeAddress", {
5203
5087
  enumerable: true,
5204
- get: function () { return chunkUHXVYWTF_cjs.normalizeAddress; }
5088
+ get: function () { return chunkFGWMLLEC_cjs.normalizeAddress; }
5205
5089
  });
5206
5090
  Object.defineProperty(exports, "normalizeHex", {
5207
5091
  enumerable: true,
5208
- get: function () { return chunkUHXVYWTF_cjs.normalizeHex; }
5092
+ get: function () { return chunkFGWMLLEC_cjs.normalizeHex; }
5209
5093
  });
5210
5094
  Object.defineProperty(exports, "parseHostedAuthCallback", {
5211
5095
  enumerable: true,
5212
- get: function () { return chunkUHXVYWTF_cjs.parseHostedAuthCallback; }
5096
+ get: function () { return chunkFGWMLLEC_cjs.parseHostedAuthCallback; }
5213
5097
  });
5214
5098
  Object.defineProperty(exports, "persistHostedAuthPendingTransaction", {
5215
5099
  enumerable: true,
5216
- get: function () { return chunkUHXVYWTF_cjs.persistHostedAuthPendingTransaction; }
5100
+ get: function () { return chunkFGWMLLEC_cjs.persistHostedAuthPendingTransaction; }
5217
5101
  });
5218
5102
  Object.defineProperty(exports, "readHostedAuthPendingTransaction", {
5219
5103
  enumerable: true,
5220
- get: function () { return chunkUHXVYWTF_cjs.readHostedAuthPendingTransaction; }
5104
+ get: function () { return chunkFGWMLLEC_cjs.readHostedAuthPendingTransaction; }
5221
5105
  });
5222
5106
  Object.defineProperty(exports, "readStoredHostedAuthSession", {
5223
5107
  enumerable: true,
5224
- get: function () { return chunkUHXVYWTF_cjs.readStoredHostedAuthSession; }
5108
+ get: function () { return chunkFGWMLLEC_cjs.readStoredHostedAuthSession; }
5109
+ });
5110
+ Object.defineProperty(exports, "requireDepositLockOwner", {
5111
+ enumerable: true,
5112
+ get: function () { return chunkFGWMLLEC_cjs.requireDepositLockOwner; }
5113
+ });
5114
+ Object.defineProperty(exports, "requireServiceAddress", {
5115
+ enumerable: true,
5116
+ get: function () { return chunkFGWMLLEC_cjs.requireServiceAddress; }
5225
5117
  });
5226
5118
  Object.defineProperty(exports, "savePendingLock", {
5227
5119
  enumerable: true,
5228
- get: function () { return chunkUHXVYWTF_cjs.savePendingLock; }
5120
+ get: function () { return chunkFGWMLLEC_cjs.savePendingLock; }
5229
5121
  });
5230
5122
  Object.defineProperty(exports, "signLockMessage", {
5231
5123
  enumerable: true,
5232
- get: function () { return chunkUHXVYWTF_cjs.signLockMessage; }
5124
+ get: function () { return chunkFGWMLLEC_cjs.signLockMessage; }
5233
5125
  });
5234
5126
  Object.defineProperty(exports, "signModifyLockMessage", {
5235
5127
  enumerable: true,
5236
- get: function () { return chunkUHXVYWTF_cjs.signModifyLockMessage; }
5128
+ get: function () { return chunkFGWMLLEC_cjs.signModifyLockMessage; }
5237
5129
  });
5238
5130
  Object.defineProperty(exports, "signTransferLockedMessage", {
5239
5131
  enumerable: true,
5240
- get: function () { return chunkUHXVYWTF_cjs.signTransferLockedMessage; }
5132
+ get: function () { return chunkFGWMLLEC_cjs.signTransferLockedMessage; }
5241
5133
  });
5242
5134
  Object.defineProperty(exports, "signTransferMessage", {
5243
5135
  enumerable: true,
5244
- get: function () { return chunkUHXVYWTF_cjs.signTransferMessage; }
5136
+ get: function () { return chunkFGWMLLEC_cjs.signTransferMessage; }
5245
5137
  });
5246
5138
  Object.defineProperty(exports, "signWithdrawFromLockMessage", {
5247
5139
  enumerable: true,
5248
- get: function () { return chunkUHXVYWTF_cjs.signWithdrawFromLockMessage; }
5140
+ get: function () { return chunkFGWMLLEC_cjs.signWithdrawFromLockMessage; }
5249
5141
  });
5250
5142
  Object.defineProperty(exports, "signWithdrawMessage", {
5251
5143
  enumerable: true,
5252
- get: function () { return chunkUHXVYWTF_cjs.signWithdrawMessage; }
5144
+ get: function () { return chunkFGWMLLEC_cjs.signWithdrawMessage; }
5253
5145
  });
5254
5146
  Object.defineProperty(exports, "stripHostedAuthCallbackParams", {
5255
5147
  enumerable: true,
5256
- get: function () { return chunkUHXVYWTF_cjs.stripHostedAuthCallbackParams; }
5148
+ get: function () { return chunkFGWMLLEC_cjs.stripHostedAuthCallbackParams; }
5257
5149
  });
5258
5150
  Object.defineProperty(exports, "submitPendingLock", {
5259
5151
  enumerable: true,
5260
- get: function () { return chunkUHXVYWTF_cjs.submitPendingLock; }
5152
+ get: function () { return chunkFGWMLLEC_cjs.submitPendingLock; }
5261
5153
  });
5262
5154
  Object.defineProperty(exports, "syncHostedAuthSessionToClient", {
5263
5155
  enumerable: true,
5264
- get: function () { return chunkUHXVYWTF_cjs.syncHostedAuthSessionToClient; }
5156
+ get: function () { return chunkFGWMLLEC_cjs.syncHostedAuthSessionToClient; }
5265
5157
  });
5266
5158
  Object.defineProperty(exports, "useDepositVerification", {
5267
5159
  enumerable: true,
5268
- get: function () { return chunkUHXVYWTF_cjs.useDepositVerification; }
5160
+ get: function () { return chunkFGWMLLEC_cjs.useDepositVerification; }
5269
5161
  });
5270
5162
  Object.defineProperty(exports, "usePrivanaContext", {
5271
5163
  enumerable: true,
5272
- get: function () { return chunkUHXVYWTF_cjs.usePrivanaContext; }
5164
+ get: function () { return chunkFGWMLLEC_cjs.usePrivanaContext; }
5273
5165
  });
5274
5166
  Object.defineProperty(exports, "useSafeAccount", {
5275
5167
  enumerable: true,
5276
- get: function () { return chunkUHXVYWTF_cjs.useSafeAccount; }
5168
+ get: function () { return chunkFGWMLLEC_cjs.useSafeAccount; }
5277
5169
  });
5278
5170
  Object.defineProperty(exports, "useSafePrivanaContext", {
5279
5171
  enumerable: true,
5280
- get: function () { return chunkUHXVYWTF_cjs.useSafePrivanaContext; }
5172
+ get: function () { return chunkFGWMLLEC_cjs.useSafePrivanaContext; }
5281
5173
  });
5282
5174
  Object.defineProperty(exports, "useSiweAuth", {
5283
5175
  enumerable: true,
5284
- get: function () { return chunkUHXVYWTF_cjs.useSiweAuth; }
5176
+ get: function () { return chunkFGWMLLEC_cjs.useSiweAuth; }
5285
5177
  });
5286
5178
  exports.DepositInlineModal = DepositInlineModal;
5287
5179
  exports.DepositModal = DepositModal;
5288
- exports.PrivanaButton = PrivanaButton;
5289
5180
  exports.PrivanaIcon = PrivanaIcon;
5290
- exports.PrivanaInlineModal = PrivanaInlineModal;
5291
- exports.PrivanaModal = PrivanaModal;
5292
5181
  exports.WalletInlineModal = WalletInlineModal;
5293
5182
  exports.WalletModal = WalletModal;
5294
5183
  exports.WithdrawInlineModal = WithdrawInlineModal;