@1sat/wallet-toolbox 0.0.38 → 0.0.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.
@@ -72,84 +72,79 @@ 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. Create storage manager (local-only initially)
76
- let storage = new WalletStorageManager(identityPubKey, localStorage);
75
+ // 4. Create storage manager with local-only storage initially (empty backups)
76
+ const storage = new WalletStorageManager(identityPubKey, localStorage, []);
77
77
  await storage.makeAvailable();
78
- // Track remote client for fullSync
79
- let remoteClient;
80
- // 5. Create the underlying Wallet
78
+ // 5. Create the underlying Wallet FIRST (needed for StorageClient signing)
81
79
  const underlyingWallet = new Wallet({
82
80
  chain,
83
81
  keyDeriver,
84
82
  storage,
85
83
  services: oneSatServices,
86
84
  });
87
- // 6. Attempt remote storage connection if URL provided
85
+ // 6. Attempt remote storage connection AFTER wallet exists
86
+ let remoteClient;
88
87
  if (config.remoteStorageUrl) {
89
88
  console.log(`[createWebWallet] Attempting remote storage connection to ${config.remoteStorageUrl}`);
90
89
  try {
90
+ // Create StorageClient with the REAL wallet (not a temp wallet)
91
+ // StorageClient captures the wallet at construction for signing requests
91
92
  remoteClient = new StorageClient(underlyingWallet, config.remoteStorageUrl);
92
93
  const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Remote storage connection timeout")), DEFAULT_REMOTE_STORAGE_TIMEOUT));
93
94
  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;
95
+ // Add remote storage to the existing storage manager using public API
96
+ await storage.addWalletStorageProvider(remoteClient);
143
97
  console.log("[createWebWallet] Remote storage connected successfully");
144
98
  }
145
99
  catch (err) {
146
100
  console.log("[createWebWallet] Remote storage connection failed:", err instanceof Error ? err.message : err);
147
- // Graceful degradation - continue with local only
101
+ remoteClient = undefined;
102
+ }
103
+ }
104
+ // Log storage state using public APIs
105
+ const stores = storage.getStores();
106
+ console.log("[createWebWallet] Storage state:", {
107
+ activeKey: storage.getActiveStore(),
108
+ backups: storage.getBackupStores(),
109
+ conflictingActives: storage.getConflictingStores(),
110
+ isActiveEnabled: storage.isActiveEnabled,
111
+ allStores: stores.map(s => ({ name: s.storageName, key: s.storageIdentityKey.slice(0, 16) + "..." })),
112
+ });
113
+ // 7. Handle conflicting actives or sync to backups
114
+ const conflictingStores = storage.getConflictingStores();
115
+ const backupStores = storage.getBackupStores();
116
+ if (conflictingStores.length > 0) {
117
+ const localKey = storage.getActiveStore();
118
+ console.log("[createWebWallet] Resolving conflicting actives...");
119
+ try {
120
+ await storage.setActive(localKey, (msg) => {
121
+ console.log("[createWebWallet] Conflict resolution:", msg);
122
+ return msg;
123
+ });
124
+ console.log("[createWebWallet] Conflict resolution complete");
148
125
  }
126
+ catch (err) {
127
+ console.log("[createWebWallet] Conflict resolution failed:", err instanceof Error ? err.message : err);
128
+ }
129
+ }
130
+ else if (backupStores.length > 0) {
131
+ // No conflicts - push local state to remote backup (fire-and-forget)
132
+ console.log("[createWebWallet] Pushing local state to remote backup...");
133
+ storage
134
+ .updateBackups(undefined, (msg) => {
135
+ console.log("[createWebWallet] Backup:", msg);
136
+ return msg;
137
+ })
138
+ .then(() => {
139
+ console.log("[createWebWallet] Backup complete");
140
+ })
141
+ .catch((err) => {
142
+ console.log("[createWebWallet] Backup failed:", err instanceof Error ? err.message : err);
143
+ });
149
144
  }
150
- // 7. Wrap with permissions manager
145
+ // 8. Wrap with permissions manager
151
146
  const wallet = new WalletPermissionsManager(underlyingWallet, adminOriginator, permissionsConfig);
152
- // 8. Create monitor (not started - consumer calls startTasks() when ready)
147
+ // 9. Create monitor (not started - consumer calls startTasks() when ready)
153
148
  const monitor = new Monitor({
154
149
  chain,
155
150
  services: oneSatServices,
@@ -162,17 +157,16 @@ export async function createWebWallet(config) {
162
157
  unprovenAttemptsLimitMain: 144,
163
158
  });
164
159
  monitor.addDefaultTasks();
165
- // Helper to sync to remote backup using updateBackups (same as initialization)
160
+ // Helper to sync to remote backup using public updateBackups API
166
161
  const syncToBackup = async (context) => {
167
- const storageAny = storage;
168
- if (storageAny._backups?.length && storageAny.updateBackups) {
169
- await storageAny.updateBackups(undefined, (msg) => {
162
+ if (storage.getBackupStores().length > 0) {
163
+ await storage.updateBackups(undefined, (msg) => {
170
164
  console.log(`[Monitor] ${context}:`, msg);
171
165
  return msg;
172
166
  });
173
167
  }
174
168
  };
175
- // 9. Wire up monitor callbacks - sync to remote first, then call user callbacks
169
+ // 10. Wire up monitor callbacks - sync to remote first, then call user callbacks
176
170
  monitor.onTransactionBroadcasted = async (result) => {
177
171
  console.log("[Monitor] Transaction broadcasted:", result.txid);
178
172
  // Sync to remote backup first (if connected)
@@ -217,13 +211,13 @@ export async function createWebWallet(config) {
217
211
  }
218
212
  }
219
213
  };
220
- // 10. Create cleanup function
214
+ // 11. Create cleanup function
221
215
  const destroy = async () => {
222
216
  monitor.stopTasks();
223
217
  await monitor.destroy();
224
218
  await underlyingWallet.destroy();
225
219
  };
226
- // 11. Create fullSync function if remote storage is connected
220
+ // 12. Create fullSync function if remote storage is connected
227
221
  const fullSyncFn = remoteClient
228
222
  ? async (onProgress) => {
229
223
  return fullSync({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1sat/wallet-toolbox",
3
- "version": "0.0.38",
3
+ "version": "0.0.40",
4
4
  "description": "BSV wallet library extending @bsv/wallet-toolbox with 1Sat Ordinals protocol support",
5
5
  "author": "1Sat Team",
6
6
  "license": "MIT",