@1sat/wallet-toolbox 0.0.37 → 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.
@@ -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. Create storage manager (local-only initially)
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
- remoteClient = new StorageClient(underlyingWallet, config.remoteStorageUrl);
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
- // Graceful degradation - continue with local only
99
+ remoteClient = undefined;
148
100
  }
149
101
  }
150
- // 7. Wrap with permissions manager
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
- // 8. Create monitor (not started - consumer calls startTasks() when ready)
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,14 +166,22 @@ export async function createWebWallet(config) {
162
166
  unprovenAttemptsLimitMain: 144,
163
167
  });
164
168
  monitor.addDefaultTasks();
165
- // 9. Wire up monitor callbacks - sync to remote first, then call user callbacks
169
+ // Helper to sync to remote backup using public updateBackups API
170
+ const syncToBackup = async (context) => {
171
+ if (storage.getBackupStores().length > 0) {
172
+ await storage.updateBackups(undefined, (msg) => {
173
+ console.log(`[Monitor] ${context}:`, msg);
174
+ return msg;
175
+ });
176
+ }
177
+ };
178
+ // 10. Wire up monitor callbacks - sync to remote first, then call user callbacks
166
179
  monitor.onTransactionBroadcasted = async (result) => {
167
180
  console.log("[Monitor] Transaction broadcasted:", result.txid);
168
181
  // Sync to remote backup first (if connected)
169
182
  if (remoteClient) {
170
183
  try {
171
- const auth = await storage.getAuth();
172
- await storage.syncToWriter(auth, remoteClient);
184
+ await syncToBackup("Backup after broadcast");
173
185
  console.log("[Monitor] Synced to backup after broadcast");
174
186
  }
175
187
  catch (err) {
@@ -191,8 +203,7 @@ export async function createWebWallet(config) {
191
203
  // Sync to remote backup first (if connected)
192
204
  if (remoteClient) {
193
205
  try {
194
- const auth = await storage.getAuth();
195
- await storage.syncToWriter(auth, remoteClient);
206
+ await syncToBackup("Backup after confirmation");
196
207
  console.log("[Monitor] Synced to backup after confirmation");
197
208
  }
198
209
  catch (err) {
@@ -209,13 +220,13 @@ export async function createWebWallet(config) {
209
220
  }
210
221
  }
211
222
  };
212
- // 10. Create cleanup function
223
+ // 11. Create cleanup function
213
224
  const destroy = async () => {
214
225
  monitor.stopTasks();
215
226
  await monitor.destroy();
216
227
  await underlyingWallet.destroy();
217
228
  };
218
- // 11. Create fullSync function if remote storage is connected
229
+ // 12. Create fullSync function if remote storage is connected
219
230
  const fullSyncFn = remoteClient
220
231
  ? async (onProgress) => {
221
232
  return fullSync({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1sat/wallet-toolbox",
3
- "version": "0.0.37",
3
+ "version": "0.0.39",
4
4
  "description": "BSV wallet library extending @bsv/wallet-toolbox with 1Sat Ordinals protocol support",
5
5
  "author": "1Sat Team",
6
6
  "license": "MIT",
@@ -44,7 +44,7 @@
44
44
  "fflate": "^0.8.2"
45
45
  },
46
46
  "peerDependencies": {
47
- "@bsv/wallet-toolbox-mobile": "npm:@bopen-io/wallet-toolbox-mobile@^1.7.20-idb-fix.17"
47
+ "@bsv/wallet-toolbox-mobile": "npm:@bopen-io/wallet-toolbox-mobile@^1.7.20-idb-fix.19"
48
48
  },
49
49
  "peerDependenciesMeta": {
50
50
  "@bsv/wallet-toolbox-mobile": {
@@ -54,7 +54,7 @@
54
54
  "devDependencies": {
55
55
  "@biomejs/biome": "^1.9.4",
56
56
  "@bsv/wallet-toolbox": "npm:@bopen-io/wallet-toolbox@^1.7.20-idb-fix.17",
57
- "@bsv/wallet-toolbox-mobile": "npm:@bopen-io/wallet-toolbox-mobile@^1.7.20-idb-fix.17",
57
+ "@bsv/wallet-toolbox-mobile": "npm:@bopen-io/wallet-toolbox-mobile@^1.7.20-idb-fix.19",
58
58
  "@types/bun": "^1.3.4",
59
59
  "@types/chrome": "^0.1.32",
60
60
  "typescript": "^5.9.3"