@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/LICENSE +21 -0
- package/README.md +186 -0
- package/dist/index.d.mts +442 -0
- package/dist/index.d.ts +442 -0
- package/dist/index.js +612 -0
- package/dist/index.mjs +575 -0
- package/package.json +86 -0
- package/src/hooks/index.ts +30 -0
- package/src/hooks/use-scan-payments.ts +288 -0
- package/src/hooks/use-stealth-address.ts +329 -0
- package/src/hooks/use-stealth-transfer.ts +252 -0
- package/src/index.ts +58 -0
- package/src/storage/index.ts +1 -0
- package/src/storage/secure-storage.ts +395 -0
- package/src/utils/clipboard.ts +67 -0
- package/src/utils/index.ts +1 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
export { Asset, ChainId, HexString, PrivacyLevel } from '@sip-protocol/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* useStealthAddress - Mobile-optimized stealth address hook
|
|
5
|
+
*
|
|
6
|
+
* React Native version with secure storage and native clipboard support.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* import { useStealthAddress } from '@sip-protocol/react-native'
|
|
11
|
+
*
|
|
12
|
+
* function ReceiveScreen() {
|
|
13
|
+
* const {
|
|
14
|
+
* metaAddress,
|
|
15
|
+
* stealthAddress,
|
|
16
|
+
* isGenerating,
|
|
17
|
+
* regenerate,
|
|
18
|
+
* copyToClipboard,
|
|
19
|
+
* saveToKeychain,
|
|
20
|
+
* } = useStealthAddress('solana')
|
|
21
|
+
*
|
|
22
|
+
* return (
|
|
23
|
+
* <View>
|
|
24
|
+
* <Text>Share: {metaAddress}</Text>
|
|
25
|
+
* <TouchableOpacity onPress={copyToClipboard}>
|
|
26
|
+
* <Text>Copy</Text>
|
|
27
|
+
* </TouchableOpacity>
|
|
28
|
+
* <TouchableOpacity onPress={saveToKeychain}>
|
|
29
|
+
* <Text>Save Securely</Text>
|
|
30
|
+
* </TouchableOpacity>
|
|
31
|
+
* </View>
|
|
32
|
+
* )
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Supported chain IDs (matches @sip-protocol/types ChainId)
|
|
38
|
+
*/
|
|
39
|
+
type SupportedChainId = 'ethereum' | 'solana' | 'near' | 'bitcoin' | 'polygon' | 'arbitrum' | 'optimism' | 'base' | 'bsc' | 'avalanche' | 'cosmos' | 'aptos' | 'sui' | 'polkadot' | 'tezos';
|
|
40
|
+
/**
|
|
41
|
+
* Options for useStealthAddress hook
|
|
42
|
+
*/
|
|
43
|
+
interface UseStealthAddressOptions {
|
|
44
|
+
/** Auto-save to secure storage on generation */
|
|
45
|
+
autoSave?: boolean;
|
|
46
|
+
/** Require biometrics to access stored keys */
|
|
47
|
+
requireBiometrics?: boolean;
|
|
48
|
+
/** Wallet identifier for storage (default: 'default') */
|
|
49
|
+
walletId?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Return type for useStealthAddress hook
|
|
53
|
+
*/
|
|
54
|
+
interface UseStealthAddressReturn {
|
|
55
|
+
/** Encoded meta-address for sharing */
|
|
56
|
+
metaAddress: string | null;
|
|
57
|
+
/** One-time stealth address */
|
|
58
|
+
stealthAddress: string | null;
|
|
59
|
+
/** Spending private key (for claiming) */
|
|
60
|
+
spendingPrivateKey: string | null;
|
|
61
|
+
/** Viewing private key (for scanning) */
|
|
62
|
+
viewingPrivateKey: string | null;
|
|
63
|
+
/** Whether generation is in progress */
|
|
64
|
+
isGenerating: boolean;
|
|
65
|
+
/** Error if any occurred */
|
|
66
|
+
error: Error | null;
|
|
67
|
+
/** Generate a new stealth address */
|
|
68
|
+
regenerate: () => void;
|
|
69
|
+
/** Copy stealth address to clipboard */
|
|
70
|
+
copyToClipboard: () => Promise<boolean>;
|
|
71
|
+
/** Save keys to secure storage */
|
|
72
|
+
saveToKeychain: () => Promise<boolean>;
|
|
73
|
+
/** Load keys from secure storage */
|
|
74
|
+
loadFromKeychain: () => Promise<boolean>;
|
|
75
|
+
/** Clear error state */
|
|
76
|
+
clearError: () => void;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Mobile-optimized stealth address hook
|
|
80
|
+
*
|
|
81
|
+
* @param chain - Target blockchain
|
|
82
|
+
* @param options - Hook options
|
|
83
|
+
*/
|
|
84
|
+
declare function useStealthAddress(chain: SupportedChainId, options?: UseStealthAddressOptions): UseStealthAddressReturn;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* useStealthTransfer - Mobile-optimized private transfer hook
|
|
88
|
+
*
|
|
89
|
+
* Handles shielded SPL token transfers on Solana from mobile devices.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```tsx
|
|
93
|
+
* import { useStealthTransfer } from '@sip-protocol/react-native'
|
|
94
|
+
*
|
|
95
|
+
* function SendScreen() {
|
|
96
|
+
* const { transfer, status, error, isLoading } = useStealthTransfer({
|
|
97
|
+
* connection,
|
|
98
|
+
* wallet: walletAdapter,
|
|
99
|
+
* })
|
|
100
|
+
*
|
|
101
|
+
* const handleSend = async () => {
|
|
102
|
+
* const result = await transfer({
|
|
103
|
+
* recipientMetaAddress: 'sip:solana:...',
|
|
104
|
+
* amount: 1000000n, // 1 USDC
|
|
105
|
+
* mint: USDC_MINT,
|
|
106
|
+
* })
|
|
107
|
+
* if (result.success) {
|
|
108
|
+
* Alert.alert('Success', 'Payment sent privately!')
|
|
109
|
+
* }
|
|
110
|
+
* }
|
|
111
|
+
*
|
|
112
|
+
* return (
|
|
113
|
+
* <TouchableOpacity onPress={handleSend} disabled={isLoading}>
|
|
114
|
+
* <Text>{isLoading ? 'Sending...' : 'Send Private Payment'}</Text>
|
|
115
|
+
* </TouchableOpacity>
|
|
116
|
+
* )
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
/**
|
|
121
|
+
* Wallet adapter interface for mobile wallets
|
|
122
|
+
*/
|
|
123
|
+
interface MobileWalletAdapter {
|
|
124
|
+
publicKey: {
|
|
125
|
+
toBase58(): string;
|
|
126
|
+
} | null;
|
|
127
|
+
signTransaction: <T>(transaction: T) => Promise<T>;
|
|
128
|
+
signAllTransactions?: <T>(transactions: T[]) => Promise<T[]>;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Transfer status enum
|
|
132
|
+
*/
|
|
133
|
+
type TransferStatus = 'idle' | 'preparing' | 'signing' | 'sending' | 'confirming' | 'success' | 'error';
|
|
134
|
+
/**
|
|
135
|
+
* Parameters for stealth transfer
|
|
136
|
+
*/
|
|
137
|
+
interface TransferParams {
|
|
138
|
+
/** Recipient's stealth meta-address */
|
|
139
|
+
recipientMetaAddress: string;
|
|
140
|
+
/** Amount in smallest units */
|
|
141
|
+
amount: bigint;
|
|
142
|
+
/** SPL token mint address */
|
|
143
|
+
mint: string;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Result of stealth transfer
|
|
147
|
+
*/
|
|
148
|
+
interface TransferResult {
|
|
149
|
+
success: boolean;
|
|
150
|
+
signature?: string;
|
|
151
|
+
stealthAddress?: string;
|
|
152
|
+
error?: Error;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Connection interface (subset of @solana/web3.js Connection)
|
|
156
|
+
*/
|
|
157
|
+
interface SolanaConnection$1 {
|
|
158
|
+
confirmTransaction(signature: string, commitment?: string): Promise<{
|
|
159
|
+
value: {
|
|
160
|
+
err: unknown;
|
|
161
|
+
};
|
|
162
|
+
}>;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Parameters for useStealthTransfer hook
|
|
166
|
+
*/
|
|
167
|
+
interface UseStealthTransferParams {
|
|
168
|
+
/** Solana connection */
|
|
169
|
+
connection: SolanaConnection$1;
|
|
170
|
+
/** Wallet adapter */
|
|
171
|
+
wallet: MobileWalletAdapter;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Return type for useStealthTransfer hook
|
|
175
|
+
*/
|
|
176
|
+
interface UseStealthTransferReturn {
|
|
177
|
+
/** Execute a private transfer */
|
|
178
|
+
transfer: (params: TransferParams) => Promise<TransferResult>;
|
|
179
|
+
/** Current transfer status */
|
|
180
|
+
status: TransferStatus;
|
|
181
|
+
/** Error if any occurred */
|
|
182
|
+
error: Error | null;
|
|
183
|
+
/** Whether a transfer is in progress */
|
|
184
|
+
isLoading: boolean;
|
|
185
|
+
/** Reset the hook state */
|
|
186
|
+
reset: () => void;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Mobile-optimized stealth transfer hook
|
|
190
|
+
*
|
|
191
|
+
* @param params - Hook parameters
|
|
192
|
+
*/
|
|
193
|
+
declare function useStealthTransfer(params: UseStealthTransferParams): UseStealthTransferReturn;
|
|
194
|
+
/**
|
|
195
|
+
* Get associated token address helper
|
|
196
|
+
*
|
|
197
|
+
* Dynamically imports from @solana/spl-token
|
|
198
|
+
*
|
|
199
|
+
* @param mint - Token mint address string
|
|
200
|
+
* @param owner - Owner address string
|
|
201
|
+
* @returns Associated token address
|
|
202
|
+
*/
|
|
203
|
+
declare function getAssociatedTokenAddress(mint: string, owner: string): Promise<string>;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* useScanPayments - Mobile-optimized payment scanning hook
|
|
207
|
+
*
|
|
208
|
+
* Scans for incoming stealth payments using viewing key.
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```tsx
|
|
212
|
+
* import { useScanPayments } from '@sip-protocol/react-native'
|
|
213
|
+
*
|
|
214
|
+
* function InboxScreen() {
|
|
215
|
+
* const { payments, isScanning, scan, claim } = useScanPayments({
|
|
216
|
+
* connection,
|
|
217
|
+
* provider: heliusProvider,
|
|
218
|
+
* })
|
|
219
|
+
*
|
|
220
|
+
* useEffect(() => {
|
|
221
|
+
* // Load keys from keychain and scan
|
|
222
|
+
* loadKeysAndScan()
|
|
223
|
+
* }, [])
|
|
224
|
+
*
|
|
225
|
+
* return (
|
|
226
|
+
* <FlatList
|
|
227
|
+
* data={payments}
|
|
228
|
+
* renderItem={({ item }) => (
|
|
229
|
+
* <PaymentCard
|
|
230
|
+
* payment={item}
|
|
231
|
+
* onClaim={() => claim(item.signature)}
|
|
232
|
+
* />
|
|
233
|
+
* )}
|
|
234
|
+
* />
|
|
235
|
+
* )
|
|
236
|
+
* }
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
/**
|
|
240
|
+
* Solana connection interface (subset of @solana/web3.js Connection)
|
|
241
|
+
*/
|
|
242
|
+
interface SolanaConnection {
|
|
243
|
+
getAccountInfo(publicKey: unknown): Promise<unknown>;
|
|
244
|
+
getSignaturesForAddress(address: unknown, options?: unknown): Promise<unknown[]>;
|
|
245
|
+
getTransaction(signature: string, options?: unknown): Promise<unknown>;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Scanned payment info
|
|
249
|
+
*/
|
|
250
|
+
interface ScannedPayment {
|
|
251
|
+
/** Transaction signature */
|
|
252
|
+
signature: string;
|
|
253
|
+
/** Stealth address that received the payment */
|
|
254
|
+
stealthAddress: string;
|
|
255
|
+
/** Ephemeral public key */
|
|
256
|
+
ephemeralPublicKey: string;
|
|
257
|
+
/** Token mint address */
|
|
258
|
+
mint: string;
|
|
259
|
+
/** Amount in smallest units */
|
|
260
|
+
amount: bigint;
|
|
261
|
+
/** Block timestamp */
|
|
262
|
+
timestamp: number;
|
|
263
|
+
/** Whether this payment has been claimed */
|
|
264
|
+
claimed: boolean;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Scan status
|
|
268
|
+
*/
|
|
269
|
+
type ScanStatus = 'idle' | 'scanning' | 'claiming' | 'error';
|
|
270
|
+
/**
|
|
271
|
+
* Hook parameters
|
|
272
|
+
*/
|
|
273
|
+
interface UseScanPaymentsParams {
|
|
274
|
+
/** Solana connection */
|
|
275
|
+
connection: SolanaConnection;
|
|
276
|
+
/** RPC provider (Helius recommended) */
|
|
277
|
+
provider?: unknown;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Hook return type
|
|
281
|
+
*/
|
|
282
|
+
interface UseScanPaymentsReturn {
|
|
283
|
+
/** Scanned payments */
|
|
284
|
+
payments: ScannedPayment[];
|
|
285
|
+
/** Current status */
|
|
286
|
+
status: ScanStatus;
|
|
287
|
+
/** Error if any */
|
|
288
|
+
error: Error | null;
|
|
289
|
+
/** Whether scanning is in progress */
|
|
290
|
+
isScanning: boolean;
|
|
291
|
+
/** Scan for payments */
|
|
292
|
+
scan: (viewingPrivateKey: string, spendingPublicKey: string) => Promise<void>;
|
|
293
|
+
/** Claim a specific payment */
|
|
294
|
+
claim: (signature: string, spendingPrivateKey: string, destinationAddress: string) => Promise<string | null>;
|
|
295
|
+
/** Claim all unclaimed payments */
|
|
296
|
+
claimAll: (spendingPrivateKey: string, destinationAddress: string) => Promise<string[]>;
|
|
297
|
+
/** Clear payments */
|
|
298
|
+
clear: () => void;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Mobile payment scanning hook
|
|
302
|
+
*/
|
|
303
|
+
declare function useScanPayments(params: UseScanPaymentsParams): UseScanPaymentsReturn;
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Secure Key Storage for React Native
|
|
307
|
+
*
|
|
308
|
+
* Provides secure storage for private keys using native platform capabilities:
|
|
309
|
+
* - iOS: Keychain with biometric protection
|
|
310
|
+
* - Android: Keystore with biometric protection
|
|
311
|
+
*
|
|
312
|
+
* Falls back to in-memory storage if react-native-keychain is not available.
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* ```typescript
|
|
316
|
+
* import { SecureStorage } from '@sip-protocol/react-native'
|
|
317
|
+
*
|
|
318
|
+
* // Store viewing key
|
|
319
|
+
* await SecureStorage.setViewingKey('my-wallet', viewingPrivateKey)
|
|
320
|
+
*
|
|
321
|
+
* // Retrieve with biometric prompt
|
|
322
|
+
* const key = await SecureStorage.getViewingKey('my-wallet')
|
|
323
|
+
*
|
|
324
|
+
* // Clear on logout
|
|
325
|
+
* await SecureStorage.clearAll()
|
|
326
|
+
* ```
|
|
327
|
+
*/
|
|
328
|
+
/**
|
|
329
|
+
* Storage options for secure key storage
|
|
330
|
+
*/
|
|
331
|
+
interface SecureStorageOptions {
|
|
332
|
+
/** Key identifier/service name */
|
|
333
|
+
service?: string;
|
|
334
|
+
/** Require biometric authentication to access */
|
|
335
|
+
requireBiometrics?: boolean;
|
|
336
|
+
/** iOS: Accessibility level */
|
|
337
|
+
accessible?: 'whenUnlocked' | 'afterFirstUnlock' | 'always';
|
|
338
|
+
/** Storage backend to use */
|
|
339
|
+
backend?: 'keychain' | 'memory';
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Key prefixes for different key types
|
|
343
|
+
*/
|
|
344
|
+
declare const KEY_PREFIXES: {
|
|
345
|
+
readonly spending: "sip:spending:";
|
|
346
|
+
readonly viewing: "sip:viewing:";
|
|
347
|
+
readonly ephemeral: "sip:ephemeral:";
|
|
348
|
+
readonly meta: "sip:meta:";
|
|
349
|
+
};
|
|
350
|
+
type KeyType = keyof typeof KEY_PREFIXES;
|
|
351
|
+
/**
|
|
352
|
+
* Store a key securely
|
|
353
|
+
*
|
|
354
|
+
* @param type - Type of key (spending, viewing, ephemeral, meta)
|
|
355
|
+
* @param identifier - Unique identifier (e.g., wallet address)
|
|
356
|
+
* @param value - Key value (hex string)
|
|
357
|
+
* @param options - Storage options
|
|
358
|
+
*/
|
|
359
|
+
declare function setKey(type: KeyType, identifier: string, value: string, options?: SecureStorageOptions): Promise<boolean>;
|
|
360
|
+
/**
|
|
361
|
+
* Retrieve a key from secure storage
|
|
362
|
+
*
|
|
363
|
+
* @param type - Type of key (spending, viewing, ephemeral, meta)
|
|
364
|
+
* @param identifier - Unique identifier (e.g., wallet address)
|
|
365
|
+
* @param options - Storage options
|
|
366
|
+
* @returns Key value or null if not found
|
|
367
|
+
*/
|
|
368
|
+
declare function getKey(type: KeyType, identifier: string, options?: SecureStorageOptions): Promise<string | null>;
|
|
369
|
+
/**
|
|
370
|
+
* Delete a key from secure storage
|
|
371
|
+
*
|
|
372
|
+
* @param type - Type of key (spending, viewing, ephemeral, meta)
|
|
373
|
+
* @param identifier - Unique identifier (e.g., wallet address)
|
|
374
|
+
* @param options - Storage options
|
|
375
|
+
*/
|
|
376
|
+
declare function deleteKey(type: KeyType, identifier: string, options?: SecureStorageOptions): Promise<boolean>;
|
|
377
|
+
/**
|
|
378
|
+
* Clear all stored keys
|
|
379
|
+
*
|
|
380
|
+
* @param options - Storage options
|
|
381
|
+
*/
|
|
382
|
+
declare function clearAll(options?: SecureStorageOptions): Promise<boolean>;
|
|
383
|
+
/**
|
|
384
|
+
* Check if biometrics are available on this device
|
|
385
|
+
*
|
|
386
|
+
* @returns Biometrics support info
|
|
387
|
+
*/
|
|
388
|
+
declare function getSupportedBiometrics(): Promise<{
|
|
389
|
+
available: boolean;
|
|
390
|
+
biometryType: 'FaceID' | 'TouchID' | 'Fingerprint' | 'None';
|
|
391
|
+
}>;
|
|
392
|
+
/**
|
|
393
|
+
* Check if secure storage is available
|
|
394
|
+
*/
|
|
395
|
+
declare function isAvailable(): boolean;
|
|
396
|
+
/**
|
|
397
|
+
* SecureStorage API
|
|
398
|
+
*
|
|
399
|
+
* Unified API for secure key storage on mobile devices.
|
|
400
|
+
*/
|
|
401
|
+
declare const SecureStorage: {
|
|
402
|
+
readonly setKey: typeof setKey;
|
|
403
|
+
readonly getKey: typeof getKey;
|
|
404
|
+
readonly deleteKey: typeof deleteKey;
|
|
405
|
+
readonly clearAll: typeof clearAll;
|
|
406
|
+
readonly setViewingKey: (identifier: string, key: string, options?: SecureStorageOptions) => Promise<boolean>;
|
|
407
|
+
readonly getViewingKey: (identifier: string, options?: SecureStorageOptions) => Promise<string | null>;
|
|
408
|
+
readonly deleteViewingKey: (identifier: string, options?: SecureStorageOptions) => Promise<boolean>;
|
|
409
|
+
readonly setSpendingKey: (identifier: string, key: string, options?: SecureStorageOptions) => Promise<boolean>;
|
|
410
|
+
readonly getSpendingKey: (identifier: string, options?: SecureStorageOptions) => Promise<string | null>;
|
|
411
|
+
readonly deleteSpendingKey: (identifier: string, options?: SecureStorageOptions) => Promise<boolean>;
|
|
412
|
+
readonly setMetaAddress: (identifier: string, meta: string, options?: SecureStorageOptions) => Promise<boolean>;
|
|
413
|
+
readonly getMetaAddress: (identifier: string, options?: SecureStorageOptions) => Promise<string | null>;
|
|
414
|
+
readonly deleteMetaAddress: (identifier: string, options?: SecureStorageOptions) => Promise<boolean>;
|
|
415
|
+
readonly getSupportedBiometrics: typeof getSupportedBiometrics;
|
|
416
|
+
readonly isAvailable: typeof isAvailable;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Clipboard Utilities for React Native
|
|
421
|
+
*
|
|
422
|
+
* Provides cross-platform clipboard access with fallback support.
|
|
423
|
+
*/
|
|
424
|
+
/**
|
|
425
|
+
* Copy text to clipboard
|
|
426
|
+
*
|
|
427
|
+
* @param text - Text to copy
|
|
428
|
+
* @returns true if successful
|
|
429
|
+
*/
|
|
430
|
+
declare function copyToClipboard(text: string): Promise<boolean>;
|
|
431
|
+
/**
|
|
432
|
+
* Read text from clipboard
|
|
433
|
+
*
|
|
434
|
+
* @returns Clipboard contents or empty string
|
|
435
|
+
*/
|
|
436
|
+
declare function readFromClipboard(): Promise<string>;
|
|
437
|
+
/**
|
|
438
|
+
* Check if clipboard is available
|
|
439
|
+
*/
|
|
440
|
+
declare function isClipboardAvailable(): boolean;
|
|
441
|
+
|
|
442
|
+
export { type KeyType, type MobileWalletAdapter, type ScanStatus, type ScannedPayment, SecureStorage, type SecureStorageOptions, type TransferParams, type TransferResult, type TransferStatus, type UseScanPaymentsParams, type UseScanPaymentsReturn, type UseStealthAddressOptions, type UseStealthAddressReturn, type UseStealthTransferParams, type UseStealthTransferReturn, copyToClipboard, getAssociatedTokenAddress, isClipboardAvailable, readFromClipboard, useScanPayments, useStealthAddress, useStealthTransfer };
|