@deserialize/multi-vm-wallet 1.4.12 → 1.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.
Files changed (191) hide show
  1. package/.claude/settings.local.json +7 -1
  2. package/BUILD_OPTIMIZATION_PLAN.md +640 -0
  3. package/BUILD_RESULTS.md +282 -0
  4. package/BUN_MIGRATION.md +415 -0
  5. package/CHANGELOG_SECURITY.md +573 -0
  6. package/IMPLEMENTATION_SUMMARY.md +494 -0
  7. package/SECURITY_AUDIT.md +1124 -0
  8. package/bun.lock +553 -0
  9. package/dist/IChainWallet.js +0 -5
  10. package/dist/bip32Old.js +0 -885
  11. package/dist/bip32Small.js +0 -79
  12. package/dist/bipTest.js +0 -362
  13. package/dist/constant.js +0 -17
  14. package/dist/english.js +0 -1
  15. package/dist/evm/aa-service/index.d.ts +0 -5
  16. package/dist/evm/aa-service/index.js +0 -14
  17. package/dist/evm/aa-service/lib/account-adapter.d.ts +0 -22
  18. package/dist/evm/aa-service/lib/account-adapter.js +0 -24
  19. package/dist/evm/aa-service/lib/kernel-account.d.ts +0 -30
  20. package/dist/evm/aa-service/lib/kernel-account.js +2 -67
  21. package/dist/evm/aa-service/lib/kernel-modules.d.ts +0 -177
  22. package/dist/evm/aa-service/lib/kernel-modules.js +4 -202
  23. package/dist/evm/aa-service/lib/session-keys.d.ts +0 -118
  24. package/dist/evm/aa-service/lib/session-keys.js +7 -151
  25. package/dist/evm/aa-service/lib/type.d.ts +0 -55
  26. package/dist/evm/aa-service/lib/type.js +0 -10
  27. package/dist/evm/aa-service/services/account-abstraction.d.ts +0 -426
  28. package/dist/evm/aa-service/services/account-abstraction.js +0 -461
  29. package/dist/evm/aa-service/services/bundler.d.ts +0 -6
  30. package/dist/evm/aa-service/services/bundler.js +0 -54
  31. package/dist/evm/evm.d.ts +10 -67
  32. package/dist/evm/evm.js +339 -102
  33. package/dist/evm/index.js +0 -3
  34. package/dist/evm/script.js +3 -17
  35. package/dist/evm/smartWallet.d.ts +0 -173
  36. package/dist/evm/smartWallet.js +0 -206
  37. package/dist/evm/smartWallet.types.d.ts +0 -6
  38. package/dist/evm/smartWallet.types.js +0 -8
  39. package/dist/evm/transaction.utils.d.ts +0 -242
  40. package/dist/evm/transaction.utils.js +4 -320
  41. package/dist/evm/transactionParsing.d.ts +0 -11
  42. package/dist/evm/transactionParsing.js +28 -147
  43. package/dist/evm/utils.d.ts +0 -46
  44. package/dist/evm/utils.js +1 -57
  45. package/dist/helpers/index.d.ts +0 -4
  46. package/dist/helpers/index.js +8 -44
  47. package/dist/helpers/routeScan.js +0 -1
  48. package/dist/index.js +0 -1
  49. package/dist/old.js +0 -884
  50. package/dist/price.js +0 -1
  51. package/dist/price.types.js +0 -2
  52. package/dist/rate-limiter.d.ts +28 -0
  53. package/dist/rate-limiter.js +95 -0
  54. package/dist/retry-logic.d.ts +14 -0
  55. package/dist/retry-logic.js +120 -0
  56. package/dist/savings/index.d.ts +1 -0
  57. package/dist/savings/index.js +16 -2
  58. package/dist/savings/saving-manager.d.ts +46 -0
  59. package/dist/savings/saving-manager.js +176 -0
  60. package/dist/savings/savings-operations.d.ts +39 -0
  61. package/dist/savings/savings-operations.js +141 -0
  62. package/dist/savings/smart-savings.d.ts +0 -63
  63. package/dist/savings/smart-savings.js +0 -78
  64. package/dist/savings/types.d.ts +0 -69
  65. package/dist/savings/types.js +0 -7
  66. package/dist/savings/validation.d.ts +9 -0
  67. package/dist/savings/validation.js +85 -0
  68. package/dist/svm/constant.js +0 -1
  69. package/dist/svm/index.js +0 -1
  70. package/dist/svm/svm.d.ts +7 -13
  71. package/dist/svm/svm.js +262 -46
  72. package/dist/svm/transactionParsing.d.ts +0 -7
  73. package/dist/svm/transactionParsing.js +3 -41
  74. package/dist/svm/transactionSender.js +0 -9
  75. package/dist/svm/utils.d.ts +0 -12
  76. package/dist/svm/utils.js +9 -60
  77. package/dist/test.d.ts +0 -4
  78. package/dist/test.js +15 -95
  79. package/dist/transaction-utils.d.ts +38 -0
  80. package/dist/transaction-utils.js +168 -0
  81. package/dist/types.d.ts +36 -0
  82. package/dist/types.js +0 -1
  83. package/dist/utils.js +0 -1
  84. package/dist/vm-validation.d.ts +11 -0
  85. package/dist/vm-validation.js +151 -0
  86. package/dist/vm.d.ts +14 -16
  87. package/dist/vm.js +64 -53
  88. package/dist/walletBip32.d.ts +2 -0
  89. package/dist/walletBip32.js +31 -66
  90. package/package.json +9 -4
  91. package/test-discovery.ts +235 -0
  92. package/test-pocket-discovery.ts +84 -0
  93. package/tsconfig.json +18 -11
  94. package/tsconfig.prod.json +10 -0
  95. package/utils/IChainWallet.ts +2 -0
  96. package/utils/evm/evm.ts +560 -39
  97. package/utils/rate-limiter.ts +179 -0
  98. package/utils/retry-logic.ts +271 -0
  99. package/utils/savings/EXAMPLES.md +883 -0
  100. package/utils/savings/SECURITY.md +731 -0
  101. package/utils/savings/index.ts +1 -1
  102. package/utils/savings/saving-manager.ts +656 -0
  103. package/utils/savings/savings-operations.ts +509 -0
  104. package/utils/savings/validation.ts +187 -0
  105. package/utils/svm/svm.ts +467 -20
  106. package/utils/test.ts +26 -3
  107. package/utils/transaction-utils.ts +394 -0
  108. package/utils/types.ts +100 -0
  109. package/utils/vm-validation.ts +280 -0
  110. package/utils/vm.ts +202 -24
  111. package/utils/walletBip32.ts +63 -3
  112. package/dist/IChainWallet.js.map +0 -1
  113. package/dist/bip32.d.ts +0 -9
  114. package/dist/bip32.js +0 -172
  115. package/dist/bip32.js.map +0 -1
  116. package/dist/bip32Old.js.map +0 -1
  117. package/dist/bip32Small.js.map +0 -1
  118. package/dist/bipTest.js.map +0 -1
  119. package/dist/constant.js.map +0 -1
  120. package/dist/english.js.map +0 -1
  121. package/dist/evm/SMART_WALLET_EXAMPLES.d.ts +0 -20
  122. package/dist/evm/SMART_WALLET_EXAMPLES.js +0 -451
  123. package/dist/evm/SMART_WALLET_EXAMPLES.js.map +0 -1
  124. package/dist/evm/aa-service/index.js.map +0 -1
  125. package/dist/evm/aa-service/lib/account-adapter.js.map +0 -1
  126. package/dist/evm/aa-service/lib/kernel-account.js.map +0 -1
  127. package/dist/evm/aa-service/lib/kernel-modules.js.map +0 -1
  128. package/dist/evm/aa-service/lib/session-keys.js.map +0 -1
  129. package/dist/evm/aa-service/lib/type.js.map +0 -1
  130. package/dist/evm/aa-service/services/account-abstraction.js.map +0 -1
  131. package/dist/evm/aa-service/services/bundler.js.map +0 -1
  132. package/dist/evm/evm.js.map +0 -1
  133. package/dist/evm/index.js.map +0 -1
  134. package/dist/evm/script.js.map +0 -1
  135. package/dist/evm/smartWallet.js.map +0 -1
  136. package/dist/evm/smartWallet.types.js.map +0 -1
  137. package/dist/evm/transaction.utils.js.map +0 -1
  138. package/dist/evm/transactionParsing.js.map +0 -1
  139. package/dist/evm/utils.js.map +0 -1
  140. package/dist/helpers/index.js.map +0 -1
  141. package/dist/helpers/routeScan.js.map +0 -1
  142. package/dist/index.js.map +0 -1
  143. package/dist/old.js.map +0 -1
  144. package/dist/price.js.map +0 -1
  145. package/dist/price.types.js.map +0 -1
  146. package/dist/privacy/artifact-manager.d.ts +0 -117
  147. package/dist/privacy/artifact-manager.js +0 -251
  148. package/dist/privacy/artifact-manager.js.map +0 -1
  149. package/dist/privacy/broadcaster-client.d.ts +0 -166
  150. package/dist/privacy/broadcaster-client.js +0 -261
  151. package/dist/privacy/broadcaster-client.js.map +0 -1
  152. package/dist/privacy/index.d.ts +0 -34
  153. package/dist/privacy/index.js +0 -56
  154. package/dist/privacy/index.js.map +0 -1
  155. package/dist/privacy/network-config.d.ts +0 -57
  156. package/dist/privacy/network-config.js +0 -118
  157. package/dist/privacy/network-config.js.map +0 -1
  158. package/dist/privacy/poi-helper.d.ts +0 -161
  159. package/dist/privacy/poi-helper.js +0 -249
  160. package/dist/privacy/poi-helper.js.map +0 -1
  161. package/dist/privacy/railgun-engine.d.ts +0 -135
  162. package/dist/privacy/railgun-engine.js +0 -205
  163. package/dist/privacy/railgun-engine.js.map +0 -1
  164. package/dist/privacy/railgun-privacy-wallet.d.ts +0 -288
  165. package/dist/privacy/railgun-privacy-wallet.js +0 -539
  166. package/dist/privacy/railgun-privacy-wallet.js.map +0 -1
  167. package/dist/privacy/types.d.ts +0 -229
  168. package/dist/privacy/types.js +0 -26
  169. package/dist/privacy/types.js.map +0 -1
  170. package/dist/savings/index.js.map +0 -1
  171. package/dist/savings/saving-actions.d.ts +0 -0
  172. package/dist/savings/saving-actions.js +0 -78
  173. package/dist/savings/saving-actions.js.map +0 -1
  174. package/dist/savings/savings-manager.d.ts +0 -126
  175. package/dist/savings/savings-manager.js +0 -234
  176. package/dist/savings/savings-manager.js.map +0 -1
  177. package/dist/savings/smart-savings.js.map +0 -1
  178. package/dist/savings/types.js.map +0 -1
  179. package/dist/svm/constant.js.map +0 -1
  180. package/dist/svm/index.js.map +0 -1
  181. package/dist/svm/svm.js.map +0 -1
  182. package/dist/svm/transactionParsing.js.map +0 -1
  183. package/dist/svm/transactionSender.js.map +0 -1
  184. package/dist/svm/utils.js.map +0 -1
  185. package/dist/test.js.map +0 -1
  186. package/dist/types.js.map +0 -1
  187. package/dist/utils.js.map +0 -1
  188. package/dist/vm.js.map +0 -1
  189. package/dist/walletBip32.js.map +0 -1
  190. package/utils/savings/saving-actions.ts +0 -92
  191. package/utils/savings/savings-manager.ts +0 -271
@@ -0,0 +1,731 @@
1
+ # Security Guide for Savings Feature
2
+
3
+ This document provides security guidance for developers implementing the savings feature in their wallet applications (mobile apps, browser extensions, desktop apps).
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Security Model](#security-model)
8
+ 2. [Two Implementation Patterns](#two-implementation-patterns)
9
+ 3. [Secure Storage](#secure-storage)
10
+ 4. [Authentication & Authorization](#authentication--authorization)
11
+ 5. [Memory Management](#memory-management)
12
+ 6. [Session Management](#session-management)
13
+ 7. [Best Practices](#best-practices)
14
+ 8. [Security Checklist](#security-checklist)
15
+
16
+ ## Security Model
17
+
18
+ ### SDK Responsibilities
19
+
20
+ This SDK provides:
21
+ - ✅ Cryptographic primitives for key derivation
22
+ - ✅ Input validation for all operations
23
+ - ✅ Memory cleanup utilities
24
+ - ✅ Two operation patterns (stateful and stateless)
25
+ - ✅ Security documentation and examples
26
+
27
+ ### Implementer Responsibilities
28
+
29
+ Your application must handle:
30
+ - 🔐 **Secure Storage**: Encrypting and storing mnemonics/keys
31
+ - 🔐 **Authentication**: Verifying user identity (biometrics, password, PIN)
32
+ - 🔐 **Authorization**: Controlling access to wallet operations
33
+ - 🔐 **App Lifecycle**: Clearing memory when app backgrounds/closes
34
+ - 🔐 **User Education**: Teaching users about security best practices
35
+
36
+ ## Two Implementation Patterns
37
+
38
+ Choose the pattern that best fits your application architecture:
39
+
40
+ ### Pattern 1: Stateless Operations (Recommended for Extensions)
41
+
42
+ **Best for**: Browser extensions, short-lived sessions
43
+
44
+ ```typescript
45
+ import { SavingsOperations } from '@wallet/utils/savings/savings-operations';
46
+
47
+ // Create operations handler (no sensitive data stored)
48
+ const operations = new SavingsOperations();
49
+
50
+ // Each operation requires mnemonic
51
+ async function transferFromPocket(pocketIndex: number, to: string, amount: bigint) {
52
+ // Get mnemonic from secure storage (implementer handles this)
53
+ const mnemonic = await secureStorage.getMnemonic();
54
+
55
+ // Perform operation - mnemonic not cached
56
+ const result = await operations.transferFromPocket(
57
+ mnemonic,
58
+ { accountIndex: pocketIndex, to, amount },
59
+ provider,
60
+ chain
61
+ );
62
+
63
+ // Mnemonic automatically cleared after operation
64
+ return result;
65
+ }
66
+ ```
67
+
68
+ **Advantages**:
69
+ - No persistent mnemonic in memory
70
+ - Automatic cleanup after each operation
71
+ - Better for browser extension background scripts
72
+
73
+ ### Pattern 2: Stateful Manager (Recommended for Mobile Apps)
74
+
75
+ **Best for**: Mobile apps, long-lived sessions
76
+
77
+ ```typescript
78
+ import { SavingsManager } from '@wallet/utils/savings/saving-manager';
79
+
80
+ let savingsManager: SavingsManager | null = null;
81
+
82
+ // Initialize when user authenticates
83
+ async function initializeWallet() {
84
+ const mnemonic = await secureStorage.getMnemonic();
85
+ savingsManager = new SavingsManager(mnemonic, chainConfig);
86
+ }
87
+
88
+ // Use manager for operations
89
+ async function transferToPocket(pocketIndex: number, amount: string) {
90
+ if (!savingsManager) throw new Error('Wallet not initialized');
91
+ return await savingsManager.transferToPocket(walletClient, pocketIndex, amount);
92
+ }
93
+
94
+ // Clean up when user locks wallet or app backgrounds
95
+ function lockWallet() {
96
+ if (savingsManager) {
97
+ savingsManager.dispose();
98
+ savingsManager = null;
99
+ }
100
+ }
101
+ ```
102
+
103
+ **Advantages**:
104
+ - Better performance (no repeated key derivation)
105
+ - Simpler code for multiple operations
106
+ - Suitable for authenticated sessions
107
+
108
+ ## Secure Storage
109
+
110
+ ### iOS (React Native / Swift)
111
+
112
+ Use iOS Keychain for maximum security:
113
+
114
+ ```typescript
115
+ // React Native example with react-native-keychain
116
+ import * as Keychain from 'react-native-keychain';
117
+
118
+ async function storeMnemonic(mnemonic: string) {
119
+ await Keychain.setGenericPassword(
120
+ 'wallet-mnemonic',
121
+ mnemonic,
122
+ {
123
+ accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
124
+ service: 'com.yourapp.wallet'
125
+ }
126
+ );
127
+ }
128
+
129
+ async function getMnemonic(): Promise<string> {
130
+ const credentials = await Keychain.getGenericPassword({
131
+ service: 'com.yourapp.wallet'
132
+ });
133
+
134
+ if (!credentials) {
135
+ throw new Error('Mnemonic not found');
136
+ }
137
+
138
+ return credentials.password;
139
+ }
140
+ ```
141
+
142
+ **Security Features**:
143
+ - Hardware-backed encryption (Secure Enclave on newer devices)
144
+ - Data protected by device passcode
145
+ - Automatic deletion on app uninstall
146
+
147
+ ### Android (React Native / Kotlin)
148
+
149
+ Use Android Keystore:
150
+
151
+ ```typescript
152
+ // React Native example with react-native-keychain
153
+ import * as Keychain from 'react-native-keychain';
154
+
155
+ async function storeMnemonic(mnemonic: string) {
156
+ await Keychain.setGenericPassword(
157
+ 'wallet-mnemonic',
158
+ mnemonic,
159
+ {
160
+ accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
161
+ service: 'com.yourapp.wallet',
162
+ securityLevel: Keychain.SECURITY_LEVEL.SECURE_HARDWARE
163
+ }
164
+ );
165
+ }
166
+ ```
167
+
168
+ **Security Features**:
169
+ - Hardware-backed encryption (TEE/StrongBox on supported devices)
170
+ - Biometric authentication integration
171
+ - Key material never leaves secure hardware
172
+
173
+ ### Browser Extensions
174
+
175
+ Use extension storage APIs with encryption:
176
+
177
+ ```typescript
178
+ import { encrypt, decrypt } from './crypto'; // Your encryption implementation
179
+
180
+ async function storeMnemonic(mnemonic: string, password: string) {
181
+ // Derive encryption key from user password
182
+ const encryptionKey = await deriveKey(password);
183
+
184
+ // Encrypt mnemonic
185
+ const encrypted = await encrypt(mnemonic, encryptionKey);
186
+
187
+ // Store in extension storage
188
+ await chrome.storage.local.set({
189
+ 'encrypted-mnemonic': encrypted
190
+ });
191
+ }
192
+
193
+ async function getMnemonic(password: string): Promise<string> {
194
+ const { 'encrypted-mnemonic': encrypted } = await chrome.storage.local.get(
195
+ 'encrypted-mnemonic'
196
+ );
197
+
198
+ if (!encrypted) {
199
+ throw new Error('Mnemonic not found');
200
+ }
201
+
202
+ // Derive encryption key from password
203
+ const encryptionKey = await deriveKey(password);
204
+
205
+ // Decrypt mnemonic
206
+ return await decrypt(encrypted, encryptionKey);
207
+ }
208
+ ```
209
+
210
+ **Security Considerations**:
211
+ - Use strong encryption (AES-256-GCM)
212
+ - Derive encryption key using PBKDF2 or Argon2
213
+ - Never store encryption key in storage
214
+ - Clear decrypted mnemonic from memory after use
215
+
216
+ ## Authentication & Authorization
217
+
218
+ ### Biometric Authentication (Mobile)
219
+
220
+ ```typescript
221
+ import TouchID from 'react-native-touch-id';
222
+
223
+ async function authenticateForTransaction(): Promise<boolean> {
224
+ try {
225
+ await TouchID.authenticate('Confirm transaction', {
226
+ title: 'Authentication Required',
227
+ fallbackLabel: 'Use Passcode',
228
+ passcodeFallback: true
229
+ });
230
+ return true;
231
+ } catch (error) {
232
+ console.error('Authentication failed:', error);
233
+ return false;
234
+ }
235
+ }
236
+
237
+ // Use before sensitive operations
238
+ async function sendFromPocket(pocketIndex: number, to: string, amount: bigint) {
239
+ // Require authentication
240
+ const authenticated = await authenticateForTransaction();
241
+ if (!authenticated) {
242
+ throw new Error('Authentication required');
243
+ }
244
+
245
+ // Proceed with operation
246
+ const mnemonic = await secureStorage.getMnemonic();
247
+ return await operations.transferFromPocket(mnemonic, { ... });
248
+ }
249
+ ```
250
+
251
+ ### Password Authentication (Browser Extensions)
252
+
253
+ ```typescript
254
+ // Session management for browser extensions
255
+ class SessionManager {
256
+ private decryptedMnemonic: string | null = null;
257
+ private sessionTimeout: number = 15 * 60 * 1000; // 15 minutes
258
+ private timeoutId?: NodeJS.Timeout;
259
+
260
+ async unlock(password: string): Promise<void> {
261
+ // Decrypt and cache mnemonic
262
+ this.decryptedMnemonic = await getMnemonic(password);
263
+
264
+ // Set auto-lock timer
265
+ this.resetTimeout();
266
+ }
267
+
268
+ lock(): void {
269
+ // Clear mnemonic from memory
270
+ if (this.decryptedMnemonic) {
271
+ this.decryptedMnemonic = '';
272
+ this.decryptedMnemonic = null;
273
+ }
274
+
275
+ if (this.timeoutId) {
276
+ clearTimeout(this.timeoutId);
277
+ }
278
+ }
279
+
280
+ private resetTimeout(): void {
281
+ if (this.timeoutId) {
282
+ clearTimeout(this.timeoutId);
283
+ }
284
+
285
+ this.timeoutId = setTimeout(() => {
286
+ this.lock();
287
+ }, this.sessionTimeout);
288
+ }
289
+
290
+ getMnemonic(): string {
291
+ if (!this.decryptedMnemonic) {
292
+ throw new Error('Wallet locked');
293
+ }
294
+
295
+ // Reset timeout on each access
296
+ this.resetTimeout();
297
+
298
+ return this.decryptedMnemonic;
299
+ }
300
+ }
301
+ ```
302
+
303
+ ## Memory Management
304
+
305
+ ### Using Stateful Manager
306
+
307
+ ```typescript
308
+ // Initialize manager when user authenticates
309
+ let manager: SavingsManager | null = null;
310
+
311
+ function initManager(mnemonic: string) {
312
+ manager = new SavingsManager(mnemonic, chainConfig);
313
+ }
314
+
315
+ // Clear memory when appropriate
316
+ function cleanup() {
317
+ if (manager) {
318
+ // Clear all cached data
319
+ manager.dispose();
320
+ manager = null;
321
+ }
322
+ }
323
+
324
+ // App lifecycle hooks
325
+ // React Native example
326
+ import { AppState } from 'react-native';
327
+
328
+ AppState.addEventListener('change', (nextAppState) => {
329
+ if (nextAppState === 'background' || nextAppState === 'inactive') {
330
+ // Clear sensitive data when app backgrounds
331
+ cleanup();
332
+ }
333
+ });
334
+ ```
335
+
336
+ ### Using Stateless Operations
337
+
338
+ ```typescript
339
+ // No persistent state - mnemonic cleared after each operation
340
+ const operations = new SavingsOperations();
341
+
342
+ async function transfer() {
343
+ // Get mnemonic only for this operation
344
+ const mnemonic = await secureStorage.getMnemonic();
345
+
346
+ try {
347
+ return await operations.transferFromPocket(
348
+ mnemonic,
349
+ { accountIndex: 0, to: '0x...', amount: 1000n },
350
+ provider,
351
+ chain
352
+ );
353
+ } finally {
354
+ // Mnemonic automatically cleared by operations class
355
+ }
356
+ }
357
+ ```
358
+
359
+ ### JavaScript Memory Limitations
360
+
361
+ **Important**: JavaScript strings are immutable. When you "clear" a string, you're only removing your reference to it. The actual data remains in memory until garbage collected.
362
+
363
+ **Best Practices**:
364
+ 1. Minimize the lifetime of sensitive data in memory
365
+ 2. Call disposal methods when done
366
+ 3. Remove all references to allow garbage collection
367
+ 4. Consider using `ArrayBuffer` for highly sensitive operations (advanced)
368
+
369
+ ```typescript
370
+ // Example with ArrayBuffer (advanced)
371
+ function secureStringToBuffer(str: string): ArrayBuffer {
372
+ const encoder = new TextEncoder();
373
+ return encoder.encode(str).buffer;
374
+ }
375
+
376
+ function clearBuffer(buffer: ArrayBuffer): void {
377
+ const view = new Uint8Array(buffer);
378
+ view.fill(0);
379
+ }
380
+ ```
381
+
382
+ ## Session Management
383
+
384
+ ### Mobile Apps
385
+
386
+ ```typescript
387
+ import { AppState } from 'react-native';
388
+
389
+ class WalletSession {
390
+ private manager: SavingsManager | null = null;
391
+ private lockTimer?: NodeJS.Timeout;
392
+ private autoLockDelay = 5 * 60 * 1000; // 5 minutes
393
+
394
+ constructor() {
395
+ // Listen for app state changes
396
+ AppState.addEventListener('change', this.handleAppStateChange);
397
+ }
398
+
399
+ async unlock(mnemonic: string) {
400
+ this.manager = new SavingsManager(mnemonic, chainConfig);
401
+ this.resetLockTimer();
402
+ }
403
+
404
+ lock() {
405
+ if (this.manager) {
406
+ this.manager.dispose();
407
+ this.manager = null;
408
+ }
409
+
410
+ if (this.lockTimer) {
411
+ clearTimeout(this.lockTimer);
412
+ }
413
+ }
414
+
415
+ private resetLockTimer() {
416
+ if (this.lockTimer) {
417
+ clearTimeout(this.lockTimer);
418
+ }
419
+
420
+ this.lockTimer = setTimeout(() => {
421
+ this.lock();
422
+ }, this.autoLockDelay);
423
+ }
424
+
425
+ private handleAppStateChange = (nextAppState: string) => {
426
+ if (nextAppState === 'background' || nextAppState === 'inactive') {
427
+ // Lock immediately when app backgrounds
428
+ this.lock();
429
+ }
430
+ };
431
+
432
+ getManager(): SavingsManager {
433
+ if (!this.manager) {
434
+ throw new Error('Wallet locked - authentication required');
435
+ }
436
+
437
+ // Reset auto-lock timer on each access
438
+ this.resetLockTimer();
439
+
440
+ return this.manager;
441
+ }
442
+ }
443
+ ```
444
+
445
+ ### Browser Extensions
446
+
447
+ ```typescript
448
+ // Background script session management
449
+ class ExtensionSession {
450
+ private operations = new SavingsOperations();
451
+ private encryptedMnemonic: string | null = null;
452
+ private password: string | null = null;
453
+
454
+ async unlock(password: string): Promise<void> {
455
+ // Verify password by attempting decryption
456
+ const mnemonic = await this.decrypt(password);
457
+
458
+ // Store for session
459
+ this.password = password;
460
+
461
+ // Keep background script alive (Chrome MV3)
462
+ this.keepAlive();
463
+ }
464
+
465
+ lock(): void {
466
+ this.password = null;
467
+ }
468
+
469
+ async performOperation<T>(
470
+ operation: (mnemonic: string) => Promise<T>
471
+ ): Promise<T> {
472
+ if (!this.password) {
473
+ throw new Error('Extension locked');
474
+ }
475
+
476
+ // Decrypt mnemonic for this operation only
477
+ const mnemonic = await this.decrypt(this.password);
478
+
479
+ try {
480
+ return await operation(mnemonic);
481
+ } finally {
482
+ // Mnemonic goes out of scope and will be garbage collected
483
+ }
484
+ }
485
+
486
+ private async decrypt(password: string): Promise<string> {
487
+ // Implement decryption logic
488
+ // ...
489
+ }
490
+
491
+ private keepAlive(): void {
492
+ // For Chrome MV3 extensions
493
+ setInterval(() => {
494
+ chrome.runtime.getPlatformInfo(() => {
495
+ // Keep background script alive
496
+ });
497
+ }, 20000);
498
+ }
499
+ }
500
+ ```
501
+
502
+ ## Best Practices
503
+
504
+ ### 1. Defense in Depth
505
+
506
+ Implement multiple layers of security:
507
+
508
+ ```typescript
509
+ class SecureWallet {
510
+ // Layer 1: Encrypted storage
511
+ private async getEncryptedMnemonic(): Promise<string> {
512
+ return await secureStorage.get('mnemonic');
513
+ }
514
+
515
+ // Layer 2: Password/biometric authentication
516
+ private async authenticate(): Promise<boolean> {
517
+ return await biometric.authenticate();
518
+ }
519
+
520
+ // Layer 3: Session timeout
521
+ private sessionManager = new SessionManager();
522
+
523
+ // Layer 4: Transaction confirmation
524
+ async sendTransaction(tx: Transaction): Promise<TransactionResult> {
525
+ // Require authentication
526
+ if (!await this.authenticate()) {
527
+ throw new Error('Authentication failed');
528
+ }
529
+
530
+ // Check session
531
+ const mnemonic = this.sessionManager.getMnemonic();
532
+
533
+ // Show confirmation dialog
534
+ const confirmed = await this.confirmTransaction(tx);
535
+ if (!confirmed) {
536
+ throw new Error('Transaction cancelled');
537
+ }
538
+
539
+ // Perform operation
540
+ return await this.operations.transferFromPocket(mnemonic, tx, ...);
541
+ }
542
+ }
543
+ ```
544
+
545
+ ### 2. User Education
546
+
547
+ Educate users about:
548
+ - Never sharing their mnemonic phrase
549
+ - Importance of secure device passcode
550
+ - Enabling biometric authentication
551
+ - Risks of rooted/jailbroken devices
552
+ - Importance of software updates
553
+
554
+ ### 3. Rate Limiting
555
+
556
+ Implement rate limiting for failed authentication attempts:
557
+
558
+ ```typescript
559
+ class RateLimiter {
560
+ private attempts = 0;
561
+ private lockUntil: number = 0;
562
+
563
+ async checkAndIncrement(): Promise<void> {
564
+ if (Date.now() < this.lockUntil) {
565
+ const remainingMs = this.lockUntil - Date.now();
566
+ throw new Error(`Too many attempts. Try again in ${Math.ceil(remainingMs / 1000)}s`);
567
+ }
568
+
569
+ this.attempts++;
570
+
571
+ if (this.attempts >= 5) {
572
+ // Lock for 5 minutes after 5 failed attempts
573
+ this.lockUntil = Date.now() + 5 * 60 * 1000;
574
+ this.attempts = 0;
575
+ throw new Error('Too many failed attempts. Account locked for 5 minutes.');
576
+ }
577
+ }
578
+
579
+ reset(): void {
580
+ this.attempts = 0;
581
+ this.lockUntil = 0;
582
+ }
583
+ }
584
+ ```
585
+
586
+ ### 4. Input Validation
587
+
588
+ Always validate user inputs before operations:
589
+
590
+ ```typescript
591
+ // The SDK provides validation utilities
592
+ import { SavingsValidation } from '@wallet/utils/savings/validation';
593
+
594
+ async function validateAndSend(to: string, amount: string) {
595
+ try {
596
+ // Validate inputs
597
+ SavingsValidation.validateAddress(to, 'Recipient address');
598
+ SavingsValidation.validateAmountString(amount, 'Amount');
599
+
600
+ // Parse amount
601
+ const amountBigInt = parseUnits(amount, 18);
602
+
603
+ // Perform operation
604
+ return await operations.transferFromPocket(mnemonic, {
605
+ accountIndex: 0,
606
+ to,
607
+ amount: amountBigInt
608
+ }, provider, chain);
609
+ } catch (error) {
610
+ // Show user-friendly error message
611
+ throw new Error(`Invalid input: ${error.message}`);
612
+ }
613
+ }
614
+ ```
615
+
616
+ ### 5. Logging and Monitoring
617
+
618
+ Never log sensitive data:
619
+
620
+ ```typescript
621
+ // ❌ NEVER DO THIS
622
+ console.log('Mnemonic:', mnemonic);
623
+ console.log('Private key:', privateKey);
624
+
625
+ // ✅ DO THIS
626
+ console.log('Transaction sent:', {
627
+ hash: result.hash,
628
+ from: publicAddress,
629
+ to: recipientAddress,
630
+ // No sensitive data
631
+ });
632
+ ```
633
+
634
+ ### 6. Testing
635
+
636
+ Test security features thoroughly:
637
+
638
+ ```typescript
639
+ describe('Wallet Security', () => {
640
+ it('should clear mnemonic on lock', async () => {
641
+ const manager = new SavingsManager(mnemonic, chainConfig);
642
+ manager.dispose();
643
+
644
+ // Verify internal state is cleared
645
+ expect((manager as any).mnemonic).toBe('');
646
+ });
647
+
648
+ it('should require authentication for transactions', async () => {
649
+ // Mock authentication failure
650
+ jest.spyOn(biometric, 'authenticate').mockRejectedValue(new Error('Failed'));
651
+
652
+ await expect(
653
+ wallet.sendTransaction({ ... })
654
+ ).rejects.toThrow('Authentication failed');
655
+ });
656
+
657
+ it('should lock after timeout', async () => {
658
+ const session = new SessionManager(5000); // 5s timeout
659
+ await session.unlock('password');
660
+
661
+ // Wait for timeout
662
+ await new Promise(resolve => setTimeout(resolve, 6000));
663
+
664
+ expect(() => session.getMnemonic()).toThrow('Wallet locked');
665
+ });
666
+ });
667
+ ```
668
+
669
+ ## Security Checklist
670
+
671
+ Before deploying your wallet application, verify:
672
+
673
+ ### Secure Storage
674
+ - [ ] Mnemonic encrypted at rest
675
+ - [ ] Using platform-specific secure storage (Keychain/Keystore)
676
+ - [ ] Encryption key derived from strong password
677
+ - [ ] No sensitive data in logs or analytics
678
+
679
+ ### Authentication
680
+ - [ ] Biometric authentication enabled (mobile)
681
+ - [ ] Strong password requirements (extensions)
682
+ - [ ] Rate limiting on failed attempts
683
+ - [ ] Session timeout implemented
684
+
685
+ ### Memory Management
686
+ - [ ] Dispose methods called on lock/logout
687
+ - [ ] Sensitive data cleared on app background
688
+ - [ ] No persistent references to sensitive data
689
+ - [ ] Session management implemented
690
+
691
+ ### Input Validation
692
+ - [ ] All user inputs validated
693
+ - [ ] Address checksums verified
694
+ - [ ] Amount limits enforced
695
+ - [ ] Transaction confirmations required
696
+
697
+ ### User Experience
698
+ - [ ] Clear security warnings
699
+ - [ ] Transaction confirmation dialogs
700
+ - [ ] User education materials
701
+ - [ ] Secure backup instructions
702
+
703
+ ### Testing
704
+ - [ ] Security features tested
705
+ - [ ] Attack scenarios simulated
706
+ - [ ] Third-party security audit completed
707
+ - [ ] Penetration testing performed
708
+
709
+ ### Compliance
710
+ - [ ] Privacy policy published
711
+ - [ ] Terms of service published
712
+ - [ ] GDPR compliance (if applicable)
713
+ - [ ] Local regulations followed
714
+
715
+ ## Additional Resources
716
+
717
+ - [OWASP Mobile Security Guide](https://owasp.org/www-project-mobile-security/)
718
+ - [Chrome Extension Security Best Practices](https://developer.chrome.com/docs/extensions/mv3/security/)
719
+ - [iOS Security Guide](https://support.apple.com/guide/security/welcome/web)
720
+ - [Android Security Best Practices](https://developer.android.com/privacy-and-security/security-tips)
721
+
722
+ ## Reporting Security Issues
723
+
724
+ If you discover a security vulnerability in this SDK, please report it to:
725
+ - Email: security@yourcompany.com
726
+ - Use responsible disclosure practices
727
+ - Allow time for patching before public disclosure
728
+
729
+ ## License
730
+
731
+ This security guide is provided as-is for educational purposes.