@1sat/wallet-toolbox 0.0.39 → 0.0.41

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,37 +72,35 @@ 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. Attempt remote storage connection BEFORE creating Wallet (if URL provided)
75
+ // 4. Create storage manager with local-only storage initially (empty backups)
76
+ const storage = new WalletStorageManager(identityPubKey, localStorage, []);
77
+ await storage.makeAvailable();
78
+ // 5. Create the underlying Wallet FIRST (needed for StorageClient signing)
79
+ const underlyingWallet = new Wallet({
80
+ chain,
81
+ keyDeriver,
82
+ storage,
83
+ services: oneSatServices,
84
+ });
85
+ // 6. Attempt remote storage connection AFTER wallet exists
76
86
  let remoteClient;
77
87
  if (config.remoteStorageUrl) {
78
88
  console.log(`[createWebWallet] Attempting remote storage connection to ${config.remoteStorageUrl}`);
79
89
  try {
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);
90
+ // Create StorageClient with the REAL wallet (not a temp wallet)
91
+ // StorageClient captures the wallet at construction for signing requests
92
+ remoteClient = new StorageClient(underlyingWallet, config.remoteStorageUrl);
91
93
  const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Remote storage connection timeout")), DEFAULT_REMOTE_STORAGE_TIMEOUT));
92
94
  await Promise.race([remoteClient.makeAvailable(), timeoutPromise]);
95
+ // Add remote storage to the existing storage manager using public API
96
+ await storage.addWalletStorageProvider(remoteClient);
93
97
  console.log("[createWebWallet] Remote storage connected successfully");
94
- // Clean up temp wallet (don't destroy storage - we'll reuse localStorage)
95
- await tempWallet.destroy();
96
98
  }
97
99
  catch (err) {
98
100
  console.log("[createWebWallet] Remote storage connection failed:", err instanceof Error ? err.message : err);
99
101
  remoteClient = undefined;
100
102
  }
101
103
  }
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
104
  // Log storage state using public APIs
107
105
  const stores = storage.getStores();
108
106
  console.log("[createWebWallet] Storage state:", {
@@ -112,7 +110,7 @@ export async function createWebWallet(config) {
112
110
  isActiveEnabled: storage.isActiveEnabled,
113
111
  allStores: stores.map(s => ({ name: s.storageName, key: s.storageIdentityKey.slice(0, 16) + "..." })),
114
112
  });
115
- // 6. Handle conflicting actives or push to backups
113
+ // 7. Handle conflicting actives or sync to backups
116
114
  const conflictingStores = storage.getConflictingStores();
117
115
  const backupStores = storage.getBackupStores();
118
116
  if (conflictingStores.length > 0) {
@@ -144,13 +142,6 @@ export async function createWebWallet(config) {
144
142
  console.log("[createWebWallet] Backup failed:", err instanceof Error ? err.message : err);
145
143
  });
146
144
  }
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
145
  // 8. Wrap with permissions manager
155
146
  const wallet = new WalletPermissionsManager(underlyingWallet, adminOriginator, permissionsConfig);
156
147
  // 9. Create monitor (not started - consumer calls startTasks() when ready)
@@ -5,6 +5,7 @@
5
5
  * This is a deliberate user action (not automatic) for recovering from sync issues.
6
6
  */
7
7
  import { createSyncMap } from "@bsv/wallet-toolbox-mobile/out/src/storage/schema/entities/EntityBase.js";
8
+ import { EntitySyncState } from "@bsv/wallet-toolbox-mobile/out/src/storage/schema/entities/EntitySyncState.js";
8
9
  /**
9
10
  * Perform a full sync with the remote backup server.
10
11
  *
@@ -28,14 +29,34 @@ import { createSyncMap } from "@bsv/wallet-toolbox-mobile/out/src/storage/schema
28
29
  */
29
30
  export async function fullSync(options) {
30
31
  const { storage, remoteStorage, identityKey, onProgress } = options;
31
- // Step 1: Push local data to remote
32
+ // Step 1: Push ALL local data to remote (bypassing timestamp filter)
32
33
  onProgress?.("pushing", "Pushing local data to remote...");
33
- const auth = await storage.getAuth();
34
- const pushResult = await storage.syncToWriter(auth, remoteStorage);
35
- onProgress?.("pushing", `Pushed ${pushResult.inserts} inserts, ${pushResult.updates} updates`);
34
+ const localSettings = storage.getSettings();
35
+ const remoteSettings = await remoteStorage.makeAvailable();
36
+ let pushInserts = 0;
37
+ let pushUpdates = 0;
38
+ let chunkCount = 0;
39
+ for (;;) {
40
+ // Get sync state from remote for proper offsets
41
+ const ss = await EntitySyncState.fromStorage(remoteStorage, identityKey, localSettings);
42
+ const args = ss.makeRequestSyncChunkArgs(identityKey, remoteSettings.storageIdentityKey);
43
+ // KEY: Override since to undefined - includes ALL data regardless of timestamp
44
+ args.since = undefined;
45
+ // Get chunk from local storage
46
+ const chunk = await storage.runAsSync(async (sync) => sync.getSyncChunk(args));
47
+ // Send chunk to remote
48
+ const result = await remoteStorage.processSyncChunk(args, chunk);
49
+ pushInserts += result.inserts;
50
+ pushUpdates += result.updates;
51
+ chunkCount++;
52
+ onProgress?.("pushing", `Chunk ${chunkCount}: ${result.inserts} inserts, ${result.updates} updates`);
53
+ if (result.done)
54
+ break;
55
+ }
56
+ onProgress?.("pushing", `Pushed ${pushInserts} inserts, ${pushUpdates} updates`);
36
57
  // Step 2: Reset sync state to force full pull
37
58
  onProgress?.("resetting", "Resetting sync state...");
38
- const remoteSettings = remoteStorage.getSettings();
59
+ const auth = await storage.getAuth();
39
60
  await storage.runAsStorageProvider(async (active) => {
40
61
  const syncStates = await active.findSyncStates({
41
62
  partial: {
@@ -63,7 +84,7 @@ export async function fullSync(options) {
63
84
  // Step 4: Complete
64
85
  onProgress?.("complete", "Full sync complete");
65
86
  return {
66
- pushed: { inserts: pushResult.inserts, updates: pushResult.updates },
87
+ pushed: { inserts: pushInserts, updates: pushUpdates },
67
88
  pulled: { inserts: pullResult.inserts, updates: pullResult.updates },
68
89
  };
69
90
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1sat/wallet-toolbox",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "description": "BSV wallet library extending @bsv/wallet-toolbox with 1Sat Ordinals protocol support",
5
5
  "author": "1Sat Team",
6
6
  "license": "MIT",