@spacesops/wdk-react-native-core 1.0.0-beta.40

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 (275) hide show
  1. package/README.md +551 -0
  2. package/dist/__mocks__/react.d.ts +40 -0
  3. package/dist/__mocks__/react.js +33 -0
  4. package/dist/__mocks__/react.js.map +1 -0
  5. package/dist/__mocks__/secureStorage.d.ts +26 -0
  6. package/dist/__mocks__/secureStorage.js +80 -0
  7. package/dist/__mocks__/secureStorage.js.map +1 -0
  8. package/dist/__tests__/hooks/useBalance.test.d.ts +6 -0
  9. package/dist/__tests__/hooks/useBalance.test.js +217 -0
  10. package/dist/__tests__/hooks/useBalance.test.js.map +1 -0
  11. package/dist/__tests__/hooks/useWallet.test.d.ts +6 -0
  12. package/dist/__tests__/hooks/useWallet.test.js +105 -0
  13. package/dist/__tests__/hooks/useWallet.test.js.map +1 -0
  14. package/dist/__tests__/hooks/useWalletManager.test.d.ts +6 -0
  15. package/dist/__tests__/hooks/useWalletManager.test.js +193 -0
  16. package/dist/__tests__/hooks/useWalletManager.test.js.map +1 -0
  17. package/dist/__tests__/hooks/useWdkApp.test.d.ts +6 -0
  18. package/dist/__tests__/hooks/useWdkApp.test.js +55 -0
  19. package/dist/__tests__/hooks/useWdkApp.test.js.map +1 -0
  20. package/dist/__tests__/hooks/useWorklet.test.d.ts +6 -0
  21. package/dist/__tests__/hooks/useWorklet.test.js +168 -0
  22. package/dist/__tests__/hooks/useWorklet.test.js.map +1 -0
  23. package/dist/__tests__/provider/WdkAppProvider.test.d.ts +6 -0
  24. package/dist/__tests__/provider/WdkAppProvider.test.js +57 -0
  25. package/dist/__tests__/provider/WdkAppProvider.test.js.map +1 -0
  26. package/dist/__tests__/services/accountService.test.d.ts +6 -0
  27. package/dist/__tests__/services/accountService.test.js +216 -0
  28. package/dist/__tests__/services/accountService.test.js.map +1 -0
  29. package/dist/__tests__/services/addressService.test.d.ts +6 -0
  30. package/dist/__tests__/services/addressService.test.js +246 -0
  31. package/dist/__tests__/services/addressService.test.js.map +1 -0
  32. package/dist/__tests__/services/balanceService.test.d.ts +6 -0
  33. package/dist/__tests__/services/balanceService.test.js +333 -0
  34. package/dist/__tests__/services/balanceService.test.js.map +1 -0
  35. package/dist/__tests__/services/walletSetupService.test.d.ts +6 -0
  36. package/dist/__tests__/services/walletSetupService.test.js +304 -0
  37. package/dist/__tests__/services/walletSetupService.test.js.map +1 -0
  38. package/dist/__tests__/services/walletSwitchingService.test.d.ts +6 -0
  39. package/dist/__tests__/services/walletSwitchingService.test.js +209 -0
  40. package/dist/__tests__/services/walletSwitchingService.test.js.map +1 -0
  41. package/dist/__tests__/services/workletLifecycleService.test.d.ts +6 -0
  42. package/dist/__tests__/services/workletLifecycleService.test.js +451 -0
  43. package/dist/__tests__/services/workletLifecycleService.test.js.map +1 -0
  44. package/dist/__tests__/setup.d.ts +7 -0
  45. package/dist/__tests__/setup.js +49 -0
  46. package/dist/__tests__/setup.js.map +1 -0
  47. package/dist/__tests__/storage/mmkvStorage.test.d.ts +6 -0
  48. package/dist/__tests__/storage/mmkvStorage.test.js +213 -0
  49. package/dist/__tests__/storage/mmkvStorage.test.js.map +1 -0
  50. package/dist/__tests__/store/walletStore.test.d.ts +4 -0
  51. package/dist/__tests__/store/walletStore.test.js +86 -0
  52. package/dist/__tests__/store/walletStore.test.js.map +1 -0
  53. package/dist/__tests__/store/workletStore.test.d.ts +4 -0
  54. package/dist/__tests__/store/workletStore.test.js +255 -0
  55. package/dist/__tests__/store/workletStore.test.js.map +1 -0
  56. package/dist/__tests__/types/hrpc.test.d.ts +4 -0
  57. package/dist/__tests__/types/hrpc.test.js +99 -0
  58. package/dist/__tests__/types/hrpc.test.js.map +1 -0
  59. package/dist/__tests__/utils/balanceUtils.test.d.ts +4 -0
  60. package/dist/__tests__/utils/balanceUtils.test.js +133 -0
  61. package/dist/__tests__/utils/balanceUtils.test.js.map +1 -0
  62. package/dist/__tests__/utils/errorHandling.test.d.ts +6 -0
  63. package/dist/__tests__/utils/errorHandling.test.js +119 -0
  64. package/dist/__tests__/utils/errorHandling.test.js.map +1 -0
  65. package/dist/__tests__/utils/errorUtils.test.d.ts +4 -0
  66. package/dist/__tests__/utils/errorUtils.test.js +133 -0
  67. package/dist/__tests__/utils/errorUtils.test.js.map +1 -0
  68. package/dist/__tests__/utils/initializationState.test.d.ts +6 -0
  69. package/dist/__tests__/utils/initializationState.test.js +243 -0
  70. package/dist/__tests__/utils/initializationState.test.js.map +1 -0
  71. package/dist/__tests__/utils/jsonUtils.test.d.ts +4 -0
  72. package/dist/__tests__/utils/jsonUtils.test.js +118 -0
  73. package/dist/__tests__/utils/jsonUtils.test.js.map +1 -0
  74. package/dist/__tests__/utils/mmkvKeyManager.test.d.ts +6 -0
  75. package/dist/__tests__/utils/mmkvKeyManager.test.js +158 -0
  76. package/dist/__tests__/utils/mmkvKeyManager.test.js.map +1 -0
  77. package/dist/__tests__/utils/mnemonicUtils.test.d.ts +4 -0
  78. package/dist/__tests__/utils/mnemonicUtils.test.js +40 -0
  79. package/dist/__tests__/utils/mnemonicUtils.test.js.map +1 -0
  80. package/dist/__tests__/utils/raceConditions.test.d.ts +6 -0
  81. package/dist/__tests__/utils/raceConditions.test.js +239 -0
  82. package/dist/__tests__/utils/raceConditions.test.js.map +1 -0
  83. package/dist/__tests__/utils/result.test.d.ts +4 -0
  84. package/dist/__tests__/utils/result.test.js +66 -0
  85. package/dist/__tests__/utils/result.test.js.map +1 -0
  86. package/dist/__tests__/utils/schemas.test.d.ts +4 -0
  87. package/dist/__tests__/utils/schemas.test.js +66 -0
  88. package/dist/__tests__/utils/schemas.test.js.map +1 -0
  89. package/dist/__tests__/utils/storeHelpers.test.d.ts +4 -0
  90. package/dist/__tests__/utils/storeHelpers.test.js +227 -0
  91. package/dist/__tests__/utils/storeHelpers.test.js.map +1 -0
  92. package/dist/__tests__/utils/typeGuards.test.d.ts +4 -0
  93. package/dist/__tests__/utils/typeGuards.test.js +175 -0
  94. package/dist/__tests__/utils/typeGuards.test.js.map +1 -0
  95. package/dist/__tests__/utils/validation.test.d.ts +4 -0
  96. package/dist/__tests__/utils/validation.test.js +126 -0
  97. package/dist/__tests__/utils/validation.test.js.map +1 -0
  98. package/dist/__tests__/utils/walletUtils.test.d.ts +4 -0
  99. package/dist/__tests__/utils/walletUtils.test.js +156 -0
  100. package/dist/__tests__/utils/walletUtils.test.js.map +1 -0
  101. package/dist/hooks/useBalance.d.ts +170 -0
  102. package/dist/hooks/useBalance.js +442 -0
  103. package/dist/hooks/useBalance.js.map +1 -0
  104. package/dist/hooks/useWallet.d.ts +43 -0
  105. package/dist/hooks/useWallet.js +193 -0
  106. package/dist/hooks/useWallet.js.map +1 -0
  107. package/dist/hooks/useWalletManager.d.ts +100 -0
  108. package/dist/hooks/useWalletManager.js +526 -0
  109. package/dist/hooks/useWalletManager.js.map +1 -0
  110. package/dist/hooks/useWdkApp.d.ts +66 -0
  111. package/dist/hooks/useWdkApp.js +74 -0
  112. package/dist/hooks/useWdkApp.js.map +1 -0
  113. package/dist/hooks/useWorklet.d.ts +66 -0
  114. package/dist/hooks/useWorklet.js +42 -0
  115. package/dist/hooks/useWorklet.js.map +1 -0
  116. package/dist/index.d.ts +33 -0
  117. package/dist/index.js +36 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/provider/WdkAppProvider.d.ts +112 -0
  120. package/dist/provider/WdkAppProvider.js +558 -0
  121. package/dist/provider/WdkAppProvider.js.map +1 -0
  122. package/dist/services/accountService.d.ts +52 -0
  123. package/dist/services/accountService.js +119 -0
  124. package/dist/services/accountService.js.map +1 -0
  125. package/dist/services/addressService.d.ts +22 -0
  126. package/dist/services/addressService.js +110 -0
  127. package/dist/services/addressService.js.map +1 -0
  128. package/dist/services/balanceService.d.ts +114 -0
  129. package/dist/services/balanceService.js +208 -0
  130. package/dist/services/balanceService.js.map +1 -0
  131. package/dist/services/walletSetupService.d.ts +217 -0
  132. package/dist/services/walletSetupService.js +535 -0
  133. package/dist/services/walletSetupService.js.map +1 -0
  134. package/dist/services/walletSwitchingService.d.ts +48 -0
  135. package/dist/services/walletSwitchingService.js +143 -0
  136. package/dist/services/walletSwitchingService.js.map +1 -0
  137. package/dist/services/workletLifecycleService.d.ts +117 -0
  138. package/dist/services/workletLifecycleService.js +433 -0
  139. package/dist/services/workletLifecycleService.js.map +1 -0
  140. package/dist/storage/mmkvStorage.d.ts +44 -0
  141. package/dist/storage/mmkvStorage.js +348 -0
  142. package/dist/storage/mmkvStorage.js.map +1 -0
  143. package/dist/store/walletStore.d.ts +130 -0
  144. package/dist/store/walletStore.js +204 -0
  145. package/dist/store/walletStore.js.map +1 -0
  146. package/dist/store/workletStore.d.ts +121 -0
  147. package/dist/store/workletStore.js +256 -0
  148. package/dist/store/workletStore.js.map +1 -0
  149. package/dist/types/hrpc.d.ts +60 -0
  150. package/dist/types/hrpc.js +26 -0
  151. package/dist/types/hrpc.js.map +1 -0
  152. package/dist/types.d.ts +168 -0
  153. package/dist/types.js +7 -0
  154. package/dist/types.js.map +1 -0
  155. package/dist/utils/balanceUtils.d.ts +30 -0
  156. package/dist/utils/balanceUtils.js +86 -0
  157. package/dist/utils/balanceUtils.js.map +1 -0
  158. package/dist/utils/constants.d.ts +66 -0
  159. package/dist/utils/constants.js +73 -0
  160. package/dist/utils/constants.js.map +1 -0
  161. package/dist/utils/errorHandling.d.ts +47 -0
  162. package/dist/utils/errorHandling.js +54 -0
  163. package/dist/utils/errorHandling.js.map +1 -0
  164. package/dist/utils/errorUtils.d.ts +89 -0
  165. package/dist/utils/errorUtils.js +264 -0
  166. package/dist/utils/errorUtils.js.map +1 -0
  167. package/dist/utils/initializationState.d.ts +129 -0
  168. package/dist/utils/initializationState.js +220 -0
  169. package/dist/utils/initializationState.js.map +1 -0
  170. package/dist/utils/jsonUtils.d.ts +21 -0
  171. package/dist/utils/jsonUtils.js +67 -0
  172. package/dist/utils/jsonUtils.js.map +1 -0
  173. package/dist/utils/logger.d.ts +27 -0
  174. package/dist/utils/logger.js +50 -0
  175. package/dist/utils/logger.js.map +1 -0
  176. package/dist/utils/mmkvKeyManager.d.ts +57 -0
  177. package/dist/utils/mmkvKeyManager.js +214 -0
  178. package/dist/utils/mmkvKeyManager.js.map +1 -0
  179. package/dist/utils/mnemonicUtils.d.ts +17 -0
  180. package/dist/utils/mnemonicUtils.js +28 -0
  181. package/dist/utils/mnemonicUtils.js.map +1 -0
  182. package/dist/utils/operationMutex.d.ts +69 -0
  183. package/dist/utils/operationMutex.js +150 -0
  184. package/dist/utils/operationMutex.js.map +1 -0
  185. package/dist/utils/result.d.ts +34 -0
  186. package/dist/utils/result.js +43 -0
  187. package/dist/utils/result.js.map +1 -0
  188. package/dist/utils/schemas.d.ts +365 -0
  189. package/dist/utils/schemas.js +152 -0
  190. package/dist/utils/schemas.js.map +1 -0
  191. package/dist/utils/storeHelpers.d.ts +112 -0
  192. package/dist/utils/storeHelpers.js +198 -0
  193. package/dist/utils/storeHelpers.js.map +1 -0
  194. package/dist/utils/typeGuards.d.ts +70 -0
  195. package/dist/utils/typeGuards.js +95 -0
  196. package/dist/utils/typeGuards.js.map +1 -0
  197. package/dist/utils/validation.d.ts +53 -0
  198. package/dist/utils/validation.js +152 -0
  199. package/dist/utils/validation.js.map +1 -0
  200. package/dist/utils/walletStateHelpers.d.ts +62 -0
  201. package/dist/utils/walletStateHelpers.js +81 -0
  202. package/dist/utils/walletStateHelpers.js.map +1 -0
  203. package/dist/utils/walletUtils.d.ts +38 -0
  204. package/dist/utils/walletUtils.js +87 -0
  205. package/dist/utils/walletUtils.js.map +1 -0
  206. package/package.json +79 -0
  207. package/src/__mocks__/react.ts +34 -0
  208. package/src/__mocks__/secureStorage.ts +87 -0
  209. package/src/__tests__/hooks/useBalance.test.ts +286 -0
  210. package/src/__tests__/hooks/useWallet.test.ts +122 -0
  211. package/src/__tests__/hooks/useWalletManager.test.ts +271 -0
  212. package/src/__tests__/hooks/useWdkApp.test.tsx +59 -0
  213. package/src/__tests__/hooks/useWorklet.test.ts +195 -0
  214. package/src/__tests__/provider/WdkAppProvider.test.tsx +67 -0
  215. package/src/__tests__/services/accountService.test.ts +337 -0
  216. package/src/__tests__/services/addressService.test.ts +312 -0
  217. package/src/__tests__/services/balanceService.test.ts +411 -0
  218. package/src/__tests__/services/walletSetupService.test.ts +463 -0
  219. package/src/__tests__/services/walletSwitchingService.test.ts +258 -0
  220. package/src/__tests__/services/workletLifecycleService.test.ts +514 -0
  221. package/src/__tests__/setup.ts +54 -0
  222. package/src/__tests__/storage/mmkvStorage.test.ts +325 -0
  223. package/src/__tests__/store/walletStore.test.ts +101 -0
  224. package/src/__tests__/store/workletStore.test.ts +329 -0
  225. package/src/__tests__/types/hrpc.test.ts +125 -0
  226. package/src/__tests__/utils/balanceUtils.test.ts +151 -0
  227. package/src/__tests__/utils/errorHandling.test.ts +147 -0
  228. package/src/__tests__/utils/errorUtils.test.ts +170 -0
  229. package/src/__tests__/utils/initializationState.test.ts +337 -0
  230. package/src/__tests__/utils/jsonUtils.test.ts +131 -0
  231. package/src/__tests__/utils/mmkvKeyManager.test.ts +205 -0
  232. package/src/__tests__/utils/mnemonicUtils.test.ts +48 -0
  233. package/src/__tests__/utils/raceConditions.test.ts +292 -0
  234. package/src/__tests__/utils/result.test.ts +73 -0
  235. package/src/__tests__/utils/schemas.test.ts +82 -0
  236. package/src/__tests__/utils/storeHelpers.test.ts +323 -0
  237. package/src/__tests__/utils/typeGuards.test.ts +209 -0
  238. package/src/__tests__/utils/validation.test.ts +152 -0
  239. package/src/__tests__/utils/walletUtils.test.ts +195 -0
  240. package/src/hooks/useBalance.ts +597 -0
  241. package/src/hooks/useWallet.ts +288 -0
  242. package/src/hooks/useWalletManager.ts +654 -0
  243. package/src/hooks/useWdkApp.ts +78 -0
  244. package/src/hooks/useWorklet.ts +109 -0
  245. package/src/index.ts +112 -0
  246. package/src/provider/WdkAppProvider.tsx +764 -0
  247. package/src/services/accountService.ts +134 -0
  248. package/src/services/addressService.ts +125 -0
  249. package/src/services/balanceService.ts +291 -0
  250. package/src/services/walletSetupService.ts +695 -0
  251. package/src/services/walletSwitchingService.ts +157 -0
  252. package/src/services/workletLifecycleService.ts +561 -0
  253. package/src/storage/mmkvStorage.ts +417 -0
  254. package/src/store/walletStore.ts +301 -0
  255. package/src/store/workletStore.ts +340 -0
  256. package/src/types/hrpc.ts +78 -0
  257. package/src/types.ts +188 -0
  258. package/src/utils/balanceUtils.ts +96 -0
  259. package/src/utils/constants.ts +84 -0
  260. package/src/utils/errorHandling.md +163 -0
  261. package/src/utils/errorHandling.ts +61 -0
  262. package/src/utils/errorUtils.ts +300 -0
  263. package/src/utils/initializationState.ts +242 -0
  264. package/src/utils/jsonUtils.ts +75 -0
  265. package/src/utils/logger.ts +54 -0
  266. package/src/utils/mmkvKeyManager.ts +256 -0
  267. package/src/utils/mnemonicUtils.ts +35 -0
  268. package/src/utils/operationMutex.ts +181 -0
  269. package/src/utils/result.ts +57 -0
  270. package/src/utils/schemas.ts +190 -0
  271. package/src/utils/storeHelpers.ts +236 -0
  272. package/src/utils/typeGuards.ts +129 -0
  273. package/src/utils/validation.ts +174 -0
  274. package/src/utils/walletStateHelpers.ts +104 -0
  275. package/src/utils/walletUtils.ts +107 -0
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Error utility functions for consistent error handling
3
+ *
4
+ * ## Usage Guidelines
5
+ *
6
+ * **For Services**: Use `handleServiceError()` from `errorHandling.ts` - this provides
7
+ * consistent normalization and logging for service-layer errors. Errors are NOT sanitized
8
+ * (sanitizeLevel: false) because services log internally and need full error details.
9
+ *
10
+ * **For Hooks/UI**: Use `normalizeError()` directly with appropriate sanitization level.
11
+ * Hooks should sanitize errors before exposing them to UI components to prevent information leakage.
12
+ *
13
+ * @example Service usage (use handleServiceError instead):
14
+ * ```typescript
15
+ * import { handleServiceError } from './errorHandling'
16
+ * try {
17
+ * await someOperation()
18
+ * } catch (error) {
19
+ * handleServiceError(error, 'MyService', 'operationName', { context })
20
+ * }
21
+ * ```
22
+ *
23
+ * @example Hook/UI usage:
24
+ * ```typescript
25
+ * import { normalizeError } from './errorUtils'
26
+ * try {
27
+ * await someOperation()
28
+ * } catch (error) {
29
+ * const normalized = normalizeError(error, true, { component: 'MyHook', operation: 'fetchData' })
30
+ * setError(normalized.message)
31
+ * }
32
+ * ```
33
+ */
34
+
35
+ /**
36
+ * Sanitization levels for error messages
37
+ */
38
+ export enum SanitizationLevel {
39
+ NONE = 'none', // No sanitization (internal debugging only)
40
+ DEVELOPMENT = 'dev', // Mask sensitive strings but show structure
41
+ PRODUCTION = 'prod', // Aggressive sanitization
42
+ }
43
+
44
+ /**
45
+ * Context-aware sensitive patterns
46
+ * More specific patterns to avoid false positives while catching real sensitive data
47
+ */
48
+ const SENSITIVE_PATTERNS = [
49
+ // Cryptographic keys and secrets (more specific)
50
+ /\b(encryption[_-]?key|encryptionKey|encrypted[_-]?seed|encryptedSeed|secret[_-]?key|private[_-]?key)\s*[:=]\s*([a-f0-9]{32,}|[A-Za-z0-9+/]{40,})/gi,
51
+ // Mnemonic phrases (12 or 24 words) - allow alphanumeric words
52
+ /\b(mnemonic|seed[_-]?phrase|recovery[_-]?phrase)\s*[:=]\s*([a-zA-Z0-9]+\s+){11,23}[a-zA-Z0-9]+/gi,
53
+ // Base64 encoded keys (long base64 strings)
54
+ /[A-Za-z0-9+/]{40,}={0,2}/g,
55
+ // Hex strings that look like keys (32+ chars, even length)
56
+ /\b0x?[a-f0-9]{32,}\b/gi,
57
+ // File paths with sensitive names
58
+ /file:\/\/[^\s]*(key|secret|password|credential|seed|mnemonic|private)[^\s]*/gi,
59
+ // Paths containing sensitive directories
60
+ /\/(?:private|secret|keys|credentials|seeds|mnemonics)\/[^\s]+/gi,
61
+ // API tokens and keys in various formats
62
+ /\b(api[_-]?key|access[_-]?token|bearer[_-]?token|auth[_-]?token)\s*[:=]\s*[^\s]{20,}/gi,
63
+ // Passwords (but not "password" as a word)
64
+ /\bpassword\s*[:=]\s*[^\s]{8,}/gi,
65
+ ]
66
+
67
+ /**
68
+ * Whitelist of safe patterns that should NOT be sanitized
69
+ * These are common non-sensitive terms that might match sensitive patterns
70
+ */
71
+ const SAFE_PATTERNS = [
72
+ /\b(public[_-]?key|publicKey)\b/gi, // Public keys are safe
73
+ /\b(error|Error|ERROR)\b/g, // Error messages themselves
74
+ /\b(function|Function|const|let|var)\b/g, // Code keywords
75
+ /\b(undefined|null|true|false)\b/g, // JavaScript literals
76
+ ]
77
+
78
+ /**
79
+ * Check if a string matches a safe pattern (should not be sanitized)
80
+ */
81
+ function isSafePattern(text: string): boolean {
82
+ return SAFE_PATTERNS.some(pattern => pattern.test(text))
83
+ }
84
+
85
+ /**
86
+ * Mask sensitive string patterns (hex/base64) for development mode
87
+ */
88
+ function maskSensitiveStrings(message: string): string {
89
+ return message
90
+ .replace(/\b0x?[a-f0-9]{32,}\b/gi, (match) => {
91
+ if (match.length <= 20) return match
92
+ return `${match.substring(0, 8)}...${match.substring(match.length - 4)}`
93
+ })
94
+ .replace(/\b[A-Za-z0-9+/]{40,}={0,2}\b/g, (match) => {
95
+ return `${match.substring(0, 8)}...${match.substring(match.length - 4)}`
96
+ })
97
+ }
98
+
99
+ /**
100
+ * Remove file paths from error messages
101
+ */
102
+ function removeFilePaths(message: string): string {
103
+ return message
104
+ .replace(/file:\/\/[^\s]+/gi, '[file path]')
105
+ .replace(/\/[^\s]+\/[^\s]+/g, '[path]')
106
+ }
107
+
108
+ /**
109
+ * Get replacement text for a sensitive pattern match
110
+ */
111
+ function getSensitiveReplacement(match: string): string {
112
+ const lowerMatch = match.toLowerCase()
113
+ if (lowerMatch.includes('encryption') || lowerMatch.includes('encrypted')) {
114
+ return '[encryption data]'
115
+ }
116
+ if (lowerMatch.includes('mnemonic') || lowerMatch.includes('seed phrase')) {
117
+ return '[mnemonic phrase]'
118
+ }
119
+ if (lowerMatch.includes('key') && !lowerMatch.includes('public')) {
120
+ return '[key]'
121
+ }
122
+ if (lowerMatch.includes('token')) {
123
+ return '[token]'
124
+ }
125
+ if (lowerMatch.includes('password')) {
126
+ return '[password]'
127
+ }
128
+ if (lowerMatch.includes('secret')) {
129
+ return '[secret]'
130
+ }
131
+ if (/[a-f0-9]{32,}/i.test(match) || /[A-Za-z0-9+/]{40,}/.test(match)) {
132
+ return '[sensitive data]'
133
+ }
134
+ return '[sensitive]'
135
+ }
136
+
137
+ /**
138
+ * Apply sensitive pattern sanitization
139
+ */
140
+ function applySensitivePatternSanitization(message: string): string {
141
+ let sanitized = message
142
+ for (const pattern of SENSITIVE_PATTERNS) {
143
+ sanitized = sanitized.replace(pattern, (match) => {
144
+ if (isSafePattern(match)) {
145
+ return match
146
+ }
147
+ return getSensitiveReplacement(match)
148
+ })
149
+ }
150
+ return sanitized
151
+ }
152
+
153
+ /**
154
+ * Sanitize error message to prevent information leakage
155
+ * Removes or masks sensitive information while preserving useful debugging info
156
+ *
157
+ * @param message - Error message to sanitize
158
+ * @param isDevelopment - Whether we're in development mode (less sanitization)
159
+ * @param context - Optional context about where the error occurred (for better sanitization)
160
+ * @returns Sanitized error message
161
+ */
162
+ export function sanitizeErrorMessage(
163
+ message: string,
164
+ isDevelopment = false,
165
+ context?: { operation?: string; component?: string }
166
+ ): string {
167
+ if (isDevelopment) {
168
+ return maskSensitiveStrings(message)
169
+ }
170
+
171
+ // In production, be more aggressive with sanitization
172
+ let sanitized = removeFilePaths(message)
173
+ sanitized = applySensitivePatternSanitization(sanitized)
174
+
175
+ // Additional cleanup: remove any remaining long hex/base64 strings
176
+ sanitized = sanitized.replace(/\b0x?[a-f0-9]{32,}\b/gi, '[hex string]')
177
+ sanitized = sanitized.replace(/\b[A-Za-z0-9+/]{40,}={0,2}\b/g, '[base64 string]')
178
+
179
+ return sanitized
180
+ }
181
+
182
+ /**
183
+ * Normalize error to Error instance
184
+ * Converts any error-like value to a proper Error object
185
+ * Always sanitizes the error message (with different levels) to prevent information leakage
186
+ *
187
+ * @param error - Error to normalize
188
+ * @param sanitizeLevel - Sanitization level or boolean (default: PRODUCTION in production, DEVELOPMENT in dev)
189
+ * @param context - Optional context about where the error occurred
190
+ * @returns Normalized Error instance
191
+ */
192
+ export function normalizeError(
193
+ error: unknown,
194
+ sanitizeLevel: SanitizationLevel | boolean = process.env.NODE_ENV === 'production'
195
+ ? SanitizationLevel.PRODUCTION
196
+ : SanitizationLevel.DEVELOPMENT,
197
+ context?: { operation?: string; component?: string; [key: string]: unknown }
198
+ ): Error {
199
+ let errorMessage: string
200
+
201
+ if (error instanceof Error) {
202
+ errorMessage = error.message
203
+ } else if (typeof error === 'string') {
204
+ errorMessage = error
205
+ } else if (error && typeof error === 'object' && 'message' in error) {
206
+ errorMessage = String(error.message)
207
+ } else {
208
+ errorMessage = String(error)
209
+ }
210
+
211
+ // Always sanitize, but with different levels
212
+ const level = typeof sanitizeLevel === 'boolean'
213
+ ? (sanitizeLevel ? SanitizationLevel.PRODUCTION : SanitizationLevel.NONE)
214
+ : sanitizeLevel
215
+
216
+ if (level !== SanitizationLevel.NONE) {
217
+ errorMessage = sanitizeErrorMessage(
218
+ errorMessage,
219
+ level === SanitizationLevel.DEVELOPMENT,
220
+ context
221
+ )
222
+ }
223
+
224
+ const normalizedError = new Error(errorMessage)
225
+
226
+ // Preserve error name and stack if available
227
+ if (error instanceof Error) {
228
+ normalizedError.name = error.name
229
+ // Sanitize stack trace based on level
230
+ if (error.stack) {
231
+ if (level !== SanitizationLevel.NONE) {
232
+ // Mask file paths and sensitive data in stack traces
233
+ normalizedError.stack = sanitizeErrorMessage(error.stack, level === SanitizationLevel.DEVELOPMENT, context)
234
+ } else {
235
+ normalizedError.stack = error.stack
236
+ }
237
+ }
238
+ }
239
+
240
+ return normalizedError
241
+ }
242
+
243
+ /**
244
+ * Get error message from any error-like value
245
+ */
246
+ export function getErrorMessage(error: unknown): string {
247
+ return normalizeError(error).message
248
+ }
249
+
250
+ /**
251
+ * Check if error is a specific type
252
+ */
253
+ export function isErrorType(error: unknown, typeName: string): boolean {
254
+ return error instanceof Error && error.name === typeName
255
+ }
256
+
257
+ /**
258
+ * Create a standardized error with context
259
+ */
260
+ export function createContextualError(
261
+ message: string,
262
+ context?: Record<string, unknown>
263
+ ): Error {
264
+ const error = new Error(message)
265
+ if (context) {
266
+ Object.assign(error, { context })
267
+ }
268
+ return error
269
+ }
270
+
271
+ /**
272
+ * Check if an error is an authentication error
273
+ * Used to prevent automatic retries when authentication fails
274
+ *
275
+ * @param error - Error to check
276
+ * @returns true if the error is an authentication error
277
+ */
278
+ export function isAuthenticationError(error: unknown): boolean {
279
+ // Check if it's an AuthenticationError instance from secure storage
280
+ if (error && typeof error === 'object' && 'constructor' in error) {
281
+ const errorName = error.constructor.name
282
+ if (errorName === 'AuthenticationError') {
283
+ return true
284
+ }
285
+ }
286
+
287
+ // Check if it's an Error instance with authentication-related properties
288
+ if (error instanceof Error) {
289
+ const msg = error.message.toLowerCase()
290
+ return (
291
+ error.name === 'AuthenticationError' ||
292
+ msg.includes('authentication') ||
293
+ msg.includes('biometric') ||
294
+ msg.includes('authentication required but failed')
295
+ )
296
+ }
297
+
298
+ return false
299
+ }
300
+
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Worklet Initialization State Machine
3
+ *
4
+ * Represents the state of the worklet runtime initialization (global, happens once).
5
+ * This is separate from wallet loading, which happens per-identifier.
6
+ */
7
+
8
+ /**
9
+ * Worklet initialization status enum
10
+ *
11
+ * Represents the current state of the worklet runtime initialization.
12
+ * The worklet is initialized once (global), but wallets are loaded per-identifier.
13
+ *
14
+ * Flow:
15
+ * 1. IDLE -> STARTING_WORKLET (worklet initialization begins)
16
+ * 2. STARTING_WORKLET -> WORKLET_READY (worklet runtime ready, can now load wallets)
17
+ *
18
+ * After WORKLET_READY, you can load different wallets (per identifier).
19
+ * Wallet loading state is separate - see walletState in WdkAppContextValue.
20
+ */
21
+ export enum InitializationStatus {
22
+ /** Initial state - worklet not started */
23
+ IDLE = 'idle',
24
+ /** Worklet runtime is starting (happens once, global) */
25
+ STARTING_WORKLET = 'starting_worklet',
26
+ /** Worklet is ready - can now load wallets (per identifier) */
27
+ WORKLET_READY = 'worklet_ready',
28
+ /** Error state - worklet initialization failed */
29
+ ERROR = 'error',
30
+ }
31
+
32
+ /**
33
+ * App-level status enum
34
+ *
35
+ * Represents the combined state of worklet initialization and wallet loading.
36
+ * This is a convenience enum for app-level "is ready?" checks.
37
+ *
38
+ * For granular control, use workletState and walletState separately.
39
+ */
40
+ export enum AppStatus {
41
+ /** Worklet not started */
42
+ IDLE = 'idle',
43
+ /** Worklet is starting */
44
+ STARTING_WORKLET = 'starting_worklet',
45
+ /** Worklet ready, no wallet loaded */
46
+ WORKLET_READY = 'worklet_ready',
47
+ /** Loading a wallet (checking existence, decrypting, initializing) */
48
+ LOADING_WALLET = 'loading_wallet',
49
+ /** Fully ready - worklet started, wallet loaded, addresses available */
50
+ READY = 'ready',
51
+ /** Error state - worklet or wallet error */
52
+ ERROR = 'error',
53
+ }
54
+
55
+ /**
56
+ * Helper to check if status represents an error state
57
+ */
58
+ export function isErrorStatus(status: InitializationStatus): boolean {
59
+ return status === InitializationStatus.ERROR
60
+ }
61
+
62
+ /**
63
+ * Helper to check if worklet initialization is complete and ready
64
+ */
65
+ export function isReadyStatus(status: InitializationStatus): boolean {
66
+ return status === InitializationStatus.WORKLET_READY
67
+ }
68
+
69
+ /**
70
+ * Helper to check if worklet initialization is in progress
71
+ */
72
+ export function isInProgressStatus(status: InitializationStatus): boolean {
73
+ return status === InitializationStatus.STARTING_WORKLET
74
+ }
75
+
76
+ /**
77
+ * Helper to check if app status represents an in-progress state
78
+ */
79
+ export function isAppInProgressStatus(status: AppStatus): boolean {
80
+ return [
81
+ AppStatus.STARTING_WORKLET,
82
+ AppStatus.LOADING_WALLET,
83
+ ].includes(status)
84
+ }
85
+
86
+ /**
87
+ * Helper to check if app is ready (worklet + wallet both ready)
88
+ */
89
+ export function isAppReadyStatus(status: AppStatus): boolean {
90
+ return status === AppStatus.READY
91
+ }
92
+
93
+ /**
94
+ * Helper to check if worklet has started (worklet runtime is ready)
95
+ * Once worklet is ready, you can load wallets (per identifier)
96
+ */
97
+ export function hasWorkletStarted(status: InitializationStatus): boolean {
98
+ return [
99
+ InitializationStatus.WORKLET_READY,
100
+ InitializationStatus.ERROR,
101
+ ].includes(status)
102
+ }
103
+
104
+ /**
105
+ * Helper to check if wallet operations can be performed
106
+ * Returns true when worklet is ready (wallets can be loaded per identifier)
107
+ */
108
+ export function canLoadWallet(status: InitializationStatus): boolean {
109
+ return status === InitializationStatus.WORKLET_READY
110
+ }
111
+
112
+ /**
113
+ * Helper to check if app status indicates worklet has started
114
+ */
115
+ export function hasWorkletStartedApp(status: AppStatus): boolean {
116
+ return [
117
+ AppStatus.WORKLET_READY,
118
+ AppStatus.LOADING_WALLET,
119
+ AppStatus.READY,
120
+ AppStatus.ERROR,
121
+ ].includes(status)
122
+ }
123
+
124
+ /**
125
+ * Helper to check if wallet operations can be performed based on app status
126
+ */
127
+ export function canLoadWalletApp(status: AppStatus): boolean {
128
+ return [
129
+ AppStatus.WORKLET_READY,
130
+ AppStatus.LOADING_WALLET,
131
+ AppStatus.READY,
132
+ ].includes(status)
133
+ }
134
+
135
+ /**
136
+ * Get human-readable worklet initialization status message
137
+ */
138
+ export function getStatusMessage(status: InitializationStatus): string {
139
+ switch (status) {
140
+ case InitializationStatus.IDLE:
141
+ return 'Not started'
142
+ case InitializationStatus.STARTING_WORKLET:
143
+ return 'Starting worklet...'
144
+ case InitializationStatus.WORKLET_READY:
145
+ return 'Worklet ready - can load wallets'
146
+ case InitializationStatus.ERROR:
147
+ return 'Worklet error'
148
+ default:
149
+ return 'Unknown'
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Get human-readable app status message
155
+ */
156
+ export function getAppStatusMessage(status: AppStatus): string {
157
+ switch (status) {
158
+ case AppStatus.IDLE:
159
+ return 'Not started'
160
+ case AppStatus.STARTING_WORKLET:
161
+ return 'Starting worklet...'
162
+ case AppStatus.WORKLET_READY:
163
+ return 'Worklet ready - can load wallets'
164
+ case AppStatus.LOADING_WALLET:
165
+ return 'Loading wallet...'
166
+ case AppStatus.READY:
167
+ return 'Ready'
168
+ case AppStatus.ERROR:
169
+ return 'Error'
170
+ default:
171
+ return 'Unknown'
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Gets worklet initialization status from worklet state
177
+ *
178
+ * @param workletState - Worklet state (global, from workletStore)
179
+ * @returns Worklet initialization status
180
+ */
181
+ export function getWorkletStatus(
182
+ workletState: { isWorkletStarted: boolean; isLoading: boolean; error: string | null }
183
+ ): InitializationStatus {
184
+ if (workletState.error) {
185
+ return InitializationStatus.ERROR
186
+ }
187
+
188
+ if (!workletState.isWorkletStarted) {
189
+ return workletState.isLoading
190
+ ? InitializationStatus.STARTING_WORKLET
191
+ : InitializationStatus.IDLE
192
+ }
193
+
194
+ return InitializationStatus.WORKLET_READY
195
+ }
196
+
197
+ /**
198
+ * Derives combined app status from worklet and wallet states
199
+ *
200
+ * This is a convenience function that combines the global worklet state with the
201
+ * per-identifier wallet state to produce a unified app-level status.
202
+ *
203
+ * NOTE: This is for convenience only. For granular control, use workletState and
204
+ * walletState separately. The combined status hides some information (e.g., can't
205
+ * distinguish worklet errors from wallet errors).
206
+ *
207
+ * @param workletState - Worklet state (global, from workletStore)
208
+ * @param walletState - Wallet state (per-identifier, from wallet state machine)
209
+ * @returns Combined app status (convenience helper)
210
+ */
211
+ export function getCombinedStatus(
212
+ workletState: { isWorkletStarted: boolean; isLoading: boolean; error: string | null },
213
+ walletState: { type: 'not_loaded' | 'checking' | 'loading' | 'ready' | 'error' }
214
+ ): AppStatus {
215
+ // Worklet errors take precedence
216
+ if (workletState.error) {
217
+ return AppStatus.ERROR
218
+ }
219
+
220
+ // Worklet not ready
221
+ if (!workletState.isWorkletStarted) {
222
+ return workletState.isLoading
223
+ ? AppStatus.STARTING_WORKLET
224
+ : AppStatus.IDLE
225
+ }
226
+
227
+ // Worklet ready, check wallet state
228
+ switch (walletState.type) {
229
+ case 'not_loaded':
230
+ return AppStatus.WORKLET_READY
231
+ case 'checking':
232
+ case 'loading':
233
+ return AppStatus.LOADING_WALLET
234
+ case 'ready':
235
+ return AppStatus.READY
236
+ case 'error':
237
+ return AppStatus.ERROR
238
+ default:
239
+ return AppStatus.IDLE
240
+ }
241
+ }
242
+
@@ -0,0 +1,75 @@
1
+ /**
2
+ * JSON Utilities
3
+ *
4
+ * Provides safe JSON stringification and validation utilities
5
+ * to prevent security issues and ensure data integrity.
6
+ */
7
+
8
+ /**
9
+ * Validate that a value has a safe JSON structure
10
+ * Prevents prototype pollution and circular references
11
+ */
12
+ export function validateJSONStructure(value: unknown): boolean {
13
+ try {
14
+ // Check for circular references
15
+ const seen = new WeakSet()
16
+
17
+ function check(value: unknown): boolean {
18
+ if (value === null || typeof value !== 'object') {
19
+ return true
20
+ }
21
+
22
+ if (seen.has(value as object)) {
23
+ return false // Circular reference
24
+ }
25
+
26
+ seen.add(value as object)
27
+
28
+ if (Array.isArray(value)) {
29
+ return value.every(check)
30
+ }
31
+
32
+ // Check for prototype pollution
33
+ const proto = Object.getPrototypeOf(value)
34
+ // Reject objects with non-standard prototypes (not null, Object.prototype, or Array.prototype)
35
+ // Note: Objects created with Object.create(Array.prototype) should be rejected
36
+ if (proto !== null && proto !== Object.prototype) {
37
+ // Allow Array.prototype only for actual arrays (checked above)
38
+ // Reject objects that inherit from Array.prototype but aren't arrays
39
+ return false
40
+ }
41
+
42
+ return Object.values(value as Record<string, unknown>).every(check)
43
+ }
44
+
45
+ return check(value)
46
+ } catch {
47
+ return false
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Safe JSON stringify with validation
53
+ * Validates structure before stringifying to prevent security issues
54
+ *
55
+ * @param value - Value to stringify
56
+ * @param space - Optional spacing for pretty printing
57
+ * @returns JSON string
58
+ * @throws Error if value cannot be safely stringified
59
+ */
60
+ export function safeStringify(value: unknown, space?: number): string {
61
+ // Validate structure first
62
+ if (!validateJSONStructure(value)) {
63
+ throw new Error('Value contains circular references or unsafe prototype properties')
64
+ }
65
+
66
+ try {
67
+ return JSON.stringify(value, null, space)
68
+ } catch (error) {
69
+ if (error instanceof Error) {
70
+ throw new Error(`Failed to stringify value: ${error.message}`)
71
+ }
72
+ throw new Error('Failed to stringify value: Unknown error')
73
+ }
74
+ }
75
+
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Logger utility for development and production
3
+ *
4
+ * Provides controlled logging that can be disabled in production
5
+ * to improve performance and prevent information leakage.
6
+ */
7
+
8
+ /**
9
+ * Check if we're in development mode
10
+ * React Native sets __DEV__ to true in development builds
11
+ */
12
+ const isDevelopment = typeof __DEV__ !== 'undefined' ? __DEV__ : process.env.NODE_ENV !== 'production'
13
+
14
+ /**
15
+ * Log a message (only in development)
16
+ *
17
+ * @param message - Message to log
18
+ * @param args - Additional arguments to log
19
+ */
20
+ export function log(...args: unknown[]): void {
21
+ if (isDevelopment) {
22
+ console.log(...args)
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Log an error (always logged, but sanitized in production)
28
+ *
29
+ * @param message - Error message
30
+ * @param error - Error object or additional data
31
+ */
32
+ export function logError(message: string, error?: unknown): void {
33
+ if (isDevelopment) {
34
+ console.error(message, error)
35
+ } else {
36
+ // In production, log sanitized errors only
37
+ // This prevents information leakage while still allowing error tracking
38
+ console.error(message)
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Log a warning (only in development)
44
+ *
45
+ * @param message - Warning message
46
+ * @param args - Additional arguments to log
47
+ */
48
+ export function logWarn(...args: unknown[]): void {
49
+ if (isDevelopment) {
50
+ console.warn(...args)
51
+ }
52
+ }
53
+
54
+