@sip-protocol/react-native 0.1.0

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 ADDED
@@ -0,0 +1,612 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ SecureStorage: () => SecureStorage,
34
+ copyToClipboard: () => copyToClipboard,
35
+ getAssociatedTokenAddress: () => getAssociatedTokenAddress,
36
+ isClipboardAvailable: () => isClipboardAvailable,
37
+ readFromClipboard: () => readFromClipboard,
38
+ useScanPayments: () => useScanPayments,
39
+ useStealthAddress: () => useStealthAddress,
40
+ useStealthTransfer: () => useStealthTransfer
41
+ });
42
+ module.exports = __toCommonJS(index_exports);
43
+
44
+ // src/hooks/use-stealth-address.ts
45
+ var import_react = require("react");
46
+
47
+ // src/utils/clipboard.ts
48
+ var Clipboard = null;
49
+ try {
50
+ Clipboard = require("@react-native-clipboard/clipboard").default;
51
+ } catch {
52
+ }
53
+ async function copyToClipboard(text) {
54
+ if (!Clipboard) {
55
+ console.warn(
56
+ "@react-native-clipboard/clipboard is not available. Install it for clipboard functionality."
57
+ );
58
+ return false;
59
+ }
60
+ try {
61
+ Clipboard.setString(text);
62
+ return true;
63
+ } catch {
64
+ return false;
65
+ }
66
+ }
67
+ async function readFromClipboard() {
68
+ if (!Clipboard) {
69
+ console.warn(
70
+ "@react-native-clipboard/clipboard is not available. Install it for clipboard functionality."
71
+ );
72
+ return "";
73
+ }
74
+ try {
75
+ return await Clipboard.getString();
76
+ } catch {
77
+ return "";
78
+ }
79
+ }
80
+ function isClipboardAvailable() {
81
+ return !!Clipboard;
82
+ }
83
+
84
+ // src/storage/secure-storage.ts
85
+ var DEFAULT_SERVICE = "com.sip-protocol.keys";
86
+ var KEY_PREFIXES = {
87
+ spending: "sip:spending:",
88
+ viewing: "sip:viewing:",
89
+ ephemeral: "sip:ephemeral:",
90
+ meta: "sip:meta:"
91
+ };
92
+ var memoryStorage = /* @__PURE__ */ new Map();
93
+ var Keychain = null;
94
+ try {
95
+ Keychain = require("react-native-keychain");
96
+ } catch {
97
+ }
98
+ function getBackend(options) {
99
+ if (options?.backend) {
100
+ return options.backend;
101
+ }
102
+ return Keychain ? "keychain" : "memory";
103
+ }
104
+ function buildKeyName(type, identifier) {
105
+ return `${KEY_PREFIXES[type]}${identifier}`;
106
+ }
107
+ async function setKey(type, identifier, value, options) {
108
+ const keyName = buildKeyName(type, identifier);
109
+ const backend = getBackend(options);
110
+ if (backend === "memory") {
111
+ memoryStorage.set(keyName, value);
112
+ return true;
113
+ }
114
+ if (!Keychain) {
115
+ throw new Error(
116
+ 'react-native-keychain is required for secure storage. Install it or use backend: "memory" for testing.'
117
+ );
118
+ }
119
+ const service = options?.service ?? DEFAULT_SERVICE;
120
+ const keychainOptions = {
121
+ service,
122
+ accessible: mapAccessible(options?.accessible)
123
+ };
124
+ if (options?.requireBiometrics) {
125
+ keychainOptions.accessControl = Keychain.ACCESS_CONTROL.BIOMETRY_CURRENT_SET;
126
+ keychainOptions.authenticationType = Keychain.AUTHENTICATION_TYPE.BIOMETRICS;
127
+ }
128
+ const result = await Keychain.setGenericPassword(
129
+ keyName,
130
+ value,
131
+ keychainOptions
132
+ );
133
+ return !!result;
134
+ }
135
+ async function getKey(type, identifier, options) {
136
+ const keyName = buildKeyName(type, identifier);
137
+ const backend = getBackend(options);
138
+ if (backend === "memory") {
139
+ return memoryStorage.get(keyName) ?? null;
140
+ }
141
+ if (!Keychain) {
142
+ throw new Error(
143
+ 'react-native-keychain is required for secure storage. Install it or use backend: "memory" for testing.'
144
+ );
145
+ }
146
+ const service = options?.service ?? DEFAULT_SERVICE;
147
+ const keychainOptions = {
148
+ service
149
+ };
150
+ if (options?.requireBiometrics) {
151
+ keychainOptions.authenticationPrompt = {
152
+ title: "Authenticate to access key",
153
+ subtitle: "SIP Protocol requires authentication",
154
+ description: "Use biometrics to unlock your private keys",
155
+ cancel: "Cancel"
156
+ };
157
+ }
158
+ const result = await Keychain.getGenericPassword(keychainOptions);
159
+ if (!result) {
160
+ return null;
161
+ }
162
+ if (result.username !== keyName) {
163
+ return null;
164
+ }
165
+ return result.password;
166
+ }
167
+ async function deleteKey(type, identifier, options) {
168
+ const keyName = buildKeyName(type, identifier);
169
+ const backend = getBackend(options);
170
+ if (backend === "memory") {
171
+ return memoryStorage.delete(keyName);
172
+ }
173
+ if (!Keychain) {
174
+ throw new Error("react-native-keychain is required for secure storage.");
175
+ }
176
+ const service = options?.service ?? DEFAULT_SERVICE;
177
+ return await Keychain.resetGenericPassword({ service });
178
+ }
179
+ async function clearAll(options) {
180
+ const backend = getBackend(options);
181
+ if (backend === "memory") {
182
+ memoryStorage.clear();
183
+ return true;
184
+ }
185
+ if (!Keychain) {
186
+ throw new Error("react-native-keychain is required for secure storage.");
187
+ }
188
+ const service = options?.service ?? DEFAULT_SERVICE;
189
+ return await Keychain.resetGenericPassword({ service });
190
+ }
191
+ function mapAccessible(level) {
192
+ if (!Keychain) return void 0;
193
+ switch (level) {
194
+ case "whenUnlocked":
195
+ return Keychain.ACCESSIBLE.WHEN_UNLOCKED;
196
+ case "afterFirstUnlock":
197
+ return Keychain.ACCESSIBLE.AFTER_FIRST_UNLOCK;
198
+ case "always":
199
+ return Keychain.ACCESSIBLE.ALWAYS;
200
+ default:
201
+ return Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY;
202
+ }
203
+ }
204
+ async function getSupportedBiometrics() {
205
+ if (!Keychain) {
206
+ return { available: false, biometryType: "None" };
207
+ }
208
+ const biometryType = await Keychain.getSupportedBiometryType();
209
+ if (!biometryType) {
210
+ return { available: false, biometryType: "None" };
211
+ }
212
+ return {
213
+ available: true,
214
+ biometryType
215
+ };
216
+ }
217
+ function isAvailable() {
218
+ return !!Keychain;
219
+ }
220
+ var SecureStorage = {
221
+ // Key operations
222
+ setKey,
223
+ getKey,
224
+ deleteKey,
225
+ clearAll,
226
+ // Convenience methods for viewing keys
227
+ setViewingKey: (identifier, key, options) => setKey("viewing", identifier, key, options),
228
+ getViewingKey: (identifier, options) => getKey("viewing", identifier, options),
229
+ deleteViewingKey: (identifier, options) => deleteKey("viewing", identifier, options),
230
+ // Convenience methods for spending keys
231
+ setSpendingKey: (identifier, key, options) => setKey("spending", identifier, key, options),
232
+ getSpendingKey: (identifier, options) => getKey("spending", identifier, options),
233
+ deleteSpendingKey: (identifier, options) => deleteKey("spending", identifier, options),
234
+ // Convenience methods for meta addresses
235
+ setMetaAddress: (identifier, meta, options) => setKey("meta", identifier, meta, options),
236
+ getMetaAddress: (identifier, options) => getKey("meta", identifier, options),
237
+ deleteMetaAddress: (identifier, options) => deleteKey("meta", identifier, options),
238
+ // Biometrics support
239
+ getSupportedBiometrics,
240
+ isAvailable
241
+ };
242
+
243
+ // src/hooks/use-stealth-address.ts
244
+ function useStealthAddress(chain, options = {}) {
245
+ const { autoSave = false, requireBiometrics = false, walletId = "default" } = options;
246
+ const [metaAddress, setMetaAddress] = (0, import_react.useState)(null);
247
+ const [stealthAddress, setStealthAddress] = (0, import_react.useState)(null);
248
+ const [spendingPrivateKey, setSpendingPrivateKey] = (0, import_react.useState)(null);
249
+ const [viewingPrivateKey, setViewingPrivateKey] = (0, import_react.useState)(null);
250
+ const [isGenerating, setIsGenerating] = (0, import_react.useState)(false);
251
+ const [error, setError] = (0, import_react.useState)(null);
252
+ (0, import_react.useEffect)(() => {
253
+ let cancelled = false;
254
+ const generate = async () => {
255
+ setIsGenerating(true);
256
+ try {
257
+ const sdk = await import("@sip-protocol/sdk");
258
+ const generateStealthMetaAddress = sdk.generateStealthMetaAddress;
259
+ const metaAddressData = generateStealthMetaAddress(chain);
260
+ if (cancelled) return;
261
+ const encodeStealthMetaAddress = sdk.encodeStealthMetaAddress;
262
+ const encoded = encodeStealthMetaAddress(metaAddressData.metaAddress);
263
+ setMetaAddress(encoded);
264
+ setSpendingPrivateKey(metaAddressData.spendingPrivateKey);
265
+ setViewingPrivateKey(metaAddressData.viewingPrivateKey);
266
+ const generateStealthAddress = sdk.generateStealthAddress;
267
+ const stealthData = generateStealthAddress(metaAddressData.metaAddress);
268
+ if (cancelled) return;
269
+ setStealthAddress(stealthData.stealthAddress.address);
270
+ setError(null);
271
+ if (autoSave && !cancelled) {
272
+ await SecureStorage.setSpendingKey(walletId, metaAddressData.spendingPrivateKey, {
273
+ requireBiometrics
274
+ });
275
+ await SecureStorage.setViewingKey(walletId, metaAddressData.viewingPrivateKey, {
276
+ requireBiometrics
277
+ });
278
+ await SecureStorage.setMetaAddress(walletId, encoded, { requireBiometrics });
279
+ }
280
+ } catch (err) {
281
+ if (cancelled) return;
282
+ const error2 = err instanceof Error ? err : new Error("Failed to generate stealth addresses");
283
+ setError(error2);
284
+ setMetaAddress(null);
285
+ setStealthAddress(null);
286
+ setSpendingPrivateKey(null);
287
+ setViewingPrivateKey(null);
288
+ } finally {
289
+ if (!cancelled) {
290
+ setIsGenerating(false);
291
+ }
292
+ }
293
+ };
294
+ generate();
295
+ return () => {
296
+ cancelled = true;
297
+ };
298
+ }, [chain, autoSave, requireBiometrics, walletId]);
299
+ const regenerate = (0, import_react.useCallback)(() => {
300
+ if (!metaAddress) return;
301
+ setIsGenerating(true);
302
+ setTimeout(async () => {
303
+ try {
304
+ const parts = metaAddress.split(":");
305
+ if (parts.length < 4) {
306
+ throw new Error("Invalid meta-address format");
307
+ }
308
+ const [, chainId, spendingKey, viewingKey] = parts;
309
+ const metaAddressObj = {
310
+ chain: chainId,
311
+ spendingKey: spendingKey.startsWith("0x") ? spendingKey : `0x${spendingKey}`,
312
+ viewingKey: viewingKey.startsWith("0x") ? viewingKey : `0x${viewingKey}`
313
+ };
314
+ const sdk = await import("@sip-protocol/sdk");
315
+ const generateStealthAddress = sdk.generateStealthAddress;
316
+ const stealthData = generateStealthAddress(metaAddressObj);
317
+ setStealthAddress(stealthData.stealthAddress.address);
318
+ setError(null);
319
+ } catch (err) {
320
+ const error2 = err instanceof Error ? err : new Error("Failed to regenerate stealth address");
321
+ setError(error2);
322
+ } finally {
323
+ setIsGenerating(false);
324
+ }
325
+ }, 0);
326
+ }, [metaAddress]);
327
+ const copyToClipboard2 = (0, import_react.useCallback)(async () => {
328
+ if (!stealthAddress) return false;
329
+ const success = await copyToClipboard(stealthAddress);
330
+ if (!success) {
331
+ setError(new Error("Failed to copy to clipboard"));
332
+ } else {
333
+ setError(null);
334
+ }
335
+ return success;
336
+ }, [stealthAddress]);
337
+ const saveToKeychain = (0, import_react.useCallback)(async () => {
338
+ if (!spendingPrivateKey || !viewingPrivateKey || !metaAddress) {
339
+ setError(new Error("No keys to save"));
340
+ return false;
341
+ }
342
+ try {
343
+ await SecureStorage.setSpendingKey(walletId, spendingPrivateKey, { requireBiometrics });
344
+ await SecureStorage.setViewingKey(walletId, viewingPrivateKey, { requireBiometrics });
345
+ await SecureStorage.setMetaAddress(walletId, metaAddress, { requireBiometrics });
346
+ setError(null);
347
+ return true;
348
+ } catch (err) {
349
+ const error2 = err instanceof Error ? err : new Error("Failed to save to keychain");
350
+ setError(error2);
351
+ return false;
352
+ }
353
+ }, [spendingPrivateKey, viewingPrivateKey, metaAddress, walletId, requireBiometrics]);
354
+ const loadFromKeychain = (0, import_react.useCallback)(async () => {
355
+ try {
356
+ const storedMeta = await SecureStorage.getMetaAddress(walletId, { requireBiometrics });
357
+ const storedSpending = await SecureStorage.getSpendingKey(walletId, { requireBiometrics });
358
+ const storedViewing = await SecureStorage.getViewingKey(walletId, { requireBiometrics });
359
+ if (!storedMeta || !storedSpending || !storedViewing) {
360
+ setError(new Error("No keys found in keychain"));
361
+ return false;
362
+ }
363
+ setMetaAddress(storedMeta);
364
+ setSpendingPrivateKey(storedSpending);
365
+ setViewingPrivateKey(storedViewing);
366
+ setError(null);
367
+ return true;
368
+ } catch (err) {
369
+ const error2 = err instanceof Error ? err : new Error("Failed to load from keychain");
370
+ setError(error2);
371
+ return false;
372
+ }
373
+ }, [walletId, requireBiometrics]);
374
+ const clearError = (0, import_react.useCallback)(() => {
375
+ setError(null);
376
+ }, []);
377
+ return {
378
+ metaAddress,
379
+ stealthAddress,
380
+ spendingPrivateKey,
381
+ viewingPrivateKey,
382
+ isGenerating,
383
+ error,
384
+ regenerate,
385
+ copyToClipboard: copyToClipboard2,
386
+ saveToKeychain,
387
+ loadFromKeychain,
388
+ clearError
389
+ };
390
+ }
391
+
392
+ // src/hooks/use-stealth-transfer.ts
393
+ var import_react2 = require("react");
394
+ function useStealthTransfer(params) {
395
+ const { connection, wallet } = params;
396
+ const [status, setStatus] = (0, import_react2.useState)("idle");
397
+ const [error, setError] = (0, import_react2.useState)(null);
398
+ const transfer = (0, import_react2.useCallback)(
399
+ async (transferParams) => {
400
+ const { recipientMetaAddress, amount, mint } = transferParams;
401
+ if (!wallet.publicKey) {
402
+ const err = new Error("Wallet not connected");
403
+ setError(err);
404
+ setStatus("error");
405
+ return { success: false, error: err };
406
+ }
407
+ try {
408
+ setStatus("preparing");
409
+ setError(null);
410
+ const sdk = await import("@sip-protocol/sdk");
411
+ if (!sdk.sendPrivateSPLTransfer) {
412
+ throw new Error(
413
+ "sendPrivateSPLTransfer not available. Install @sip-protocol/sdk with Solana support."
414
+ );
415
+ }
416
+ const sendPrivateSPLTransfer = sdk.sendPrivateSPLTransfer;
417
+ const { PublicKey } = await import("@solana/web3.js");
418
+ const { getAssociatedTokenAddress: getAssociatedTokenAddress2 } = await import("@solana/spl-token");
419
+ const mintPubkey = new PublicKey(mint);
420
+ const senderTokenAccount = await getAssociatedTokenAddress2(
421
+ mintPubkey,
422
+ new PublicKey(wallet.publicKey.toBase58())
423
+ );
424
+ setStatus("signing");
425
+ const result = await sendPrivateSPLTransfer({
426
+ connection,
427
+ sender: new PublicKey(wallet.publicKey.toBase58()),
428
+ senderTokenAccount,
429
+ recipientMetaAddress,
430
+ mint: mintPubkey,
431
+ amount,
432
+ signTransaction: wallet.signTransaction
433
+ });
434
+ setStatus("confirming");
435
+ const confirmation = await connection.confirmTransaction(
436
+ result.signature,
437
+ "confirmed"
438
+ );
439
+ if (confirmation.value.err) {
440
+ throw new Error(`Transaction failed: ${confirmation.value.err}`);
441
+ }
442
+ setStatus("success");
443
+ setError(null);
444
+ return {
445
+ success: true,
446
+ signature: result.signature,
447
+ stealthAddress: result.stealthAddress
448
+ };
449
+ } catch (err) {
450
+ const error2 = err instanceof Error ? err : new Error("Transfer failed");
451
+ setError(error2);
452
+ setStatus("error");
453
+ return { success: false, error: error2 };
454
+ }
455
+ },
456
+ [connection, wallet]
457
+ );
458
+ const reset = (0, import_react2.useCallback)(() => {
459
+ setStatus("idle");
460
+ setError(null);
461
+ }, []);
462
+ return {
463
+ transfer,
464
+ status,
465
+ error,
466
+ isLoading: status !== "idle" && status !== "success" && status !== "error",
467
+ reset
468
+ };
469
+ }
470
+ async function getAssociatedTokenAddress(mint, owner) {
471
+ const { PublicKey } = await import("@solana/web3.js");
472
+ const { getAssociatedTokenAddress: getATA } = await import("@solana/spl-token");
473
+ const ata = await getATA(new PublicKey(mint), new PublicKey(owner));
474
+ return ata.toBase58();
475
+ }
476
+
477
+ // src/hooks/use-scan-payments.ts
478
+ var import_react3 = require("react");
479
+ function useScanPayments(params) {
480
+ const { connection } = params;
481
+ const [payments, setPayments] = (0, import_react3.useState)([]);
482
+ const [status, setStatus] = (0, import_react3.useState)("idle");
483
+ const [error, setError] = (0, import_react3.useState)(null);
484
+ const scanningRef = (0, import_react3.useRef)(false);
485
+ const scan = (0, import_react3.useCallback)(
486
+ async (viewingPrivateKey, spendingPublicKey) => {
487
+ if (scanningRef.current) return;
488
+ scanningRef.current = true;
489
+ try {
490
+ setStatus("scanning");
491
+ setError(null);
492
+ const sdk = await import("@sip-protocol/sdk");
493
+ if (!sdk.scanForPayments) {
494
+ throw new Error(
495
+ "scanForPayments not available. Install @sip-protocol/sdk with Solana support."
496
+ );
497
+ }
498
+ const scanForPayments = sdk.scanForPayments;
499
+ const result = await scanForPayments({
500
+ connection,
501
+ viewingPrivateKey,
502
+ spendingPublicKey
503
+ });
504
+ const scannedPayments = result.map((p) => ({
505
+ signature: p.signature,
506
+ stealthAddress: p.stealthAddress,
507
+ ephemeralPublicKey: p.ephemeralPublicKey,
508
+ mint: p.mint,
509
+ amount: p.amount,
510
+ timestamp: p.timestamp ?? Date.now(),
511
+ claimed: false
512
+ }));
513
+ setPayments((prev) => {
514
+ const existingSigs = new Set(prev.map((p) => p.signature));
515
+ const newPayments = scannedPayments.filter((p) => !existingSigs.has(p.signature));
516
+ return [...prev, ...newPayments];
517
+ });
518
+ setStatus("idle");
519
+ } catch (err) {
520
+ const error2 = err instanceof Error ? err : new Error("Scan failed");
521
+ setError(error2);
522
+ setStatus("error");
523
+ } finally {
524
+ scanningRef.current = false;
525
+ }
526
+ },
527
+ [connection]
528
+ );
529
+ const claim = (0, import_react3.useCallback)(
530
+ async (signature, spendingPrivateKey, destinationAddress) => {
531
+ try {
532
+ setStatus("claiming");
533
+ setError(null);
534
+ const payment = payments.find((p) => p.signature === signature);
535
+ if (!payment) {
536
+ throw new Error("Payment not found");
537
+ }
538
+ const sdk = await import("@sip-protocol/sdk");
539
+ const { PublicKey } = await import("@solana/web3.js");
540
+ if (!sdk.claimStealthPayment) {
541
+ throw new Error(
542
+ "claimStealthPayment not available. Install @sip-protocol/sdk with Solana support."
543
+ );
544
+ }
545
+ const claimStealthPayment = sdk.claimStealthPayment;
546
+ const result = await claimStealthPayment({
547
+ connection,
548
+ stealthAddress: payment.stealthAddress,
549
+ ephemeralPublicKey: payment.ephemeralPublicKey,
550
+ viewingPrivateKey: "",
551
+ // Not needed for claiming
552
+ spendingPrivateKey,
553
+ destinationAddress: new PublicKey(destinationAddress),
554
+ mint: new PublicKey(payment.mint)
555
+ });
556
+ setPayments(
557
+ (prev) => prev.map(
558
+ (p) => p.signature === signature ? { ...p, claimed: true } : p
559
+ )
560
+ );
561
+ setStatus("idle");
562
+ return result.signature;
563
+ } catch (err) {
564
+ const error2 = err instanceof Error ? err : new Error("Claim failed");
565
+ setError(error2);
566
+ setStatus("error");
567
+ return null;
568
+ }
569
+ },
570
+ [connection, payments]
571
+ );
572
+ const claimAll = (0, import_react3.useCallback)(
573
+ async (spendingPrivateKey, destinationAddress) => {
574
+ const unclaimedPayments = payments.filter((p) => !p.claimed);
575
+ const signatures = [];
576
+ for (const payment of unclaimedPayments) {
577
+ const sig = await claim(payment.signature, spendingPrivateKey, destinationAddress);
578
+ if (sig) {
579
+ signatures.push(sig);
580
+ }
581
+ }
582
+ return signatures;
583
+ },
584
+ [payments, claim]
585
+ );
586
+ const clear = (0, import_react3.useCallback)(() => {
587
+ setPayments([]);
588
+ setError(null);
589
+ setStatus("idle");
590
+ }, []);
591
+ return {
592
+ payments,
593
+ status,
594
+ error,
595
+ isScanning: status === "scanning",
596
+ scan,
597
+ claim,
598
+ claimAll,
599
+ clear
600
+ };
601
+ }
602
+ // Annotate the CommonJS export names for ESM import in node:
603
+ 0 && (module.exports = {
604
+ SecureStorage,
605
+ copyToClipboard,
606
+ getAssociatedTokenAddress,
607
+ isClipboardAvailable,
608
+ readFromClipboard,
609
+ useScanPayments,
610
+ useStealthAddress,
611
+ useStealthTransfer
612
+ });