@1sat/wallet-toolbox 0.0.66 → 0.0.69
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/wallet/factory.js +71 -66
- package/package.json +1 -1
package/dist/wallet/factory.js
CHANGED
|
@@ -95,32 +95,33 @@ export async function createWebWallet(config) {
|
|
|
95
95
|
// Add remote storage to the existing storage manager using public API
|
|
96
96
|
await storage.addWalletStorageProvider(remoteClient);
|
|
97
97
|
console.log("[createWebWallet] Remote storage connected successfully");
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
console.log(
|
|
98
|
+
// Bidirectional sync: pull first, then push
|
|
99
|
+
// Pull builds idMap via natural key matching (reference for transactions)
|
|
100
|
+
// Push sends local changes to remote
|
|
101
|
+
console.log("[createWebWallet] Pulling from remote...");
|
|
102
|
+
const pullResult = await storage.syncFromReader(identityPubKey, remoteClient);
|
|
103
|
+
console.log(`[createWebWallet] Pulled: ${pullResult.inserts} inserts, ${pullResult.updates} updates`);
|
|
104
|
+
console.log("[createWebWallet] Pushing to remote...");
|
|
105
|
+
await storage.updateBackups(undefined, (msg) => {
|
|
106
|
+
console.log("[createWebWallet] Push:", msg);
|
|
107
|
+
return msg;
|
|
108
|
+
});
|
|
109
|
+
console.log("[createWebWallet] Push complete");
|
|
102
110
|
}
|
|
103
111
|
catch (err) {
|
|
104
112
|
console.log("[createWebWallet] Remote storage connection failed:", err instanceof Error ? err.message : err);
|
|
105
113
|
remoteClient = undefined;
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
|
-
// Log storage state
|
|
109
|
-
const stores = storage.getStores();
|
|
116
|
+
// Log storage state for debugging
|
|
110
117
|
console.log("[createWebWallet] Storage state:", {
|
|
111
118
|
activeKey: storage.getActiveStore(),
|
|
112
|
-
backups: storage.getBackupStores(),
|
|
113
|
-
conflictingActives: storage.getConflictingStores(),
|
|
119
|
+
backups: storage.getBackupStores().length,
|
|
120
|
+
conflictingActives: storage.getConflictingStores().length,
|
|
114
121
|
isActiveEnabled: storage.isActiveEnabled,
|
|
115
|
-
allStores: stores.map((s) => ({
|
|
116
|
-
name: s.storageName,
|
|
117
|
-
key: s.storageIdentityKey.slice(0, 16) + "...",
|
|
118
|
-
})),
|
|
119
122
|
});
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
let backupStores = storage.getBackupStores();
|
|
123
|
-
if (conflictingStores.length > 0) {
|
|
123
|
+
// Handle conflicting actives - must resolve before wallet can function
|
|
124
|
+
if (storage.getConflictingStores().length > 0) {
|
|
124
125
|
const localKey = storage.getActiveStore();
|
|
125
126
|
console.log("[createWebWallet] Resolving conflicting actives...");
|
|
126
127
|
try {
|
|
@@ -131,40 +132,50 @@ export async function createWebWallet(config) {
|
|
|
131
132
|
console.log("[createWebWallet] Conflict resolution complete");
|
|
132
133
|
}
|
|
133
134
|
catch (err) {
|
|
134
|
-
console.log("[createWebWallet] Conflict resolution failed:", err instanceof Error ? err.message : err);
|
|
135
|
-
// FALLBACK: If conflict resolution fails, operate in local-only mode
|
|
136
|
-
// This allows the wallet to function even when remote sync is broken
|
|
137
|
-
console.log("[createWebWallet] Falling back to local-only mode (remote disabled)");
|
|
138
|
-
// Recreate storage manager with only local storage to clear conflicts
|
|
139
|
-
storage = new WalletStorageManager(identityPubKey, localStorage, []);
|
|
140
|
-
await storage.makeAvailable();
|
|
141
|
-
// Update the wallet's storage reference
|
|
142
|
-
underlyingWallet.storage = storage;
|
|
135
|
+
console.log("[createWebWallet] Conflict resolution failed, falling back to local-only:", err instanceof Error ? err.message : err);
|
|
143
136
|
remoteClient = undefined;
|
|
144
|
-
// Refresh conflict state
|
|
145
|
-
conflictingStores = storage.getConflictingStores();
|
|
146
|
-
backupStores = storage.getBackupStores();
|
|
147
|
-
console.log("[createWebWallet] Local-only mode active, isActiveEnabled:", storage.isActiveEnabled);
|
|
148
137
|
}
|
|
149
138
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
139
|
+
// Helper to sync to remote backup using public updateBackups API
|
|
140
|
+
const syncToBackup = async (context) => {
|
|
141
|
+
if (storage.getBackupStores().length > 0) {
|
|
142
|
+
await storage.updateBackups(undefined, (msg) => {
|
|
143
|
+
console.log(`[createWebWallet] ${context}:`, msg);
|
|
144
|
+
return msg;
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
// 8. Intercept createAction/signAction to sync after immediate broadcasts
|
|
149
|
+
// With acceptDelayedBroadcast: false, broadcasts happen synchronously and
|
|
150
|
+
// bypass the monitor's onTransactionBroadcasted callback. We detect broadcasts
|
|
151
|
+
// by checking for txid in the result and sync to backup immediately.
|
|
152
|
+
if (remoteClient) {
|
|
153
|
+
const originalCreateAction = underlyingWallet.createAction.bind(underlyingWallet);
|
|
154
|
+
underlyingWallet.createAction = async (args) => {
|
|
155
|
+
const result = await originalCreateAction(args);
|
|
156
|
+
if (result.txid) {
|
|
157
|
+
console.log("[createWebWallet] Broadcast detected in createAction:", result.txid);
|
|
158
|
+
syncToBackup("Backup after createAction").catch((err) => {
|
|
159
|
+
console.warn("[createWebWallet] Failed to sync after createAction:", err);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
};
|
|
164
|
+
const originalSignAction = underlyingWallet.signAction.bind(underlyingWallet);
|
|
165
|
+
underlyingWallet.signAction = async (args) => {
|
|
166
|
+
const result = await originalSignAction(args);
|
|
167
|
+
if (result.txid) {
|
|
168
|
+
console.log("[createWebWallet] Broadcast detected in signAction:", result.txid);
|
|
169
|
+
syncToBackup("Backup after signAction").catch((err) => {
|
|
170
|
+
console.warn("[createWebWallet] Failed to sync after signAction:", err);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return result;
|
|
174
|
+
};
|
|
164
175
|
}
|
|
165
|
-
//
|
|
176
|
+
// 9. Wrap with permissions manager
|
|
166
177
|
const wallet = new WalletPermissionsManager(underlyingWallet, adminOriginator, permissionsConfig);
|
|
167
|
-
//
|
|
178
|
+
// 10. Create monitor (not started - consumer calls startTasks() when ready)
|
|
168
179
|
const monitor = new Monitor({
|
|
169
180
|
chain,
|
|
170
181
|
services: oneSatServices,
|
|
@@ -178,26 +189,20 @@ export async function createWebWallet(config) {
|
|
|
178
189
|
});
|
|
179
190
|
monitor.addDefaultTasks();
|
|
180
191
|
console.log("[createWebWallet] Monitor created with tasks:", monitor["_tasks"].map((t) => t.name));
|
|
181
|
-
//
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
await storage.updateBackups(undefined, (msg) => {
|
|
185
|
-
console.log(`[Monitor] ${context}:`, msg);
|
|
186
|
-
return msg;
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
// 10. Wire up monitor callbacks - sync to remote first, then call user callbacks
|
|
192
|
+
// 11. Wire up monitor callbacks - sync to remote first, then call user callbacks
|
|
193
|
+
// Note: For delayed broadcasts, the monitor triggers these. For immediate broadcasts,
|
|
194
|
+
// the interception in step 8 handles the sync, but these still fire for the user callback.
|
|
191
195
|
monitor.onTransactionBroadcasted = async (result) => {
|
|
192
|
-
console.log("[
|
|
196
|
+
console.log("[createWebWallet] Monitor detected broadcast:", result.txid);
|
|
193
197
|
// Sync to remote backup first (if connected)
|
|
198
|
+
// Note: For immediate broadcasts, step 8 already synced, but this is harmless
|
|
194
199
|
if (remoteClient) {
|
|
195
200
|
try {
|
|
196
|
-
await syncToBackup("Backup after broadcast");
|
|
197
|
-
console.log("[
|
|
201
|
+
await syncToBackup("Backup after monitor broadcast");
|
|
202
|
+
console.log("[createWebWallet] Synced to backup after monitor broadcast");
|
|
198
203
|
}
|
|
199
204
|
catch (err) {
|
|
200
|
-
console.warn("[
|
|
205
|
+
console.warn("[createWebWallet] Failed to sync after monitor broadcast:", err);
|
|
201
206
|
}
|
|
202
207
|
}
|
|
203
208
|
// Then call user callback (if provided)
|
|
@@ -206,20 +211,20 @@ export async function createWebWallet(config) {
|
|
|
206
211
|
config.onTransactionBroadcasted(result.txid);
|
|
207
212
|
}
|
|
208
213
|
catch (err) {
|
|
209
|
-
console.warn("[
|
|
214
|
+
console.warn("[createWebWallet] User callback error after broadcast:", err);
|
|
210
215
|
}
|
|
211
216
|
}
|
|
212
217
|
};
|
|
213
218
|
monitor.onTransactionProven = async (status) => {
|
|
214
|
-
console.log("[
|
|
219
|
+
console.log("[createWebWallet] Transaction proven:", status.txid, "block", status.blockHeight);
|
|
215
220
|
// Sync to remote backup first (if connected)
|
|
216
221
|
if (remoteClient) {
|
|
217
222
|
try {
|
|
218
223
|
await syncToBackup("Backup after confirmation");
|
|
219
|
-
console.log("[
|
|
224
|
+
console.log("[createWebWallet] Synced to backup after confirmation");
|
|
220
225
|
}
|
|
221
226
|
catch (err) {
|
|
222
|
-
console.warn("[
|
|
227
|
+
console.warn("[createWebWallet] Failed to sync after confirmation:", err);
|
|
223
228
|
}
|
|
224
229
|
}
|
|
225
230
|
// Then call user callback (if provided)
|
|
@@ -228,17 +233,17 @@ export async function createWebWallet(config) {
|
|
|
228
233
|
config.onTransactionProven(status.txid, status.blockHeight);
|
|
229
234
|
}
|
|
230
235
|
catch (err) {
|
|
231
|
-
console.warn("[
|
|
236
|
+
console.warn("[createWebWallet] User callback error after proven:", err);
|
|
232
237
|
}
|
|
233
238
|
}
|
|
234
239
|
};
|
|
235
|
-
//
|
|
240
|
+
// 12. Create cleanup function
|
|
236
241
|
const destroy = async () => {
|
|
237
242
|
monitor.stopTasks();
|
|
238
243
|
await monitor.destroy();
|
|
239
244
|
await underlyingWallet.destroy();
|
|
240
245
|
};
|
|
241
|
-
//
|
|
246
|
+
// 13. Create fullSync function if remote storage is connected
|
|
242
247
|
const fullSyncFn = remoteClient
|
|
243
248
|
? async (onProgress) => {
|
|
244
249
|
return fullSync({
|