@oasisprotocol/privana-sdk 0.5.0 → 0.5.1

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.js CHANGED
@@ -1,9 +1,9 @@
1
1
  "use client";
2
- import { usePrivanaContext, createHostedAuthPendingStorageKey, clearHostedAuthPendingTransaction, HostedAuthRequiredError, HostedAuthError, createPkceVerifier, createPkceChallenge, createHostedAuthState, persistHostedAuthPendingTransaction, parseHostedAuthCallback, readHostedAuthPendingTransaction, HostedAuthStateMismatchError, buildHostedAuthSession, useSafePrivanaContext, usePrivateReadRequest, formatTokenAmount, useDepositVerification, getTransactionReceipt, waitForTransactionReceipt, cn, Button, stripHostedAuthCallbackParams, AccountingApiError, getChainId2, shortenAddress, formatTimeRemaining, parseTokenAmount, getExplorerAddressUrl, getExplorerLabel, Skeleton, FiatOnRampForm } from './chunk-54FC6TO3.js';
3
- export { AccountingApiError, Button, HOSTED_AUTH_CLOCK_SKEW_MS, HostedAuthError, HostedAuthRequiredError, HostedAuthStateMismatchError, HttpClient, NETWORK_CONFIG, NetworkError, PrivanaClient, PrivanaProvider, SUPPORTED_CHAINS, SiweAuthProvider, Skeleton, ValidationError, applyRefreshResponse, buildHostedAuthSession, buildSiweStatement, buttonVariants, clearHostedAuthPendingTransaction, createHostedAuthPendingStorageKey, createHostedAuthState, createHostedAuthStorageKey, createPkceChallenge, createPkceVerifier, getAccountingContract, getApiUrl, getChainById, getChainId, getExplorerAddressUrl, getExplorerLabel, isHostedAuthRefreshActive, isHostedAuthSessionActive, normalizeAddress, normalizeHex, parseHostedAuthCallback, persistHostedAuthPendingTransaction, readHostedAuthPendingTransaction, readStoredHostedAuthSession, stripHostedAuthCallbackParams, syncHostedAuthSessionToClient, useDepositVerification, usePrivanaContext, useSafeAccount, useSafePrivanaContext, useSiweAuth } from './chunk-54FC6TO3.js';
2
+ import { usePrivanaContext, createHostedAuthPendingStorageKey, clearHostedAuthPendingTransaction, HostedAuthRequiredError, HostedAuthError, createPkceVerifier, createPkceChallenge, createHostedAuthState, persistHostedAuthPendingTransaction, parseHostedAuthCallback, readHostedAuthPendingTransaction, HostedAuthStateMismatchError, buildHostedAuthSession, useSafePrivanaContext, usePrivateReadRequest, formatTokenAmount, submitPendingLock, PostDepositLockError, useDepositVerification, useEnsureCorrectChain, getTransactionReceipt, waitForTransactionReceipt, canUseBrowserStorage, clampLockAmount, getWalletClient, createSignedLockRequest, signWithdrawMessage, signLockMessage, signTransferMessage, signTransferLockedMessage, signModifyLockMessage, cn, Button, stripHostedAuthCallbackParams, AccountingApiError, getBrowserStorageItem, removeBrowserStorageItem, isSignedLockUsable, setBrowserStorageItem, shortenAddress, formatTimeRemaining, parseTokenAmount, getExplorerAddressUrl, getExplorerLabel, Skeleton, formatCountdown, FiatOnRampForm } from './chunk-SAJ7K5WT.js';
3
+ export { AccountingApiError, Button, DEFAULT_LOCK_DURATION_SECONDS, DEFAULT_ONRAMP_LOCK_BUFFER, HOSTED_AUTH_CLOCK_SKEW_MS, HostedAuthError, HostedAuthRequiredError, HostedAuthStateMismatchError, HttpClient, LOCK_TYPES, MODIFY_LOCK_TYPES, NETWORK_CONFIG, NetworkError, PostDepositLockError, PrivanaClient, PrivanaProvider, SUPPORTED_CHAINS, SiweAuthProvider, Skeleton, TRANSFER_LOCKED_TYPES, TRANSFER_TYPES, ValidationError, WITHDRAW_FROM_LOCK_TYPES, WITHDRAW_TYPES, applyLockBuffer, applyRefreshResponse, buildHostedAuthSession, buildSiweStatement, buttonVariants, clampLockAmount, clearHostedAuthPendingTransaction, clearPendingLock, createDomain, createHostedAuthPendingStorageKey, createHostedAuthState, createHostedAuthStorageKey, createLockExpiry, createPkceChallenge, createPkceVerifier, createSignedLockRequest, getAccountingContract, getApiUrl, getChainById, getChainId, getExplorerAddressUrl, getExplorerLabel, isHostedAuthRefreshActive, isHostedAuthSessionActive, isSignedLockUsable, loadPendingLock, normalizeAddress, normalizeHex, parseHostedAuthCallback, persistHostedAuthPendingTransaction, readHostedAuthPendingTransaction, readStoredHostedAuthSession, savePendingLock, signLockMessage, signModifyLockMessage, signTransferLockedMessage, signTransferMessage, signWithdrawFromLockMessage, signWithdrawMessage, stripHostedAuthCallbackParams, submitPendingLock, syncHostedAuthSessionToClient, useDepositVerification, usePrivanaContext, useSafeAccount, useSafePrivanaContext, useSiweAuth } from './chunk-SAJ7K5WT.js';
4
4
  import { useState, useRef, useMemo, useCallback, useContext, useEffect, useId } from 'react';
5
5
  import { QueryClientContext, useQuery, useQueryClient, useMutation, keepPreviousData } from '@tanstack/react-query';
6
- import { useAccount, useWalletClient, useConfig, useWriteContract, useSendTransaction, useChainId, useSwitchChain, useBalance as useBalance$1, useReadContract } from 'wagmi';
6
+ import { useAccount, useWalletClient, useConfig, useWriteContract, useSendTransaction, useBalance as useBalance$1, useReadContract } from 'wagmi';
7
7
  import { zeroAddress, erc20Abi } from 'viem';
8
8
  import * as DialogPrimitive from '@radix-ui/react-dialog';
9
9
  import { XIcon } from 'lucide-react';
@@ -12,202 +12,6 @@ import { toast } from 'sonner';
12
12
  import { QRCodeSVG } from 'qrcode.react';
13
13
  import { MoonPayProvider, MoonPayContext } from '@moonpay/moonpay-react';
14
14
 
15
- // src/sdk/signatures/eip712-types.ts
16
- function createDomain(chainId, verifyingContract) {
17
- return {
18
- name: "AccountingModule",
19
- version: "1",
20
- chainId,
21
- verifyingContract
22
- };
23
- }
24
- var LOCK_TYPES = {
25
- Lock: [
26
- { name: "serviceAddress", type: "address" },
27
- { name: "tokenId", type: "bytes32" },
28
- { name: "amount", type: "uint256" },
29
- { name: "expiry", type: "uint256" },
30
- { name: "nonce", type: "uint256" }
31
- ]
32
- };
33
- var TRANSFER_TYPES = {
34
- Transfer: [
35
- { name: "toAddress", type: "address" },
36
- { name: "tokenId", type: "bytes32" },
37
- { name: "amount", type: "uint256" },
38
- { name: "nonce", type: "uint256" }
39
- ]
40
- };
41
- var TRANSFER_LOCKED_TYPES = {
42
- TransferLocked: [
43
- { name: "userAddress", type: "address" },
44
- { name: "toAddress", type: "address" },
45
- { name: "lockId", type: "uint256" },
46
- { name: "amount", type: "uint256" },
47
- { name: "nonce", type: "uint256" },
48
- { name: "serviceAddress", type: "address" }
49
- ]
50
- };
51
- var WITHDRAW_TYPES = {
52
- Withdraw: [
53
- { name: "tokenId", type: "bytes32" },
54
- { name: "amount", type: "uint256" },
55
- { name: "nonce", type: "uint256" }
56
- ]
57
- };
58
- var MODIFY_LOCK_TYPES = {
59
- ModifyLock: [
60
- { name: "lockId", type: "uint256" },
61
- { name: "amount", type: "uint256" },
62
- { name: "newExpiry", type: "uint256" },
63
- { name: "nonce", type: "uint256" }
64
- ]
65
- };
66
- var WITHDRAW_FROM_LOCK_TYPES = {
67
- WithdrawFromLock: [
68
- { name: "userAddress", type: "address" },
69
- { name: "toAddress", type: "address" },
70
- { name: "lockId", type: "uint256" },
71
- { name: "amount", type: "uint256" },
72
- { name: "nonce", type: "uint256" }
73
- ]
74
- };
75
-
76
- // src/sdk/signatures/sign-lock.ts
77
- async function signLockMessage({
78
- walletClient,
79
- chainId,
80
- verifyingContract,
81
- message
82
- }) {
83
- const account = walletClient.account;
84
- if (!account) {
85
- throw new Error("No account connected to wallet client");
86
- }
87
- const domain = createDomain(chainId, verifyingContract);
88
- const signature = await walletClient.signTypedData({
89
- account,
90
- domain,
91
- types: LOCK_TYPES,
92
- primaryType: "Lock",
93
- message
94
- });
95
- return signature;
96
- }
97
- function createLockExpiry(minutesFromNow = 60) {
98
- return BigInt(Math.floor(Date.now() / 1e3) + minutesFromNow * 60);
99
- }
100
-
101
- // src/sdk/signatures/sign-modify-lock.ts
102
- async function signModifyLockMessage({
103
- walletClient,
104
- chainId,
105
- verifyingContract,
106
- message
107
- }) {
108
- const account = walletClient.account;
109
- if (!account) {
110
- throw new Error("No account connected to wallet client");
111
- }
112
- const domain = createDomain(chainId, verifyingContract);
113
- const signature = await walletClient.signTypedData({
114
- account,
115
- domain,
116
- types: MODIFY_LOCK_TYPES,
117
- primaryType: "ModifyLock",
118
- message
119
- });
120
- return signature;
121
- }
122
-
123
- // src/sdk/signatures/sign-transfer.ts
124
- async function signTransferMessage({
125
- walletClient,
126
- chainId,
127
- verifyingContract,
128
- message
129
- }) {
130
- const account = walletClient.account;
131
- if (!account) {
132
- throw new Error("No account connected to wallet client");
133
- }
134
- const domain = createDomain(chainId, verifyingContract);
135
- const signature = await walletClient.signTypedData({
136
- account,
137
- domain,
138
- types: TRANSFER_TYPES,
139
- primaryType: "Transfer",
140
- message
141
- });
142
- return signature;
143
- }
144
-
145
- // src/sdk/signatures/sign-transfer-locked.ts
146
- async function signTransferLockedMessage({
147
- walletClient,
148
- chainId,
149
- verifyingContract,
150
- message
151
- }) {
152
- const account = walletClient.account;
153
- if (!account) {
154
- throw new Error("No account connected to wallet client");
155
- }
156
- const domain = createDomain(chainId, verifyingContract);
157
- const signature = await walletClient.signTypedData({
158
- account,
159
- domain,
160
- types: TRANSFER_LOCKED_TYPES,
161
- primaryType: "TransferLocked",
162
- message
163
- });
164
- return signature;
165
- }
166
-
167
- // src/sdk/signatures/sign-withdraw.ts
168
- async function signWithdrawMessage({
169
- walletClient,
170
- chainId,
171
- verifyingContract,
172
- message
173
- }) {
174
- const account = walletClient.account;
175
- if (!account) {
176
- throw new Error("No account connected to wallet client");
177
- }
178
- const domain = createDomain(chainId, verifyingContract);
179
- const signature = await walletClient.signTypedData({
180
- account,
181
- domain,
182
- types: WITHDRAW_TYPES,
183
- primaryType: "Withdraw",
184
- message
185
- });
186
- return signature;
187
- }
188
-
189
- // src/sdk/signatures/sign-withdraw-from-lock.ts
190
- async function signWithdrawFromLockMessage({
191
- walletClient,
192
- chainId,
193
- verifyingContract,
194
- message
195
- }) {
196
- const account = walletClient.account;
197
- if (!account) {
198
- throw new Error("No account connected to wallet client");
199
- }
200
- const domain = createDomain(chainId, verifyingContract);
201
- const signature = await walletClient.signTypedData({
202
- account,
203
- domain,
204
- types: WITHDRAW_FROM_LOCK_TYPES,
205
- primaryType: "WithdrawFromLock",
206
- message
207
- });
208
- return signature;
209
- }
210
-
211
15
  // src/sdk/hooks/use-privana-client.ts
212
16
  function usePrivanaClient() {
213
17
  const { client } = usePrivanaContext();
@@ -468,75 +272,22 @@ function useBatchBalances(options) {
468
272
  refetch: query.refetch
469
273
  };
470
274
  }
471
- function useEnsureCorrectChain() {
472
- const config = useConfig();
473
- const chainId = useChainId();
474
- const { switchChainAsync } = useSwitchChain();
475
- const waitUntilOnChain = useCallback(
476
- async (expectedChainId, timeoutMs, pollIntervalMs = 250) => {
477
- const startedAt = Date.now();
478
- while (Date.now() - startedAt < timeoutMs) {
479
- const currentChainId = getChainId2(config);
480
- if (currentChainId === expectedChainId) return true;
481
- await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
482
- }
483
- return false;
484
- },
485
- [config]
486
- );
487
- const ensureCorrectChain = useCallback(
488
- async (targetChainId) => {
489
- const currentChainId = getChainId2(config);
490
- if (currentChainId === targetChainId) return false;
491
- let switchErrorMessage;
492
- try {
493
- const timeoutPromise = new Promise((_, reject) => {
494
- setTimeout(() => reject(new Error("Chain switch timeout")), 3e3);
495
- });
496
- await Promise.race([switchChainAsync({ chainId: targetChainId }), timeoutPromise]);
497
- } catch (error) {
498
- if (error instanceof Error && error.message.includes("Unsupported Chain")) {
499
- console.warn("Got 'Unsupported Chain' error, chain may have switched anyway.");
500
- } else {
501
- switchErrorMessage = error instanceof Error ? error.message : "Unknown chain switch error";
502
- }
503
- }
504
- const settled = await waitUntilOnChain(targetChainId, 2e4);
505
- if (settled) return true;
506
- if (switchErrorMessage) {
507
- throw new Error(
508
- `Failed to switch to chain (Chain ID: ${targetChainId}): ${switchErrorMessage}`
509
- );
510
- }
511
- throw new Error(`Chain switch did not settle in time (expected ${targetChainId}).`);
512
- },
513
- [config, switchChainAsync, waitUntilOnChain]
514
- );
515
- const isOnChain = useCallback((targetChainId) => chainId === targetChainId, [chainId]);
516
- return {
517
- chainId,
518
- ensureCorrectChain,
519
- isOnChain
520
- };
521
- }
522
-
523
- // src/sdk/hooks/use-deposit.ts
524
275
  var STALE_MS = 30 * 60 * 1e3;
525
276
  function storageKey(address) {
526
277
  return `privana:pending-deposit:${address.toLowerCase()}`;
527
278
  }
528
279
  function savePendingDeposit(address, data) {
529
- try {
530
- sessionStorage.setItem(storageKey(address), JSON.stringify(data));
531
- } catch {
280
+ const stored = setBrowserStorageItem(storageKey(address), JSON.stringify(data));
281
+ if (!stored && data.signedLock) {
282
+ throw new Error("Unable to persist pending locked deposit for recovery");
532
283
  }
533
284
  }
534
285
  function loadPendingDeposit(address) {
535
286
  try {
536
- const raw = sessionStorage.getItem(storageKey(address));
287
+ const raw = getBrowserStorageItem(storageKey(address));
537
288
  if (!raw) return null;
538
289
  const data = JSON.parse(raw);
539
- if (Date.now() - data.savedAt > STALE_MS) {
290
+ if (Date.now() - data.savedAt > STALE_MS && !(data.signedLock && isSignedLockUsable(data.signedLock))) {
540
291
  clearPendingDeposit(address);
541
292
  return null;
542
293
  }
@@ -545,15 +296,20 @@ function loadPendingDeposit(address) {
545
296
  return null;
546
297
  }
547
298
  }
548
- function clearPendingDeposit(address) {
549
- try {
550
- sessionStorage.removeItem(storageKey(address));
551
- } catch {
299
+ function clearPendingDeposit(address, onlyForTxHash) {
300
+ if (onlyForTxHash) {
301
+ try {
302
+ const raw = getBrowserStorageItem(storageKey(address));
303
+ const recordTxHash = raw ? JSON.parse(raw).txHash : void 0;
304
+ if (recordTxHash && recordTxHash !== onlyForTxHash) return;
305
+ } catch {
306
+ }
552
307
  }
308
+ removeBrowserStorageItem(storageKey(address));
553
309
  }
554
310
  function useDeposit(options = {}) {
555
311
  const { address } = useAccount();
556
- const { client, enabledTokens, getChainById: getChainById2 } = usePrivanaContext();
312
+ const { client, enabledTokens, getChainById: getChainById2, networkConfig, serviceAddress } = usePrivanaContext();
557
313
  const { data: walletClient } = useWalletClient();
558
314
  const queryClient = useQueryClient();
559
315
  const config = useConfig();
@@ -570,21 +326,54 @@ function useDeposit(options = {}) {
570
326
  const onDepositAddressReceivedRef = useRef(options.onDepositAddressReceived);
571
327
  const onDepositSuccessRef = useRef(options.onDepositSuccess);
572
328
  const onCreditedRef = useRef(options.onCredited);
329
+ const onLockSubmittedRef = useRef(options.onLockSubmitted);
330
+ const onLockFailedRef = useRef(options.onLockFailed);
573
331
  const onCheckTimeoutRef = useRef(options.onCheckTimeout);
574
332
  const onErrorRef = useRef(options.onError);
575
333
  useEffect(() => {
576
334
  onDepositAddressReceivedRef.current = options.onDepositAddressReceived;
577
335
  onDepositSuccessRef.current = options.onDepositSuccess;
578
336
  onCreditedRef.current = options.onCredited;
337
+ onLockSubmittedRef.current = options.onLockSubmitted;
338
+ onLockFailedRef.current = options.onLockFailed;
579
339
  onCheckTimeoutRef.current = options.onCheckTimeout;
580
340
  onErrorRef.current = options.onError;
581
341
  }, [
582
342
  options.onDepositAddressReceived,
583
343
  options.onDepositSuccess,
584
344
  options.onCredited,
345
+ options.onLockSubmitted,
346
+ options.onLockFailed,
585
347
  options.onCheckTimeout,
586
348
  options.onError
587
349
  ]);
350
+ const pendingLockRef = useRef(null);
351
+ const submitPendingLockAfterCredit = useCallback(
352
+ async (signedLock, response) => {
353
+ try {
354
+ const result = await submitPendingLock({
355
+ client,
356
+ payload: signedLock,
357
+ creditedAmount: response.amount != null ? BigInt(response.amount) : void 0
358
+ });
359
+ queryClient.invalidateQueries({ queryKey: ["accounting-balance"] });
360
+ queryClient.invalidateQueries({ queryKey: ["accounting-locked-funds"] });
361
+ queryClient.invalidateQueries({ queryKey: ["accounting-total-locked-balance"] });
362
+ queryClient.invalidateQueries({ queryKey: ["accounting-history"] });
363
+ onLockSubmittedRef.current?.(result);
364
+ } catch (err) {
365
+ const error2 = err instanceof PostDepositLockError ? err : new PostDepositLockError(
366
+ err instanceof Error ? err.message : "Lock submission failed",
367
+ "submission-failed",
368
+ BigInt(signedLock.amount),
369
+ void 0,
370
+ { cause: err }
371
+ );
372
+ (onLockFailedRef.current ?? onErrorRef.current)?.(error2);
373
+ }
374
+ },
375
+ [client, queryClient]
376
+ );
588
377
  const {
589
378
  isVerifying,
590
379
  didTimeout,
@@ -597,8 +386,16 @@ function useDeposit(options = {}) {
597
386
  pollTimeout: options.pollTimeout,
598
387
  onCredited: (hash, response) => {
599
388
  verificationContextRef.current = null;
600
- if (address) clearPendingDeposit(address);
601
- onCreditedRef.current?.(hash, response);
389
+ const signedLock = pendingLockRef.current;
390
+ pendingLockRef.current = null;
391
+ if (signedLock) {
392
+ void submitPendingLockAfterCredit(signedLock, response).finally(() => {
393
+ if (address) clearPendingDeposit(address, hash);
394
+ });
395
+ } else if (address) {
396
+ clearPendingDeposit(address);
397
+ }
398
+ onCreditedRef.current?.(hash, response, signedLock !== null);
602
399
  },
603
400
  onCheckTimeout: (hash) => {
604
401
  onCheckTimeoutRef.current?.(hash);
@@ -649,6 +446,7 @@ function useDeposit(options = {}) {
649
446
  resetVerification();
650
447
  if (address) clearPendingDeposit(address);
651
448
  verificationContextRef.current = null;
449
+ pendingLockRef.current = null;
652
450
  setDepositAddress(null);
653
451
  setTxHash(void 0);
654
452
  setIsSwitchingChain(false);
@@ -668,6 +466,7 @@ function useDeposit(options = {}) {
668
466
  setTxHash(hash);
669
467
  setDepositAddress(persisted.depositAddress);
670
468
  setIsWaitingForConfirmation(true);
469
+ pendingLockRef.current = persisted.signedLock ?? null;
671
470
  const ctx = {
672
471
  hash,
673
472
  chainId: persisted.chainId,
@@ -724,13 +523,6 @@ function useDeposit(options = {}) {
724
523
  if (!sourceChain) throw new Error(`Chain ${token.chainId} not configured`);
725
524
  const addrResponse = await addressMutation.mutateAsync();
726
525
  if (isStale()) return;
727
- setIsSwitchingChain(true);
728
- try {
729
- await ensureCorrectChain(sourceChain.id);
730
- } finally {
731
- if (!isStale()) setIsSwitchingChain(false);
732
- }
733
- if (isStale()) return;
734
526
  const depositAddr = addrResponse.deposit_address;
735
527
  if (!depositAddr || depositAddr === zeroAddress) {
736
528
  throw new Error("Invalid deposit address received from API");
@@ -743,6 +535,43 @@ function useDeposit(options = {}) {
743
535
  `Amount is below the minimum deposit (${minAmountStr}) for ${isNative ? "native" : "ERC-20"} on chain ${sourceChain.id}`
744
536
  );
745
537
  }
538
+ if (params.postDepositLock && !canUseBrowserStorage()) {
539
+ throw new Error("Browser storage is required for locked deposit recovery");
540
+ }
541
+ const lockAmount = clampLockAmount(params.amount, params.postDepositLock?.maxAmount);
542
+ let signedLock;
543
+ if (params.postDepositLock) {
544
+ setIsSwitchingChain(true);
545
+ try {
546
+ await ensureCorrectChain(networkConfig.chainId);
547
+ } finally {
548
+ if (!isStale()) setIsSwitchingChain(false);
549
+ }
550
+ if (isStale()) return;
551
+ const signingWalletClient = await getWalletClient(config, {
552
+ chainId: networkConfig.chainId
553
+ });
554
+ signedLock = await createSignedLockRequest({
555
+ client,
556
+ walletClient: signingWalletClient,
557
+ userAddress: address,
558
+ networkConfig,
559
+ serviceAddress: requireServiceAddress(
560
+ params.postDepositLock.serviceAddress ?? serviceAddress
561
+ ),
562
+ tokenId: params.tokenId,
563
+ amount: lockAmount,
564
+ lockDuration: params.postDepositLock.lockDuration
565
+ });
566
+ }
567
+ if (isStale()) return;
568
+ setIsSwitchingChain(true);
569
+ try {
570
+ await ensureCorrectChain(sourceChain.id);
571
+ } finally {
572
+ if (!isStale()) setIsSwitchingChain(false);
573
+ }
574
+ if (isStale()) return;
746
575
  const hash = token.contract === zeroAddress ? await sendTransactionAsync({
747
576
  to: depositAddr,
748
577
  value: params.amount,
@@ -762,13 +591,19 @@ function useDeposit(options = {}) {
762
591
  amount: params.amount
763
592
  };
764
593
  verificationContextRef.current = ctx;
765
- savePendingDeposit(address, {
766
- txHash: hash,
767
- chainId: sourceChain.id,
768
- amount: params.amount.toString(),
769
- depositAddress: addrResponse,
770
- savedAt: Date.now()
771
- });
594
+ pendingLockRef.current = signedLock ?? null;
595
+ try {
596
+ savePendingDeposit(address, {
597
+ txHash: hash,
598
+ chainId: sourceChain.id,
599
+ amount: params.amount.toString(),
600
+ depositAddress: addrResponse,
601
+ signedLock,
602
+ savedAt: Date.now()
603
+ });
604
+ } catch (err) {
605
+ console.warn("Failed to persist pending deposit after transfer broadcast:", err);
606
+ }
772
607
  try {
773
608
  setIsWaitingForConfirmation(true);
774
609
  try {
@@ -803,12 +638,15 @@ function useDeposit(options = {}) {
803
638
  address,
804
639
  walletClient,
805
640
  addressMutation,
641
+ client,
806
642
  getChainById2,
807
643
  config,
808
644
  confirmations,
809
645
  enabledTokens,
810
646
  ensureCorrectChain,
647
+ networkConfig,
811
648
  queryClient,
649
+ serviceAddress,
812
650
  writeContractAsync,
813
651
  sendTransactionAsync,
814
652
  reset,
@@ -843,6 +681,12 @@ function useDeposit(options = {}) {
843
681
  reset
844
682
  };
845
683
  }
684
+ function requireServiceAddress(serviceAddress) {
685
+ if (!serviceAddress) {
686
+ throw new Error("Service address not configured");
687
+ }
688
+ return serviceAddress;
689
+ }
846
690
  function useDepositAddress(options = {}) {
847
691
  const queryClient = useContext(QueryClientContext);
848
692
  const accountingContext = useSafePrivanaContext();
@@ -1370,6 +1214,59 @@ function useExpiredLocks(options = {}) {
1370
1214
  refetch: query.refetch
1371
1215
  };
1372
1216
  }
1217
+ function statusCodeOf(error) {
1218
+ return error instanceof AccountingApiError ? error.statusCode : void 0;
1219
+ }
1220
+ function usePendingDeposits(options = {}) {
1221
+ const queryClient = useContext(QueryClientContext);
1222
+ const accountingContext = useSafePrivanaContext();
1223
+ const hasProviders = !!queryClient && !!accountingContext;
1224
+ const client = accountingContext?.client;
1225
+ const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = usePrivateReadRequest();
1226
+ const { chainId, tokenAddress, lookbackBlocks } = options;
1227
+ const query = useQuery({
1228
+ queryKey: ["accounting-pending-deposits", ...privateReadQueryScope, chainId, tokenAddress],
1229
+ queryFn: async () => {
1230
+ if (!privateReadAddress) throw new Error("No authenticated account available");
1231
+ if (!chainId) throw new Error("No chain ID provided");
1232
+ if (!client) throw new Error("No accounting client");
1233
+ try {
1234
+ return await executePrivateRead(
1235
+ () => client.getPendingDeposits({
1236
+ chain_id: chainId,
1237
+ token_address: tokenAddress,
1238
+ lookback_blocks: lookbackBlocks
1239
+ })
1240
+ );
1241
+ } catch (error) {
1242
+ if (statusCodeOf(error) === 404) {
1243
+ return { pending: [], scanned_from_block: 0, scanned_to_block: 0 };
1244
+ }
1245
+ throw error;
1246
+ }
1247
+ },
1248
+ enabled: hasProviders && (options.enabled ?? true) && privateReadReady && !!privateReadAddress && !!chainId && !!client,
1249
+ // A 503 means discovery is not configured for this chain server-side —
1250
+ // polling can't fix that, so stop until a manual refetch succeeds.
1251
+ refetchInterval: (query2) => statusCodeOf(query2.state.error) === 503 ? false : options.refetchInterval ?? 3e4,
1252
+ staleTime: 25e3,
1253
+ retry: (failureCount, error) => {
1254
+ const status = statusCodeOf(error);
1255
+ if (status === 429 || status === 404 || status === 503) return false;
1256
+ return failureCount < 2;
1257
+ }
1258
+ });
1259
+ return {
1260
+ pending: query.data?.pending ?? [],
1261
+ scannedToBlock: query.data?.scanned_to_block,
1262
+ isFetching: query.isFetching,
1263
+ isError: query.isError,
1264
+ error: query.error,
1265
+ isRateLimited: statusCodeOf(query.error) === 429,
1266
+ isUnavailable: statusCodeOf(query.error) === 503,
1267
+ refetch: async () => (await query.refetch()).data
1268
+ };
1269
+ }
1373
1270
  function usePendingWithdrawals(options = {}) {
1374
1271
  const { address, isConnected } = useAccount();
1375
1272
  const { client, pollingInterval } = usePrivanaContext();
@@ -3285,7 +3182,10 @@ function TokenSelectorView2({ selectedTokenId, onSelect }) {
3285
3182
  function CreditCardWidgetView({
3286
3183
  token,
3287
3184
  amount,
3288
- allowance
3185
+ allowance,
3186
+ onCredited,
3187
+ onLockSubmitted,
3188
+ onLockFailed
3289
3189
  }) {
3290
3190
  const moonpayCurrencyCode = token?.moonpayCurrencyCode;
3291
3191
  const containerRef = useRef(null);
@@ -3300,10 +3200,18 @@ function CreditCardWidgetView({
3300
3200
  {
3301
3201
  tokenId: token.id,
3302
3202
  currencyCode: moonpayCurrencyCode,
3303
- defaultBaseCurrencyAmount: amount || void 0,
3203
+ quoteCurrencyAmount: amount || void 0,
3204
+ lockAmount: true,
3304
3205
  variant: "embedded",
3305
3206
  autoStart: true,
3306
- theme: widgetTheme
3207
+ theme: widgetTheme,
3208
+ postDepositLock: allowance ? {
3209
+ maxAmount: BigInt(allowance.value),
3210
+ lockDuration: allowance.lockDuration
3211
+ } : void 0,
3212
+ onCredited,
3213
+ onLockSubmitted,
3214
+ onLockFailed
3307
3215
  }
3308
3216
  ) : /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-sm", children: [
3309
3217
  token?.symbol ?? "This token",
@@ -3605,7 +3513,7 @@ function DepositView({
3605
3513
  className: "bg-secondary text-foreground hover:bg-secondary/80 cursor-pointer rounded px-3 py-2.5 text-xs font-semibold transition-colors",
3606
3514
  children: "MAX"
3607
3515
  }
3608
- ) : isCreditCard ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: "USD" }) : selectedToken && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: selectedToken.symbol })
3516
+ ) : isCreditCard ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: selectedToken?.symbol ?? "USD" }) : selectedToken && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: selectedToken.symbol })
3609
3517
  ]
3610
3518
  }
3611
3519
  ),
@@ -3659,14 +3567,105 @@ function SummaryRow({ value, label }) {
3659
3567
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label })
3660
3568
  ] });
3661
3569
  }
3570
+ var LISTENING_WINDOW_MS = 36e5;
3571
+ function remainingSeconds(deadline) {
3572
+ return Math.max(0, Math.round((deadline - Date.now()) / 1e3));
3573
+ }
3574
+ function useCountdown(deadline) {
3575
+ const [secondsLeft, setSecondsLeft] = useState(() => remainingSeconds(deadline));
3576
+ useEffect(() => {
3577
+ if (remainingSeconds(deadline) <= 0) return;
3578
+ const id = setInterval(() => {
3579
+ const left = remainingSeconds(deadline);
3580
+ setSecondsLeft(left);
3581
+ if (left <= 0) clearInterval(id);
3582
+ }, 1e3);
3583
+ return () => clearInterval(id);
3584
+ }, [deadline]);
3585
+ return secondsLeft;
3586
+ }
3587
+ function AwaitingDepositStatus({
3588
+ title,
3589
+ subtitle,
3590
+ remaining
3591
+ }) {
3592
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3 text-center", children: [
3593
+ /* @__PURE__ */ jsx("div", { className: "text-foreground", children: /* @__PURE__ */ jsx(Spinner, { size: 32 }) }),
3594
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
3595
+ /* @__PURE__ */ jsx("h3", { className: "text-foreground text-xl leading-6 font-medium", children: title }),
3596
+ /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-sm leading-[18px]", children: [
3597
+ subtitle,
3598
+ remaining && /* @__PURE__ */ jsxs(Fragment, { children: [
3599
+ /* @__PURE__ */ jsx("br", {}),
3600
+ "Remaining time: ",
3601
+ remaining
3602
+ ] })
3603
+ ] })
3604
+ ] })
3605
+ ] });
3606
+ }
3662
3607
  function ExternalDepositView({
3663
3608
  token,
3664
- amount
3609
+ amount,
3610
+ onCredited
3665
3611
  }) {
3666
3612
  const { getChainById: getChainById2 } = usePrivanaContext();
3667
3613
  const { depositAddress, isReady, isLoading } = useDepositAddress();
3668
3614
  const chain = token ? getChainById2(token.chainId) : void 0;
3669
3615
  const [copied, setCopied] = useState(false);
3616
+ const [deadline] = useState(() => Date.now() + LISTENING_WINDOW_MS);
3617
+ const secondsLeft = useCountdown(deadline);
3618
+ const listening = secondsLeft > 0;
3619
+ const [nothingFound, setNothingFound] = useState(false);
3620
+ const [credited, setCredited] = useState(null);
3621
+ const verification = useDepositVerification({
3622
+ onCredited: (txHash) => {
3623
+ if (onCredited) {
3624
+ onCredited();
3625
+ return;
3626
+ }
3627
+ setCredited({ txHash });
3628
+ }
3629
+ });
3630
+ const { isVerifying, verificationFailed, didTimeout, verify } = verification;
3631
+ const scanPaused = isVerifying || verificationFailed || didTimeout || !!credited;
3632
+ const {
3633
+ pending,
3634
+ isFetching: isScanning,
3635
+ isError: isScanError,
3636
+ isRateLimited,
3637
+ isUnavailable,
3638
+ refetch: refetchPendingDeposits
3639
+ } = usePendingDeposits({
3640
+ chainId: token?.chainId,
3641
+ enabled: isReady && !!depositAddress && !!token,
3642
+ refetchInterval: listening && !scanPaused ? 3e4 : false
3643
+ });
3644
+ const processedRef = useRef(/* @__PURE__ */ new Set());
3645
+ useEffect(() => {
3646
+ if (scanPaused) return;
3647
+ const next = [...pending].sort((a, b) => a.block_number - b.block_number).find((d) => !processedRef.current.has(`${d.tx_hash}:${d.log_index}`));
3648
+ if (!next) return;
3649
+ processedRef.current.add(`${next.tx_hash}:${next.log_index}`);
3650
+ void verify({
3651
+ hash: next.tx_hash,
3652
+ chainId: next.chain_id,
3653
+ amount: BigInt(next.amount),
3654
+ logIndex: next.log_index
3655
+ });
3656
+ }, [pending, scanPaused, verify]);
3657
+ const nothingFoundTimerRef = useRef(void 0);
3658
+ useEffect(() => () => clearTimeout(nothingFoundTimerRef.current), []);
3659
+ const handleRefresh = () => {
3660
+ processedRef.current.clear();
3661
+ void refetchPendingDeposits().then((result) => {
3662
+ if (!result || result.pending.length === 0) {
3663
+ setNothingFound(true);
3664
+ clearTimeout(nothingFoundTimerRef.current);
3665
+ nothingFoundTimerRef.current = setTimeout(() => setNothingFound(false), 4e3);
3666
+ }
3667
+ });
3668
+ };
3670
3669
  const handleCopy = () => {
3671
3670
  if (!depositAddress) return;
3672
3671
  void navigator.clipboard.writeText(depositAddress);
@@ -3704,6 +3703,55 @@ function ExternalDepositView({
3704
3703
  }
3705
3704
  )
3706
3705
  ] })
3706
+ ] }),
3707
+ credited ? /* @__PURE__ */ jsx(
3708
+ TransactionSuccessView,
3709
+ {
3710
+ title: "Deposit Credited",
3711
+ message: `Transfer ${shortenAddress(credited.txHash)} has been credited to your Privana balance.`,
3712
+ onDone: () => {
3713
+ setCredited(null);
3714
+ verification.reset();
3715
+ void refetchPendingDeposits();
3716
+ }
3717
+ }
3718
+ ) : verificationFailed || didTimeout ? /* @__PURE__ */ jsx(
3719
+ TransactionErrorView,
3720
+ {
3721
+ title: "Could not verify deposit",
3722
+ 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.",
3723
+ onRetry: () => void verification.retryVerification(),
3724
+ onDismiss: () => verification.reset(),
3725
+ isRetrying: isVerifying
3726
+ }
3727
+ ) : isVerifying ? /* @__PURE__ */ jsx(
3728
+ AwaitingDepositStatus,
3729
+ {
3730
+ title: "Deposit detected",
3731
+ subtitle: "Crediting the incoming transaction to your Privana balance..."
3732
+ }
3733
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
3734
+ /* @__PURE__ */ jsx(
3735
+ AwaitingDepositStatus,
3736
+ {
3737
+ title: "Awaiting Deposit",
3738
+ 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.",
3739
+ remaining: listening ? formatCountdown(secondsLeft) : void 0
3740
+ }
3741
+ ),
3742
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
3743
+ /* @__PURE__ */ jsx(
3744
+ "button",
3745
+ {
3746
+ type: "button",
3747
+ onClick: handleRefresh,
3748
+ disabled: !depositAddress || isScanning,
3749
+ className: "bg-secondary text-foreground hover:bg-secondary/80 flex h-10 w-full 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",
3750
+ children: "Refresh deposit status"
3751
+ }
3752
+ ),
3753
+ isRateLimited ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Checked too recently \u2014 try again in a moment." }) : isUnavailable ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Deposit discovery is unavailable for this chain." }) : isScanError ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Chain temporarily unreachable \u2014 retrying automatically." }) : nothingFound ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-center text-sm", children: "No incoming transaction found yet." }) : null
3754
+ ] })
3707
3755
  ] })
3708
3756
  ] });
3709
3757
  }
@@ -3716,6 +3764,7 @@ function DepositModalContent({
3716
3764
  onConnectWallet,
3717
3765
  onDeposit,
3718
3766
  onDepositSuccess,
3767
+ onLockFailed,
3719
3768
  onClose,
3720
3769
  onCloseBlockedChange,
3721
3770
  onExit
@@ -3747,6 +3796,21 @@ function DepositModalContent({
3747
3796
  const [showSuccess, setShowSuccess] = useState(false);
3748
3797
  const [showTimeout, setShowTimeout] = useState(false);
3749
3798
  const [cancelled, setCancelled] = useState(false);
3799
+ const [isSubmittingLock, setIsSubmittingLock] = useState(false);
3800
+ const [lockFailedMessage, setLockFailedMessage] = useState(null);
3801
+ const finishDeposit = () => {
3802
+ setAmount("");
3803
+ if (onDepositSuccess) {
3804
+ resetDeposit();
3805
+ onDepositSuccess();
3806
+ } else {
3807
+ setShowSuccess(true);
3808
+ }
3809
+ };
3810
+ const finishCardPurchase = () => {
3811
+ setAmount("");
3812
+ onDepositSuccess?.();
3813
+ };
3750
3814
  const {
3751
3815
  txHash,
3752
3816
  isGettingAddress,
@@ -3761,14 +3825,24 @@ function DepositModalContent({
3761
3825
  retryVerification,
3762
3826
  reset: resetDeposit
3763
3827
  } = useDeposit({
3764
- onCredited: () => {
3765
- setAmount("");
3766
- if (onDepositSuccess) {
3767
- resetDeposit();
3768
- onDepositSuccess();
3769
- } else {
3770
- setShowSuccess(true);
3828
+ onCredited: (_txHash, _response, lockPending) => {
3829
+ if (lockPending) {
3830
+ setIsSubmittingLock(true);
3831
+ return;
3771
3832
  }
3833
+ finishDeposit();
3834
+ },
3835
+ onLockSubmitted: () => {
3836
+ setIsSubmittingLock(false);
3837
+ finishDeposit();
3838
+ },
3839
+ // The deposit credited; only the policy lock failed. Success must not
3840
+ // fire (the host would act on unlocked funds) — show the dedicated
3841
+ // error view and let the host re-prompt for a fresh lock.
3842
+ onLockFailed: (err) => {
3843
+ setIsSubmittingLock(false);
3844
+ setLockFailedMessage(err.message);
3845
+ onLockFailed?.(err);
3772
3846
  },
3773
3847
  onCheckTimeout: () => {
3774
3848
  setAmount("");
@@ -3801,7 +3875,11 @@ function DepositModalContent({
3801
3875
  setCancelled(false);
3802
3876
  deposit({
3803
3877
  tokenId: token.id,
3804
- amount: parseTokenAmount(args.amount, token.decimals)
3878
+ amount: parseTokenAmount(args.amount, token.decimals),
3879
+ postDepositLock: allowance ? {
3880
+ maxAmount: BigInt(allowance.value),
3881
+ lockDuration: allowance.lockDuration
3882
+ } : void 0
3805
3883
  }).catch((err) => {
3806
3884
  toast.error(err instanceof Error ? err.message : "Deposit failed");
3807
3885
  });
@@ -3811,26 +3889,32 @@ function DepositModalContent({
3811
3889
  const depositSteps = [
3812
3890
  {
3813
3891
  label: "Getting deposit address",
3814
- status: isGettingAddress ? "active" : isSwitchingChain || isSendingTransaction || isWaitingForConfirmation || isWaitingForProcessing ? "completed" : "pending"
3892
+ status: isGettingAddress ? "active" : isSwitchingChain || isSendingTransaction || isWaitingForConfirmation || isWaitingForProcessing || isSubmittingLock ? "completed" : "pending"
3815
3893
  },
3816
3894
  {
3817
3895
  label: `Switching to ${targetChain?.name ?? "deposit chain"}`,
3818
- status: isSwitchingChain ? "active" : isSendingTransaction || isWaitingForConfirmation || isWaitingForProcessing ? "completed" : "pending"
3896
+ status: isSwitchingChain ? "active" : isSendingTransaction || isWaitingForConfirmation || isWaitingForProcessing || isSubmittingLock ? "completed" : "pending"
3819
3897
  },
3820
3898
  {
3821
3899
  label: "Confirm in wallet",
3822
- status: isSendingTransaction ? "active" : isWaitingForConfirmation || isWaitingForProcessing ? "completed" : "pending"
3900
+ status: isSendingTransaction ? "active" : isWaitingForConfirmation || isWaitingForProcessing || isSubmittingLock ? "completed" : "pending"
3823
3901
  },
3824
3902
  {
3825
3903
  label: "Confirming transaction",
3826
- status: isWaitingForConfirmation ? "active" : isWaitingForProcessing ? "completed" : "pending"
3904
+ status: isWaitingForConfirmation ? "active" : isWaitingForProcessing || isSubmittingLock ? "completed" : "pending"
3827
3905
  },
3828
3906
  {
3829
3907
  label: "Verifying deposit \u2014 may take up to a few minutes",
3830
- status: isWaitingForProcessing ? "active" : "pending"
3831
- }
3908
+ status: isWaitingForProcessing ? "active" : isSubmittingLock ? "completed" : "pending"
3909
+ },
3910
+ ...allowance ? [
3911
+ {
3912
+ label: `Locking funds for ${appName}`,
3913
+ status: isSubmittingLock ? "active" : "pending"
3914
+ }
3915
+ ] : []
3832
3916
  ];
3833
- const flowView = showSuccess ? "deposit-success" : showTimeout ? "deposit-timeout" : verificationFailed ? "deposit-error" : isPending && !cancelled ? "depositing" : null;
3917
+ const flowView = showSuccess ? "deposit-success" : lockFailedMessage ? "lock-error" : showTimeout ? "deposit-timeout" : verificationFailed ? "deposit-error" : isPending && !cancelled || isSubmittingLock ? "depositing" : null;
3834
3918
  const activeView = flowView ?? view;
3835
3919
  const handleDepositDone = () => {
3836
3920
  setShowSuccess(false);
@@ -3842,6 +3926,12 @@ function DepositModalContent({
3842
3926
  setCancelled(true);
3843
3927
  resetDeposit();
3844
3928
  };
3929
+ const handleLockFailedDone = () => {
3930
+ setLockFailedMessage(null);
3931
+ setAmount("");
3932
+ setCancelled(false);
3933
+ resetDeposit();
3934
+ };
3845
3935
  const handleDismissVerificationError = () => {
3846
3936
  setAmount("");
3847
3937
  setCancelled(false);
@@ -3895,6 +3985,14 @@ function DepositModalContent({
3895
3985
  onDone: handleDepositDone
3896
3986
  }
3897
3987
  ),
3988
+ activeView === "lock-error" && /* @__PURE__ */ jsx(
3989
+ TransactionWarningView,
3990
+ {
3991
+ title: "Deposit credited, lock failed",
3992
+ message: `Your deposit was credited but locking the funds for ${appName} failed: ${lockFailedMessage}`,
3993
+ onDone: handleLockFailedDone
3994
+ }
3995
+ ),
3898
3996
  activeView === "deposit-timeout" && /* @__PURE__ */ jsx(
3899
3997
  TransactionWarningView,
3900
3998
  {
@@ -3988,8 +4086,28 @@ function DepositModalContent({
3988
4086
  }
3989
4087
  }
3990
4088
  ),
3991
- activeView === "external-deposit" && /* @__PURE__ */ jsx(ExternalDepositView, { token: selectedToken, amount }),
3992
- activeView === "credit-card-widget" && /* @__PURE__ */ jsx(MoonPayGate, { enabled: true, children: /* @__PURE__ */ jsx(CreditCardWidgetView, { token: selectedToken, amount, allowance }) })
4089
+ activeView === "external-deposit" && /* @__PURE__ */ jsx(
4090
+ ExternalDepositView,
4091
+ {
4092
+ token: selectedToken,
4093
+ amount,
4094
+ onCredited: allowance ? void 0 : onDepositSuccess
4095
+ }
4096
+ ),
4097
+ activeView === "credit-card-widget" && /* @__PURE__ */ jsx(MoonPayGate, { enabled: true, children: /* @__PURE__ */ jsx(
4098
+ CreditCardWidgetView,
4099
+ {
4100
+ token: selectedToken,
4101
+ amount,
4102
+ allowance,
4103
+ onCredited: allowance ? void 0 : finishCardPurchase,
4104
+ onLockSubmitted: finishCardPurchase,
4105
+ onLockFailed: (err) => {
4106
+ setLockFailedMessage(err.message);
4107
+ onLockFailed?.(err);
4108
+ }
4109
+ }
4110
+ ) })
3993
4111
  ] });
3994
4112
  }
3995
4113
  function DepositModal({ open, onClose, ...handlers }) {
@@ -4780,6 +4898,6 @@ function WalletInlineModal({ className, ...handlers }) {
4780
4898
  );
4781
4899
  }
4782
4900
 
4783
- export { DepositInlineModal, DepositModal, LOCK_TYPES, MODIFY_LOCK_TYPES, PrivanaButton, PrivanaIcon, PrivanaInlineModal, PrivanaModal, TRANSFER_LOCKED_TYPES, TRANSFER_TYPES, WITHDRAW_FROM_LOCK_TYPES, WITHDRAW_TYPES, WalletInlineModal, WalletModal, WithdrawInlineModal, WithdrawModal, createDomain, createLockExpiry, getChainIcon, getTokenIcon, signLockMessage, signModifyLockMessage, signTransferLockedMessage, signTransferMessage, signWithdrawFromLockMessage, signWithdrawMessage, useBalance, useBatchBalances, useDeposit, useDepositAddress, useExpiredLocks, useHistory, useHostedRedirectAuth, useLockFunds, useLockedFunds, useModifyLock, usePendingWithdrawals, usePrivanaClient, useTokenInfo, useTokenList, useTotalLockedBalance, useTransfer, useUnlockFunds, useWithdraw };
4901
+ export { DepositInlineModal, DepositModal, PrivanaButton, PrivanaIcon, PrivanaInlineModal, PrivanaModal, WalletInlineModal, WalletModal, WithdrawInlineModal, WithdrawModal, getChainIcon, getTokenIcon, useBalance, useBatchBalances, useDeposit, useDepositAddress, useExpiredLocks, useHistory, useHostedRedirectAuth, useLockFunds, useLockedFunds, useModifyLock, usePendingDeposits, usePendingWithdrawals, usePrivanaClient, useTokenInfo, useTokenList, useTotalLockedBalance, useTransfer, useUnlockFunds, useWithdraw };
4784
4902
  //# sourceMappingURL=index.js.map
4785
4903
  //# sourceMappingURL=index.js.map