@1sat/wallet-toolbox 0.0.38 → 0.0.39
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 +75 -72
- package/package.json +1 -1
package/dist/wallet/factory.js
CHANGED
|
@@ -72,84 +72,88 @@ export async function createWebWallet(config) {
|
|
|
72
72
|
storageOptions.feeModel = feeModel;
|
|
73
73
|
const localStorage = new StorageIdb(storageOptions);
|
|
74
74
|
await localStorage.migrate(DEFAULT_DATABASE_NAME, identityPubKey);
|
|
75
|
-
// 4.
|
|
76
|
-
let storage = new WalletStorageManager(identityPubKey, localStorage);
|
|
77
|
-
await storage.makeAvailable();
|
|
78
|
-
// Track remote client for fullSync
|
|
75
|
+
// 4. Attempt remote storage connection BEFORE creating Wallet (if URL provided)
|
|
79
76
|
let remoteClient;
|
|
80
|
-
// 5. Create the underlying Wallet
|
|
81
|
-
const underlyingWallet = new Wallet({
|
|
82
|
-
chain,
|
|
83
|
-
keyDeriver,
|
|
84
|
-
storage,
|
|
85
|
-
services: oneSatServices,
|
|
86
|
-
});
|
|
87
|
-
// 6. Attempt remote storage connection if URL provided
|
|
88
77
|
if (config.remoteStorageUrl) {
|
|
89
78
|
console.log(`[createWebWallet] Attempting remote storage connection to ${config.remoteStorageUrl}`);
|
|
90
79
|
try {
|
|
91
|
-
|
|
80
|
+
// Create a temporary wallet just for StorageClient auth
|
|
81
|
+
// StorageClient needs a wallet to sign requests
|
|
82
|
+
const tempStorage = new WalletStorageManager(identityPubKey, localStorage);
|
|
83
|
+
await tempStorage.makeAvailable();
|
|
84
|
+
const tempWallet = new Wallet({
|
|
85
|
+
chain,
|
|
86
|
+
keyDeriver,
|
|
87
|
+
storage: tempStorage,
|
|
88
|
+
services: oneSatServices,
|
|
89
|
+
});
|
|
90
|
+
remoteClient = new StorageClient(tempWallet, config.remoteStorageUrl);
|
|
92
91
|
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Remote storage connection timeout")), DEFAULT_REMOTE_STORAGE_TIMEOUT));
|
|
93
92
|
await Promise.race([remoteClient.makeAvailable(), timeoutPromise]);
|
|
94
|
-
// Remote connected - recreate storage manager with backup
|
|
95
|
-
storage = new WalletStorageManager(identityPubKey, localStorage, [
|
|
96
|
-
remoteClient,
|
|
97
|
-
]);
|
|
98
|
-
await storage.makeAvailable();
|
|
99
|
-
// Check for conflicting actives and resolve if needed
|
|
100
|
-
const storageAny = storage;
|
|
101
|
-
console.log("[createWebWallet] Storage state:", {
|
|
102
|
-
activeKey: storageAny._active?.settings?.storageIdentityKey,
|
|
103
|
-
backups: storageAny._backups?.map((b) => b.settings?.storageIdentityKey),
|
|
104
|
-
conflictingActives: storageAny._conflictingActives?.map((c) => c.settings?.storageIdentityKey),
|
|
105
|
-
});
|
|
106
|
-
// Only resolve actual conflicts, don't treat backups as conflicts
|
|
107
|
-
if (storageAny._conflictingActives &&
|
|
108
|
-
storageAny._conflictingActives.length > 0) {
|
|
109
|
-
const localKey = storageAny._active?.settings?.storageIdentityKey;
|
|
110
|
-
if (localKey && storageAny.setActive) {
|
|
111
|
-
console.log("[createWebWallet] Resolving conflicting actives...");
|
|
112
|
-
try {
|
|
113
|
-
await storageAny.setActive(localKey, (msg) => {
|
|
114
|
-
console.log("[createWebWallet] Conflict resolution:", msg);
|
|
115
|
-
return msg;
|
|
116
|
-
});
|
|
117
|
-
console.log("[createWebWallet] Conflict resolution complete");
|
|
118
|
-
}
|
|
119
|
-
catch (err) {
|
|
120
|
-
console.log("[createWebWallet] Conflict resolution failed:", err instanceof Error ? err.message : err);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
else if (storageAny._backups &&
|
|
125
|
-
storageAny._backups.length > 0 &&
|
|
126
|
-
storageAny.updateBackups) {
|
|
127
|
-
// No conflicts - push local state to remote backup (fire-and-forget)
|
|
128
|
-
console.log("[createWebWallet] Pushing local state to remote backup...");
|
|
129
|
-
storageAny
|
|
130
|
-
.updateBackups(undefined, (msg) => {
|
|
131
|
-
console.log("[createWebWallet] Backup:", msg);
|
|
132
|
-
return msg;
|
|
133
|
-
})
|
|
134
|
-
.then(() => {
|
|
135
|
-
console.log("[createWebWallet] Backup complete");
|
|
136
|
-
})
|
|
137
|
-
.catch((err) => {
|
|
138
|
-
console.log("[createWebWallet] Backup failed:", err instanceof Error ? err.message : err);
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
// Update wallet's storage reference
|
|
142
|
-
underlyingWallet._storage = storage;
|
|
143
93
|
console.log("[createWebWallet] Remote storage connected successfully");
|
|
94
|
+
// Clean up temp wallet (don't destroy storage - we'll reuse localStorage)
|
|
95
|
+
await tempWallet.destroy();
|
|
144
96
|
}
|
|
145
97
|
catch (err) {
|
|
146
98
|
console.log("[createWebWallet] Remote storage connection failed:", err instanceof Error ? err.message : err);
|
|
147
|
-
|
|
99
|
+
remoteClient = undefined;
|
|
148
100
|
}
|
|
149
101
|
}
|
|
150
|
-
//
|
|
102
|
+
// 5. Create storage manager with final configuration (local + remote if connected)
|
|
103
|
+
const backups = remoteClient ? [remoteClient] : [];
|
|
104
|
+
const storage = new WalletStorageManager(identityPubKey, localStorage, backups);
|
|
105
|
+
await storage.makeAvailable();
|
|
106
|
+
// Log storage state using public APIs
|
|
107
|
+
const stores = storage.getStores();
|
|
108
|
+
console.log("[createWebWallet] Storage state:", {
|
|
109
|
+
activeKey: storage.getActiveStore(),
|
|
110
|
+
backups: storage.getBackupStores(),
|
|
111
|
+
conflictingActives: storage.getConflictingStores(),
|
|
112
|
+
isActiveEnabled: storage.isActiveEnabled,
|
|
113
|
+
allStores: stores.map(s => ({ name: s.storageName, key: s.storageIdentityKey.slice(0, 16) + "..." })),
|
|
114
|
+
});
|
|
115
|
+
// 6. Handle conflicting actives or push to backups
|
|
116
|
+
const conflictingStores = storage.getConflictingStores();
|
|
117
|
+
const backupStores = storage.getBackupStores();
|
|
118
|
+
if (conflictingStores.length > 0) {
|
|
119
|
+
const localKey = storage.getActiveStore();
|
|
120
|
+
console.log("[createWebWallet] Resolving conflicting actives...");
|
|
121
|
+
try {
|
|
122
|
+
await storage.setActive(localKey, (msg) => {
|
|
123
|
+
console.log("[createWebWallet] Conflict resolution:", msg);
|
|
124
|
+
return msg;
|
|
125
|
+
});
|
|
126
|
+
console.log("[createWebWallet] Conflict resolution complete");
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
console.log("[createWebWallet] Conflict resolution failed:", err instanceof Error ? err.message : err);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else if (backupStores.length > 0) {
|
|
133
|
+
// No conflicts - push local state to remote backup (fire-and-forget)
|
|
134
|
+
console.log("[createWebWallet] Pushing local state to remote backup...");
|
|
135
|
+
storage
|
|
136
|
+
.updateBackups(undefined, (msg) => {
|
|
137
|
+
console.log("[createWebWallet] Backup:", msg);
|
|
138
|
+
return msg;
|
|
139
|
+
})
|
|
140
|
+
.then(() => {
|
|
141
|
+
console.log("[createWebWallet] Backup complete");
|
|
142
|
+
})
|
|
143
|
+
.catch((err) => {
|
|
144
|
+
console.log("[createWebWallet] Backup failed:", err instanceof Error ? err.message : err);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
// 7. Create the underlying Wallet with the FINAL storage configuration
|
|
148
|
+
const underlyingWallet = new Wallet({
|
|
149
|
+
chain,
|
|
150
|
+
keyDeriver,
|
|
151
|
+
storage,
|
|
152
|
+
services: oneSatServices,
|
|
153
|
+
});
|
|
154
|
+
// 8. Wrap with permissions manager
|
|
151
155
|
const wallet = new WalletPermissionsManager(underlyingWallet, adminOriginator, permissionsConfig);
|
|
152
|
-
//
|
|
156
|
+
// 9. Create monitor (not started - consumer calls startTasks() when ready)
|
|
153
157
|
const monitor = new Monitor({
|
|
154
158
|
chain,
|
|
155
159
|
services: oneSatServices,
|
|
@@ -162,17 +166,16 @@ export async function createWebWallet(config) {
|
|
|
162
166
|
unprovenAttemptsLimitMain: 144,
|
|
163
167
|
});
|
|
164
168
|
monitor.addDefaultTasks();
|
|
165
|
-
// Helper to sync to remote backup using updateBackups
|
|
169
|
+
// Helper to sync to remote backup using public updateBackups API
|
|
166
170
|
const syncToBackup = async (context) => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
await storageAny.updateBackups(undefined, (msg) => {
|
|
171
|
+
if (storage.getBackupStores().length > 0) {
|
|
172
|
+
await storage.updateBackups(undefined, (msg) => {
|
|
170
173
|
console.log(`[Monitor] ${context}:`, msg);
|
|
171
174
|
return msg;
|
|
172
175
|
});
|
|
173
176
|
}
|
|
174
177
|
};
|
|
175
|
-
//
|
|
178
|
+
// 10. Wire up monitor callbacks - sync to remote first, then call user callbacks
|
|
176
179
|
monitor.onTransactionBroadcasted = async (result) => {
|
|
177
180
|
console.log("[Monitor] Transaction broadcasted:", result.txid);
|
|
178
181
|
// Sync to remote backup first (if connected)
|
|
@@ -217,13 +220,13 @@ export async function createWebWallet(config) {
|
|
|
217
220
|
}
|
|
218
221
|
}
|
|
219
222
|
};
|
|
220
|
-
//
|
|
223
|
+
// 11. Create cleanup function
|
|
221
224
|
const destroy = async () => {
|
|
222
225
|
monitor.stopTasks();
|
|
223
226
|
await monitor.destroy();
|
|
224
227
|
await underlyingWallet.destroy();
|
|
225
228
|
};
|
|
226
|
-
//
|
|
229
|
+
// 12. Create fullSync function if remote storage is connected
|
|
227
230
|
const fullSyncFn = remoteClient
|
|
228
231
|
? async (onProgress) => {
|
|
229
232
|
return fullSync({
|