OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-wallet commits / 8623565

Phase 2: Fix storage initialization race condition
- Added singleton lock to prevent concurrent storage initialization - Multiple API calls no longer cause file descriptor conflicts - Initialization promise ensures only one storage instance created - Waits for in-progress initialization instead of creating duplicates - Fixes 'File descriptor could not be locked' errors Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
8623565ab14603b77ae1ac9b61b93c1c60c0ef25
by plankatron <fleeky@gmail.com> · 2026-01-27T20:59:49.000Z

Changed files (2) +28 -1

.claude/tmux-registry.json +1 -1
……@@ -8,7 +8,7 @@
88 "purpose": "Seeding pear://18x3enb54ttcr6uuhg5hh1cqzwi8ydnm658fmgyyjkzoqxd1ybso",
99 "command": "pear seed pear://18x3enb54ttcr6uuhg5hh1cqzwi8ydnm658fmgyyjkzoqxd1ybso .",
1010 "persistent": true,
11 "latest_version": "11460",
11 "latest_version": "11464",
1212 "last_deployed": "2026-01-27",
1313 "features": "Phase 2 COMPLETE: Auth + Encryption + Validation + Rate Limiting + CORS + Signed Invites + Password Unlock UI ✅"
1414 },
lib/wallet-storage.cjs +27 -0
……@@ -29,6 +29,9 @@ let swarm = null
2929let identityKeyPair = null
3030let connections = new Set() // Track active connections
3131
32// Initialization lock to prevent concurrent initialization
33let initializationPromise = null
34
3235// WDK singleton instances (Phase 6.1)
3336let wdkInstance = null
3437let walletManagers = {} // { bitcoin, ethereum }
……@@ -112,10 +115,34 @@ async function apply(nodes, view, base) {
112115 * @param {Object} identity - keet-identity-key instance
113116 */
114117async function initializeStorage(identity) {
118 // Return existing instance if already initialized
115119 if (store && autobase && txHistoryDb) {
116120 return { store, autobase, txHistoryDb, swarm }
117121 }
118122
123 // If initialization is in progress, wait for it
124 if (initializationPromise) {
125 console.log('⏳ Storage initialization in progress, waiting...')
126 return await initializationPromise
127 }
128
129 // Start new initialization
130 console.log('🔧 Initializing storage (singleton)')
131 initializationPromise = _initializeStorage(identity)
132
133 try {
134 const result = await initializationPromise
135 return result
136 } finally {
137 // Clear the promise after initialization completes (success or failure)
138 initializationPromise = null
139 }
140}
141
142/**
143 * Internal storage initialization (wrapped by singleton lock)
144 */
145async function _initializeStorage(identity) {
119146 // Store identity keypair for attestation
120147 identityKeyPair = identity.identityKeyPair
121148