@1sat/wallet-toolbox 0.0.18 → 0.0.20
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.d.ts +4 -1
- package/dist/wallet/factory.js +42 -20
- package/dist/wallet/fullSync.d.ts +53 -0
- package/dist/wallet/fullSync.js +69 -0
- package/dist/wallet/index.d.ts +1 -0
- package/dist/wallet/index.js +1 -0
- package/package.json +4 -4
package/dist/wallet/factory.d.ts
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* (browser extension) and 1sat-website (React app).
|
|
6
6
|
*/
|
|
7
7
|
import { PrivateKey } from "@bsv/sdk";
|
|
8
|
-
import {
|
|
8
|
+
import { Monitor, type PermissionsManagerConfig, WalletPermissionsManager } from "@bsv/wallet-toolbox-mobile/out/src/index.client.js";
|
|
9
9
|
import { OneSatServices } from "../services/OneSatServices";
|
|
10
|
+
import { type FullSyncResult } from "./fullSync";
|
|
10
11
|
type Chain = "main" | "test";
|
|
11
12
|
/**
|
|
12
13
|
* Configuration for creating a web wallet.
|
|
@@ -40,6 +41,8 @@ export interface WebWalletResult {
|
|
|
40
41
|
monitor: Monitor;
|
|
41
42
|
/** Cleanup function - stops monitor, destroys wallet */
|
|
42
43
|
destroy: () => Promise<void>;
|
|
44
|
+
/** Full sync with remote backup (only available if remoteStorageUrl was provided and connected) */
|
|
45
|
+
fullSync?: () => Promise<FullSyncResult>;
|
|
43
46
|
}
|
|
44
47
|
/**
|
|
45
48
|
* Create a web wallet with storage, services, permissions, and monitor.
|
package/dist/wallet/factory.js
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* (browser extension) and 1sat-website (React app).
|
|
6
6
|
*/
|
|
7
7
|
import { KeyDeriver, PrivateKey } from "@bsv/sdk";
|
|
8
|
-
import {
|
|
8
|
+
import { Monitor, Services, StorageClient, StorageIdb, StorageProvider, Wallet, WalletPermissionsManager, WalletStorageManager, } from "@bsv/wallet-toolbox-mobile/out/src/index.client.js";
|
|
9
9
|
import { OneSatServices } from "../services/OneSatServices";
|
|
10
|
+
import { fullSync } from "./fullSync";
|
|
10
11
|
// Default database name for IndexedDB storage
|
|
11
12
|
const DEFAULT_DATABASE_NAME = "wallet";
|
|
12
13
|
// Default timeout for remote storage connection
|
|
@@ -74,6 +75,8 @@ export async function createWebWallet(config) {
|
|
|
74
75
|
// 4. Create storage manager (local-only initially)
|
|
75
76
|
let storage = new WalletStorageManager(identityPubKey, localStorage);
|
|
76
77
|
await storage.makeAvailable();
|
|
78
|
+
// Track remote client for fullSync
|
|
79
|
+
let remoteClient;
|
|
77
80
|
// 5. Create the underlying Wallet
|
|
78
81
|
const underlyingWallet = new Wallet({
|
|
79
82
|
chain,
|
|
@@ -85,7 +88,7 @@ export async function createWebWallet(config) {
|
|
|
85
88
|
if (config.remoteStorageUrl) {
|
|
86
89
|
console.log(`[createWebWallet] Attempting remote storage connection to ${config.remoteStorageUrl}`);
|
|
87
90
|
try {
|
|
88
|
-
|
|
91
|
+
remoteClient = new StorageClient(underlyingWallet, config.remoteStorageUrl);
|
|
89
92
|
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Remote storage connection timeout")), DEFAULT_REMOTE_STORAGE_TIMEOUT));
|
|
90
93
|
await Promise.race([remoteClient.makeAvailable(), timeoutPromise]);
|
|
91
94
|
// Remote connected - recreate storage manager with backup
|
|
@@ -97,36 +100,44 @@ export async function createWebWallet(config) {
|
|
|
97
100
|
const storageAny = storage;
|
|
98
101
|
console.log("[createWebWallet] Storage state:", {
|
|
99
102
|
activeKey: storageAny._active?.settings?.storageIdentityKey,
|
|
100
|
-
backups: storageAny._backups?.map(b => b.settings?.storageIdentityKey),
|
|
101
|
-
conflictingActives: storageAny._conflictingActives?.map(c => c.settings?.storageIdentityKey),
|
|
103
|
+
backups: storageAny._backups?.map((b) => b.settings?.storageIdentityKey),
|
|
104
|
+
conflictingActives: storageAny._conflictingActives?.map((c) => c.settings?.storageIdentityKey),
|
|
102
105
|
});
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (storageAny._backups && storageAny._backups.length > 0) {
|
|
107
|
-
console.log("[createWebWallet] Reclassifying backups as conflicts to pull remote data...");
|
|
108
|
-
storageAny._conflictingActives = storageAny._conflictingActives || [];
|
|
109
|
-
storageAny._conflictingActives.push(...storageAny._backups);
|
|
110
|
-
storageAny._backups = [];
|
|
111
|
-
}
|
|
112
|
-
// If there are conflicting actives (including reclassified backups), resolve by merging into local
|
|
113
|
-
// This is now blocking since setActive no longer holds IDB transactions during network calls
|
|
114
|
-
if (storageAny._conflictingActives && storageAny._conflictingActives.length > 0) {
|
|
106
|
+
// Only resolve actual conflicts, don't treat backups as conflicts
|
|
107
|
+
if (storageAny._conflictingActives &&
|
|
108
|
+
storageAny._conflictingActives.length > 0) {
|
|
115
109
|
const localKey = storageAny._active?.settings?.storageIdentityKey;
|
|
116
110
|
if (localKey && storageAny.setActive) {
|
|
117
|
-
console.log("[createWebWallet]
|
|
111
|
+
console.log("[createWebWallet] Resolving conflicting actives...");
|
|
118
112
|
try {
|
|
119
113
|
await storageAny.setActive(localKey, (msg) => {
|
|
120
|
-
console.log("[createWebWallet]
|
|
114
|
+
console.log("[createWebWallet] Conflict resolution:", msg);
|
|
121
115
|
return msg;
|
|
122
116
|
});
|
|
123
|
-
console.log("[createWebWallet]
|
|
117
|
+
console.log("[createWebWallet] Conflict resolution complete");
|
|
124
118
|
}
|
|
125
119
|
catch (err) {
|
|
126
|
-
console.log("[createWebWallet]
|
|
120
|
+
console.log("[createWebWallet] Conflict resolution failed:", err instanceof Error ? err.message : err);
|
|
127
121
|
}
|
|
128
122
|
}
|
|
129
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
|
+
}
|
|
130
141
|
// Update wallet's storage reference
|
|
131
142
|
underlyingWallet._storage = storage;
|
|
132
143
|
console.log("[createWebWallet] Remote storage connected successfully");
|
|
@@ -157,10 +168,21 @@ export async function createWebWallet(config) {
|
|
|
157
168
|
await monitor.destroy();
|
|
158
169
|
await underlyingWallet.destroy();
|
|
159
170
|
};
|
|
171
|
+
// 10. Create fullSync function if remote storage is connected
|
|
172
|
+
const fullSyncFn = remoteClient
|
|
173
|
+
? async () => {
|
|
174
|
+
return fullSync({
|
|
175
|
+
storage,
|
|
176
|
+
remoteStorage: remoteClient,
|
|
177
|
+
identityKey: identityPubKey,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
: undefined;
|
|
160
181
|
return {
|
|
161
182
|
wallet,
|
|
162
183
|
services: oneSatServices,
|
|
163
184
|
monitor,
|
|
164
185
|
destroy,
|
|
186
|
+
fullSync: fullSyncFn,
|
|
165
187
|
};
|
|
166
188
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full wallet synchronization with remote backup server.
|
|
3
|
+
*
|
|
4
|
+
* Performs a complete resync: push local → reset sync state → full pull from server.
|
|
5
|
+
* This is a deliberate user action (not automatic) for recovering from sync issues.
|
|
6
|
+
*/
|
|
7
|
+
import type { WalletStorageManager } from "@bsv/wallet-toolbox-mobile/out/src/index.client.js";
|
|
8
|
+
import type { sdk as mobileToolboxSdk } from "@bsv/wallet-toolbox-mobile/out/src/index.client.js";
|
|
9
|
+
type WalletStorageProvider = mobileToolboxSdk.WalletStorageProvider;
|
|
10
|
+
export type FullSyncStage = "pushing" | "resetting" | "pulling" | "complete";
|
|
11
|
+
export interface FullSyncOptions {
|
|
12
|
+
/** Local storage manager */
|
|
13
|
+
storage: WalletStorageManager;
|
|
14
|
+
/** Remote backup storage provider (StorageClient) */
|
|
15
|
+
remoteStorage: WalletStorageProvider;
|
|
16
|
+
/** Identity key for the wallet */
|
|
17
|
+
identityKey: string;
|
|
18
|
+
/** Optional progress callback */
|
|
19
|
+
onProgress?: (stage: FullSyncStage, message: string) => void;
|
|
20
|
+
}
|
|
21
|
+
export interface FullSyncResult {
|
|
22
|
+
pushed: {
|
|
23
|
+
inserts: number;
|
|
24
|
+
updates: number;
|
|
25
|
+
};
|
|
26
|
+
pulled: {
|
|
27
|
+
inserts: number;
|
|
28
|
+
updates: number;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Perform a full sync with the remote backup server.
|
|
33
|
+
*
|
|
34
|
+
* Steps:
|
|
35
|
+
* 1. Push all local data to remote backup
|
|
36
|
+
* 2. Clear local syncMap / reset sync state
|
|
37
|
+
* 3. Pull ALL data from server (not incremental)
|
|
38
|
+
* 4. Rebuild complete server→client ID mappings
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const result = await fullSync({
|
|
43
|
+
* storage,
|
|
44
|
+
* remoteStorage: remoteClient,
|
|
45
|
+
* identityKey: pubKey,
|
|
46
|
+
* onProgress: (stage, msg) => console.log(`[${stage}] ${msg}`)
|
|
47
|
+
* });
|
|
48
|
+
* console.log(`Pushed: ${result.pushed.inserts}/${result.pushed.updates}`);
|
|
49
|
+
* console.log(`Pulled: ${result.pulled.inserts}/${result.pulled.updates}`);
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function fullSync(options: FullSyncOptions): Promise<FullSyncResult>;
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full wallet synchronization with remote backup server.
|
|
3
|
+
*
|
|
4
|
+
* Performs a complete resync: push local → reset sync state → full pull from server.
|
|
5
|
+
* This is a deliberate user action (not automatic) for recovering from sync issues.
|
|
6
|
+
*/
|
|
7
|
+
import { createSyncMap } from "@bsv/wallet-toolbox-mobile/out/src/storage/schema/entities/EntityBase.js";
|
|
8
|
+
/**
|
|
9
|
+
* Perform a full sync with the remote backup server.
|
|
10
|
+
*
|
|
11
|
+
* Steps:
|
|
12
|
+
* 1. Push all local data to remote backup
|
|
13
|
+
* 2. Clear local syncMap / reset sync state
|
|
14
|
+
* 3. Pull ALL data from server (not incremental)
|
|
15
|
+
* 4. Rebuild complete server→client ID mappings
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const result = await fullSync({
|
|
20
|
+
* storage,
|
|
21
|
+
* remoteStorage: remoteClient,
|
|
22
|
+
* identityKey: pubKey,
|
|
23
|
+
* onProgress: (stage, msg) => console.log(`[${stage}] ${msg}`)
|
|
24
|
+
* });
|
|
25
|
+
* console.log(`Pushed: ${result.pushed.inserts}/${result.pushed.updates}`);
|
|
26
|
+
* console.log(`Pulled: ${result.pulled.inserts}/${result.pulled.updates}`);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export async function fullSync(options) {
|
|
30
|
+
const { storage, remoteStorage, identityKey, onProgress } = options;
|
|
31
|
+
// Step 1: Push local data to remote
|
|
32
|
+
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`);
|
|
36
|
+
// Step 2: Reset sync state to force full pull
|
|
37
|
+
onProgress?.("resetting", "Resetting sync state...");
|
|
38
|
+
const remoteSettings = remoteStorage.getSettings();
|
|
39
|
+
await storage.runAsStorageProvider(async (active) => {
|
|
40
|
+
const syncStates = await active.findSyncStates({
|
|
41
|
+
partial: {
|
|
42
|
+
userId: auth.userId,
|
|
43
|
+
storageIdentityKey: remoteSettings.storageIdentityKey,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
if (syncStates.length > 0) {
|
|
47
|
+
const syncState = syncStates[0];
|
|
48
|
+
await active.updateSyncState(syncState.syncStateId, {
|
|
49
|
+
syncMap: JSON.stringify(createSyncMap()),
|
|
50
|
+
when: undefined,
|
|
51
|
+
status: "unknown",
|
|
52
|
+
});
|
|
53
|
+
onProgress?.("resetting", "Sync state reset complete");
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
onProgress?.("resetting", "No existing sync state found");
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
// Step 3: Pull from remote (full pull due to reset state)
|
|
60
|
+
onProgress?.("pulling", "Pulling all data from remote...");
|
|
61
|
+
const pullResult = await storage.syncFromReader(identityKey, remoteStorage);
|
|
62
|
+
onProgress?.("pulling", `Pulled ${pullResult.inserts} inserts, ${pullResult.updates} updates`);
|
|
63
|
+
// Step 4: Complete
|
|
64
|
+
onProgress?.("complete", "Full sync complete");
|
|
65
|
+
return {
|
|
66
|
+
pushed: { inserts: pushResult.inserts, updates: pushResult.updates },
|
|
67
|
+
pulled: { inserts: pullResult.inserts, updates: pullResult.updates },
|
|
68
|
+
};
|
|
69
|
+
}
|
package/dist/wallet/index.d.ts
CHANGED
package/dist/wallet/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1sat/wallet-toolbox",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"description": "BSV wallet library extending @bsv/wallet-toolbox with 1Sat Ordinals protocol support",
|
|
5
5
|
"author": "1Sat Team",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"buffer": "^6.0.3"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@bsv/wallet-toolbox-mobile": "npm:@bopen-io/wallet-toolbox-mobile@^1.7.20-idb-fix.
|
|
45
|
+
"@bsv/wallet-toolbox-mobile": "npm:@bopen-io/wallet-toolbox-mobile@^1.7.20-idb-fix.15"
|
|
46
46
|
},
|
|
47
47
|
"peerDependenciesMeta": {
|
|
48
48
|
"@bsv/wallet-toolbox-mobile": {
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@biomejs/biome": "^1.9.4",
|
|
54
|
-
"@bsv/wallet-toolbox": "npm:@bopen-io/wallet-toolbox@^1.7.20-idb-fix.
|
|
55
|
-
"@bsv/wallet-toolbox-mobile": "npm:@bopen-io/wallet-toolbox-mobile@^1.7.20-idb-fix.
|
|
54
|
+
"@bsv/wallet-toolbox": "npm:@bopen-io/wallet-toolbox@^1.7.20-idb-fix.15",
|
|
55
|
+
"@bsv/wallet-toolbox-mobile": "npm:@bopen-io/wallet-toolbox-mobile@^1.7.20-idb-fix.15",
|
|
56
56
|
"@types/bun": "^1.3.4",
|
|
57
57
|
"@types/chrome": "^0.1.32",
|
|
58
58
|
"typescript": "^5.9.3"
|