@miden-sdk/miden-sdk 0.15.0-alpha.5 → 0.15.0-alpha.6
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/mt/{Cargo-smJQCGjz.js → Cargo-C9UbiAcT.js} +62 -6
- package/dist/mt/{Cargo-smJQCGjz.js.map → Cargo-C9UbiAcT.js.map} +1 -1
- package/dist/mt/api-types.d.ts +6 -2
- package/dist/mt/assets/miden_client_web.wasm +0 -0
- package/dist/mt/crates/miden_client_web.d.ts +31 -1
- package/dist/mt/eager.js +2 -2
- package/dist/mt/index.d.ts +2 -1
- package/dist/mt/index.js +299 -266
- package/dist/mt/index.js.map +1 -1
- package/dist/mt/wasm.js +1 -1
- package/dist/mt/workerHelpers.js +1 -1
- package/dist/mt/workers/{Cargo-smJQCGjz-q4GYXDiD.js → Cargo-C9UbiAcT-Z344cyB1.js} +62 -6
- package/dist/mt/workers/{Cargo-smJQCGjz-q4GYXDiD.js.map → Cargo-C9UbiAcT-Z344cyB1.js.map} +1 -1
- package/dist/mt/workers/assets/miden_client_web.wasm +0 -0
- package/dist/mt/workers/web-client-methods-worker.js +118 -7
- package/dist/mt/workers/web-client-methods-worker.js.map +1 -1
- package/dist/mt/workers/web-client-methods-worker.module.js +55 -2
- package/dist/mt/workers/web-client-methods-worker.module.js.map +1 -1
- package/dist/mt/workers/workerHelpers.js +1 -1
- package/dist/st/{Cargo-CG4XszZo.js → Cargo-OZMlHpic.js} +24 -2
- package/dist/st/{Cargo-CG4XszZo.js.map → Cargo-OZMlHpic.js.map} +1 -1
- package/dist/st/api-types.d.ts +6 -2
- package/dist/st/assets/miden_client_web.wasm +0 -0
- package/dist/st/crates/miden_client_web.d.ts +15 -1
- package/dist/st/eager.js +2 -2
- package/dist/st/index.d.ts +2 -1
- package/dist/st/index.js +299 -266
- package/dist/st/index.js.map +1 -1
- package/dist/st/wasm.js +1 -1
- package/dist/st/workers/{Cargo-CG4XszZo-S7EHAZSa.js → Cargo-OZMlHpic-DZjvJlWc.js} +24 -2
- package/dist/st/workers/{Cargo-CG4XszZo-S7EHAZSa.js.map → Cargo-OZMlHpic-DZjvJlWc.js.map} +1 -1
- package/dist/st/workers/assets/miden_client_web.wasm +0 -0
- package/dist/st/workers/web-client-methods-worker.js +79 -4
- package/dist/st/workers/web-client-methods-worker.js.map +1 -1
- package/dist/st/workers/web-client-methods-worker.module.js +55 -2
- package/dist/st/workers/web-client-methods-worker.module.js.map +1 -1
- package/js/client.js +24 -5
- package/js/node/napi-compat.js +7 -3
- package/js/resources/transactions.js +4 -1
- package/package.json +4 -4
package/dist/mt/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import loadWasm from './wasm.js';
|
|
2
|
-
export { Account, AccountArray, AccountBuilder, AccountBuilderResult, AccountCode, AccountComponent, AccountComponentCode, AccountDelta, AccountFile, AccountHeader, AccountId, AccountIdArray, AccountInterface, AccountProof, AccountReader, AccountStatus, AccountStorage, AccountStorageDelta, AccountStorageMode, AccountStorageRequirements, AccountVaultDelta, Address, AdviceInputs, AdviceMap, AssetVault, AuthFalcon512RpoMultisigConfig, AuthSecretKey, BasicFungibleFaucetComponent, BlockHeader, CodeBuilder, CommittedNote, ConsumableNoteRecord, Endpoint, ExecutedTransaction, Felt, FeltArray, FetchedAccount, FetchedNote, FlattenedU8Vec, ForeignAccount, ForeignAccountArray, FungibleAsset, FungibleAssetDelta, FungibleAssetDeltaItem, GetProceduresResultItem, InputNote, InputNoteRecord, InputNoteState, InputNotes, IntoUnderlyingByteSource, IntoUnderlyingSink, IntoUnderlyingSource, JsAccountUpdate, JsStateSyncUpdate, JsStorageMapEntry, JsStorageSlot, JsVaultAsset, Library, MerklePath, NetworkId, NetworkNoteStatusInfo, NetworkType, Note, NoteAndArgs, NoteAndArgsArray, NoteArray, NoteAssets, NoteAttachment, NoteAttachmentScheme, NoteConsumability, NoteConsumptionStatus, NoteDetails, NoteDetailsAndTag, NoteDetailsAndTagArray, NoteExecutionHint, NoteExportFormat, NoteFile, NoteFilter, NoteFilterTypes, NoteHeader, NoteId, NoteIdAndArgs, NoteIdAndArgsArray, NoteInclusionProof, NoteLocation, NoteMetadata, NoteRecipient, NoteRecipientArray, NoteScript, NoteStorage, NoteSyncBlock, NoteSyncInfo, NoteTag, NoteType, OutputNote, OutputNoteArray, OutputNoteRecord, OutputNoteState, OutputNotes, Package, PartialNote, Poseidon2, ProcedureThreshold, Program, ProvenTransaction, PublicKey, RpcClient, Rpo256, SerializedInputNoteData, SerializedOutputNoteData, SerializedTransactionData, Signature, SigningInputs, SigningInputsType, SlotAndKeys, SparseMerklePath, StorageMap, StorageMapEntry, StorageMapEntryJs, StorageMapInfo, StorageMapUpdate, StorageSlot, StorageSlotArray, SyncSummary, TestUtils, TokenSymbol, TransactionArgs, TransactionFilter, TransactionId, TransactionProver, TransactionRecord, TransactionRequest, TransactionRequestBuilder, TransactionResult, TransactionScript, TransactionScriptInputPair, TransactionScriptInputPairArray, TransactionStatus, TransactionStoreUpdate, TransactionSummary, WebClient, WebKeystoreApi, Word, createAuthFalcon512RpoMultisig, exportStore, importStore, initSync, initThreadPool, parallelSumBench, rayonThreadCount, sequentialSumBench, setupLogging, wbg_rayon_PoolBuilder, wbg_rayon_start_worker } from './Cargo-
|
|
2
|
+
export { Account, AccountArray, AccountBuilder, AccountBuilderResult, AccountCode, AccountComponent, AccountComponentCode, AccountDelta, AccountFile, AccountHeader, AccountId, AccountIdArray, AccountInterface, AccountProof, AccountReader, AccountStatus, AccountStorage, AccountStorageDelta, AccountStorageMode, AccountStorageRequirements, AccountVaultDelta, Address, AdviceInputs, AdviceMap, AssetVault, AuthFalcon512RpoMultisigConfig, AuthSecretKey, BasicFungibleFaucetComponent, BlockHeader, CodeBuilder, CommittedNote, ConsumableNoteRecord, Endpoint, ExecutedTransaction, Felt, FeltArray, FetchedAccount, FetchedNote, FlattenedU8Vec, ForeignAccount, ForeignAccountArray, FungibleAsset, FungibleAssetDelta, FungibleAssetDeltaItem, GetProceduresResultItem, InputNote, InputNoteRecord, InputNoteState, InputNotes, IntoUnderlyingByteSource, IntoUnderlyingSink, IntoUnderlyingSource, JsAccountUpdate, JsStateSyncUpdate, JsStorageMapEntry, JsStorageSlot, JsVaultAsset, Library, MerklePath, NetworkId, NetworkNoteStatusInfo, NetworkType, Note, NoteAndArgs, NoteAndArgsArray, NoteArray, NoteAssets, NoteAttachment, NoteAttachmentScheme, NoteConsumability, NoteConsumptionStatus, NoteDetails, NoteDetailsAndTag, NoteDetailsAndTagArray, NoteExecutionHint, NoteExportFormat, NoteFile, NoteFilter, NoteFilterTypes, NoteHeader, NoteId, NoteIdAndArgs, NoteIdAndArgsArray, NoteInclusionProof, NoteLocation, NoteMetadata, NoteRecipient, NoteRecipientArray, NoteScript, NoteStorage, NoteSyncBlock, NoteSyncInfo, NoteTag, NoteType, OutputNote, OutputNoteArray, OutputNoteRecord, OutputNoteState, OutputNotes, Package, PartialNote, Poseidon2, ProcedureThreshold, Program, ProvenTransaction, PublicKey, RpcClient, Rpo256, SerializedInputNoteData, SerializedOutputNoteData, SerializedTransactionData, Signature, SigningInputs, SigningInputsType, SlotAndKeys, SparseMerklePath, StorageMap, StorageMapEntry, StorageMapEntryJs, StorageMapInfo, StorageMapUpdate, StorageSlot, StorageSlotArray, SyncSummary, TestUtils, TokenSymbol, TransactionArgs, TransactionFilter, TransactionId, TransactionProver, TransactionRecord, TransactionRequest, TransactionRequestBuilder, TransactionResult, TransactionScript, TransactionScriptInputPair, TransactionScriptInputPairArray, TransactionStatus, TransactionStoreUpdate, TransactionSummary, WebClient, WebKeystoreApi, Word, createAuthFalcon512RpoMultisig, exportStore, importStore, initSync, initThreadPool, mtProbeAsync, mtProbeSync, parallelSumBench, rayonThreadCount, sequentialSumBench, setupLogging, wbg_rayon_PoolBuilder, wbg_rayon_start_worker } from './Cargo-C9UbiAcT.js';
|
|
3
3
|
|
|
4
4
|
const WorkerAction = Object.freeze({
|
|
5
5
|
INIT: "init",
|
|
@@ -26,20 +26,24 @@ const MethodName = Object.freeze({
|
|
|
26
26
|
SUBMIT_NEW_TRANSACTION_WITH_PROVER_MOCK: "submitNewTransactionWithProverMock",
|
|
27
27
|
SYNC_STATE: "syncState",
|
|
28
28
|
SYNC_STATE_MOCK: "syncStateMock",
|
|
29
|
+
SYNC_CHAIN: "syncChain",
|
|
30
|
+
SYNC_CHAIN_MOCK: "syncChainMock",
|
|
31
|
+
SYNC_NOTE_TRANSPORT: "syncNoteTransport",
|
|
32
|
+
SYNC_NOTE_TRANSPORT_MOCK: "syncNoteTransportMock",
|
|
29
33
|
});
|
|
30
34
|
|
|
31
35
|
/**
|
|
32
36
|
* Sync Lock Module
|
|
33
37
|
*
|
|
34
|
-
*
|
|
35
|
-
* with an in-process mutex fallback for older browsers.
|
|
38
|
+
* Coordinates concurrent sync calls using the Web Locks API.
|
|
36
39
|
*
|
|
37
40
|
* Behavior:
|
|
38
|
-
* -
|
|
39
|
-
*
|
|
40
|
-
* -
|
|
41
|
-
*
|
|
42
|
-
* -
|
|
41
|
+
* - Same-method coalescing: if a sync of the same method is in progress,
|
|
42
|
+
* subsequent callers share its result promise
|
|
43
|
+
* - Different-method serialization: different methods (e.g. syncState vs
|
|
44
|
+
* syncNoteTransport) wait for each other via the Web Lock, or via an
|
|
45
|
+
* in-process per-dbId promise chain when Web Locks are unavailable
|
|
46
|
+
* - Web Locks also serialize across tabs (Chrome 69+, Safari 15.4+)
|
|
43
47
|
*/
|
|
44
48
|
|
|
45
49
|
/**
|
|
@@ -53,195 +57,86 @@ function hasWebLocks() {
|
|
|
53
57
|
);
|
|
54
58
|
}
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
*/
|
|
59
|
-
const syncStates = new Map();
|
|
60
|
+
// Coalesce map keyed by `${dbId}:${methodId}` -> in-flight promise.
|
|
61
|
+
const inFlight = new Map();
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
let state = syncStates.get(dbId);
|
|
66
|
-
if (!state) {
|
|
67
|
-
state = {
|
|
68
|
-
inProgress: false,
|
|
69
|
-
result: null,
|
|
70
|
-
error: null,
|
|
71
|
-
waiters: [],
|
|
72
|
-
releaseLock: null,
|
|
73
|
-
syncGeneration: 0,
|
|
74
|
-
};
|
|
75
|
-
syncStates.set(dbId, state);
|
|
76
|
-
}
|
|
77
|
-
return state;
|
|
78
|
-
}
|
|
63
|
+
// Per-dbId promise tail used to serialize cross-method calls when Web Locks
|
|
64
|
+
// are unavailable. Each new task chains onto the current tail so different
|
|
65
|
+
// methods on the same dbId run sequentially within the tab.
|
|
66
|
+
const fallbackTails = new Map();
|
|
79
67
|
|
|
80
68
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* If a sync is already in progress:
|
|
84
|
-
* - Returns { acquired: false, coalescedResult } after waiting for the result
|
|
85
|
-
*
|
|
86
|
-
* If no sync is in progress:
|
|
87
|
-
* - Returns { acquired: true } and the caller should perform the sync,
|
|
88
|
-
* then call releaseSyncLock() or releaseSyncLockWithError()
|
|
69
|
+
* Build the coalesce-map key for an in-flight sync of `(dbId, methodId)`.
|
|
89
70
|
*
|
|
90
|
-
* @param {string} dbId
|
|
91
|
-
* @param {
|
|
92
|
-
* @returns {
|
|
71
|
+
* @param {string} dbId
|
|
72
|
+
* @param {string} methodId
|
|
73
|
+
* @returns {string}
|
|
93
74
|
*/
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// If a sync is already in progress, wait for it to complete (coalescing)
|
|
98
|
-
if (state.inProgress) {
|
|
99
|
-
return new Promise((resolve, reject) => {
|
|
100
|
-
let timeoutId;
|
|
101
|
-
if (timeoutMs > 0) {
|
|
102
|
-
timeoutId = setTimeout(() => {
|
|
103
|
-
const idx = state.waiters.findIndex((w) => w.resolve === onResult);
|
|
104
|
-
if (idx !== -1) {
|
|
105
|
-
state.waiters.splice(idx, 1);
|
|
106
|
-
}
|
|
107
|
-
reject(new Error("Sync lock acquisition timed out"));
|
|
108
|
-
}, timeoutMs);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const onResult = (result) => {
|
|
112
|
-
/* v8 ignore next 1 -- timeoutId only set when timeoutMs>0 AND another sync is in progress; combo rare in tests */
|
|
113
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
114
|
-
resolve({ acquired: false, coalescedResult: result });
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const onError = (error) => {
|
|
118
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
119
|
-
reject(error);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
state.waiters.push({ resolve: onResult, reject: onError });
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Mark sync as in progress and increment generation
|
|
127
|
-
state.inProgress = true;
|
|
128
|
-
state.result = null;
|
|
129
|
-
state.error = null;
|
|
130
|
-
state.syncGeneration++;
|
|
131
|
-
const currentGeneration = state.syncGeneration;
|
|
132
|
-
|
|
133
|
-
// Try to acquire Web Lock if available
|
|
134
|
-
if (hasWebLocks()) {
|
|
135
|
-
const lockName = `miden-sync-${dbId}`;
|
|
136
|
-
|
|
137
|
-
return new Promise((resolve, reject) => {
|
|
138
|
-
let timeoutId;
|
|
139
|
-
let timedOut = false;
|
|
140
|
-
|
|
141
|
-
if (timeoutMs > 0) {
|
|
142
|
-
timeoutId = setTimeout(() => {
|
|
143
|
-
timedOut = true;
|
|
144
|
-
if (state.syncGeneration === currentGeneration) {
|
|
145
|
-
state.inProgress = false;
|
|
146
|
-
const error = new Error("Sync lock acquisition timed out");
|
|
147
|
-
for (const waiter of state.waiters) {
|
|
148
|
-
waiter.reject(error);
|
|
149
|
-
}
|
|
150
|
-
state.waiters = [];
|
|
151
|
-
}
|
|
152
|
-
reject(new Error("Sync lock acquisition timed out"));
|
|
153
|
-
}, timeoutMs);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
navigator.locks
|
|
157
|
-
.request(lockName, { mode: "exclusive" }, async () => {
|
|
158
|
-
/* v8 ignore next 3 -- race: lock granted after timeout or newer generation */
|
|
159
|
-
if (timedOut || state.syncGeneration !== currentGeneration) {
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
164
|
-
|
|
165
|
-
return new Promise((releaseLock) => {
|
|
166
|
-
state.releaseLock = releaseLock;
|
|
167
|
-
resolve({ acquired: true });
|
|
168
|
-
});
|
|
169
|
-
})
|
|
170
|
-
.catch((err) => {
|
|
171
|
-
/* v8 ignore next 5 -- catch path requires Web Locks rejection combined with
|
|
172
|
-
optional timeout; tested via "rejects when Web Locks request rejects" but
|
|
173
|
-
the timeoutId-set branch needs Web Locks + timeout simultaneously */
|
|
174
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
175
|
-
if (state.syncGeneration === currentGeneration) {
|
|
176
|
-
state.inProgress = false;
|
|
177
|
-
}
|
|
178
|
-
reject(err instanceof Error ? err : new Error(String(err)));
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
} else {
|
|
182
|
-
// Fallback: no Web Locks, just use in-process state
|
|
183
|
-
return { acquired: true };
|
|
184
|
-
}
|
|
75
|
+
function coalesceKey(dbId, methodId) {
|
|
76
|
+
return `${dbId}:${methodId}`;
|
|
185
77
|
}
|
|
186
78
|
|
|
187
79
|
/**
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
80
|
+
* Run `fn` while holding the per-db Web Lock. When Web Locks are unavailable,
|
|
81
|
+
* serializes `fn` against any other in-flight call on the same `dbId` via an
|
|
82
|
+
* in-process promise chain — the wasm-bindgen `WebClient` uses a synchronous
|
|
83
|
+
* `RefCell` for interior mutability in the browser, so overlapping
|
|
84
|
+
* cross-method borrows would throw "recursive use of an object detected
|
|
85
|
+
* which would lead to unsafe aliasing in rust".
|
|
191
86
|
*
|
|
192
|
-
* @param {string} dbId
|
|
193
|
-
* @param {
|
|
87
|
+
* @param {string} dbId
|
|
88
|
+
* @param {() => Promise<T>} fn
|
|
89
|
+
* @returns {Promise<T>}
|
|
90
|
+
* @template T
|
|
194
91
|
*/
|
|
195
|
-
function
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
for (const waiter of state.waiters) {
|
|
207
|
-
waiter.resolve(result);
|
|
208
|
-
}
|
|
209
|
-
state.waiters = [];
|
|
210
|
-
|
|
211
|
-
if (state.releaseLock) {
|
|
212
|
-
state.releaseLock();
|
|
213
|
-
state.releaseLock = null;
|
|
92
|
+
function runUnderLock(dbId, fn) {
|
|
93
|
+
if (!hasWebLocks()) {
|
|
94
|
+
const prev = fallbackTails.get(dbId) ?? Promise.resolve();
|
|
95
|
+
const next = prev.catch(() => {}).then(fn);
|
|
96
|
+
const guarded = next.catch(() => {});
|
|
97
|
+
fallbackTails.set(dbId, guarded);
|
|
98
|
+
guarded.then(() => {
|
|
99
|
+
// Drop the slot only if no successor chained onto this tail.
|
|
100
|
+
if (fallbackTails.get(dbId) === guarded) fallbackTails.delete(dbId);
|
|
101
|
+
});
|
|
102
|
+
return next;
|
|
214
103
|
}
|
|
104
|
+
return navigator.locks.request(
|
|
105
|
+
`miden-sync-${dbId}`,
|
|
106
|
+
{ mode: "exclusive" },
|
|
107
|
+
fn
|
|
108
|
+
);
|
|
215
109
|
}
|
|
216
110
|
|
|
217
111
|
/**
|
|
218
|
-
*
|
|
112
|
+
* Run `fn` under the sync lock for (dbId, methodId).
|
|
219
113
|
*
|
|
220
|
-
*
|
|
114
|
+
* Concurrent calls with the same (dbId, methodId) share the same promise
|
|
115
|
+
* (coalescing). Concurrent calls on the same dbId with different methodIds
|
|
116
|
+
* serialize via the Web Lock.
|
|
221
117
|
*
|
|
222
|
-
* @param {string} dbId -
|
|
223
|
-
* @param {
|
|
118
|
+
* @param {string} dbId - Database ID
|
|
119
|
+
* @param {string} methodId - Method identifier (see MethodName constants)
|
|
120
|
+
* @param {() => Promise<T>} fn - Work to run under the lock
|
|
121
|
+
* @returns {Promise<T>}
|
|
224
122
|
*/
|
|
225
|
-
function
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
state.releaseLock();
|
|
243
|
-
state.releaseLock = null;
|
|
244
|
-
}
|
|
123
|
+
function withSyncLock(dbId, methodId, fn) {
|
|
124
|
+
const key = coalesceKey(dbId, methodId);
|
|
125
|
+
|
|
126
|
+
let work = inFlight.get(key);
|
|
127
|
+
if (!work) {
|
|
128
|
+
work = runUnderLock(dbId, fn);
|
|
129
|
+
inFlight.set(key, work);
|
|
130
|
+
// Swallow on the derived promise so a rejection here doesn't surface as
|
|
131
|
+
// an unhandled rejection; the caller still sees the error through `work`.
|
|
132
|
+
work
|
|
133
|
+
.finally(() => {
|
|
134
|
+
if (inFlight.get(key) === work) inFlight.delete(key);
|
|
135
|
+
})
|
|
136
|
+
.catch(() => {});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return work;
|
|
245
140
|
}
|
|
246
141
|
|
|
247
142
|
/**
|
|
@@ -1128,7 +1023,10 @@ class TransactionsResource {
|
|
|
1128
1023
|
}
|
|
1129
1024
|
|
|
1130
1025
|
try {
|
|
1131
|
-
|
|
1026
|
+
// Chain-only sync is sufficient: confirmation only needs on-chain
|
|
1027
|
+
// state, and skipping NTL keeps polling alive when the note
|
|
1028
|
+
// transport endpoint is unavailable.
|
|
1029
|
+
await this.#inner.syncChain();
|
|
1132
1030
|
} catch {
|
|
1133
1031
|
// Sync may fail transiently; continue polling
|
|
1134
1032
|
}
|
|
@@ -1945,15 +1843,34 @@ class MidenClient {
|
|
|
1945
1843
|
}
|
|
1946
1844
|
|
|
1947
1845
|
/**
|
|
1948
|
-
* Syncs the client
|
|
1846
|
+
* Syncs the client: fetches private notes from the Note Transport Layer, then syncs on-chain
|
|
1847
|
+
* state with the Miden node. Fails fast on either.
|
|
1949
1848
|
*
|
|
1950
|
-
* @param {object} [opts] - Sync options.
|
|
1951
|
-
* @param {number} [opts.timeout] - Timeout in milliseconds (0 = no timeout).
|
|
1952
1849
|
* @returns {Promise<SyncSummary>} The sync summary.
|
|
1953
1850
|
*/
|
|
1954
|
-
async sync(
|
|
1851
|
+
async sync() {
|
|
1852
|
+
this.assertNotTerminated();
|
|
1853
|
+
return await this.#inner.syncState();
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
/**
|
|
1857
|
+
* Syncs on-chain state only (no NTL fetch).
|
|
1858
|
+
*
|
|
1859
|
+
* @returns {Promise<SyncSummary>}
|
|
1860
|
+
*/
|
|
1861
|
+
async syncChain() {
|
|
1955
1862
|
this.assertNotTerminated();
|
|
1956
|
-
return await this.#inner.
|
|
1863
|
+
return await this.#inner.syncChain();
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
/**
|
|
1867
|
+
* Fetches private notes from the Note Transport Layer.
|
|
1868
|
+
*
|
|
1869
|
+
* @returns {Promise<void>}
|
|
1870
|
+
*/
|
|
1871
|
+
async syncNoteTransport() {
|
|
1872
|
+
this.assertNotTerminated();
|
|
1873
|
+
return await this.#inner.syncNoteTransport();
|
|
1957
1874
|
}
|
|
1958
1875
|
|
|
1959
1876
|
/**
|
|
@@ -2884,10 +2801,19 @@ class WebClient {
|
|
|
2884
2801
|
this.loadedResolver = resolve;
|
|
2885
2802
|
});
|
|
2886
2803
|
|
|
2887
|
-
// Create a promise that resolves when the worker signals that it is
|
|
2888
|
-
|
|
2804
|
+
// Create a promise that resolves when the worker signals that it is
|
|
2805
|
+
// fully initialized, and rejects if initialization fails. Every
|
|
2806
|
+
// worker-forwarded method awaits `ready` first, so an init failure must
|
|
2807
|
+
// reject it — otherwise those calls would await a promise that never
|
|
2808
|
+
// settles and hang forever.
|
|
2809
|
+
this.ready = new Promise((resolve, reject) => {
|
|
2889
2810
|
this.readyResolver = resolve;
|
|
2811
|
+
this.readyRejecter = reject;
|
|
2890
2812
|
});
|
|
2813
|
+
// Init can fail before any caller awaits `ready`; this no-op handler
|
|
2814
|
+
// suppresses the unhandledrejection event without consuming the
|
|
2815
|
+
// rejection for real awaiters.
|
|
2816
|
+
this.ready.catch(() => {});
|
|
2891
2817
|
|
|
2892
2818
|
// Listen for messages from the worker.
|
|
2893
2819
|
this.worker.addEventListener("message", async (event) => {
|
|
@@ -2951,6 +2877,21 @@ class WebClient {
|
|
|
2951
2877
|
} else {
|
|
2952
2878
|
resolve(result);
|
|
2953
2879
|
}
|
|
2880
|
+
return;
|
|
2881
|
+
}
|
|
2882
|
+
|
|
2883
|
+
// An error with no request attached comes from worker initialization
|
|
2884
|
+
// (INIT is the only requestId-less action that can fail). Reject
|
|
2885
|
+
// `ready` so queued and future method calls fail with the real cause
|
|
2886
|
+
// instead of awaiting forever.
|
|
2887
|
+
if (error && !requestId) {
|
|
2888
|
+
const workerError =
|
|
2889
|
+
error instanceof Error ? error : deserializeError(error);
|
|
2890
|
+
console.error(
|
|
2891
|
+
"WebClient: worker initialization failed:",
|
|
2892
|
+
workerError
|
|
2893
|
+
);
|
|
2894
|
+
this.readyRejecter(workerError);
|
|
2954
2895
|
}
|
|
2955
2896
|
});
|
|
2956
2897
|
|
|
@@ -3435,7 +3376,7 @@ class WebClient {
|
|
|
3435
3376
|
}
|
|
3436
3377
|
|
|
3437
3378
|
/**
|
|
3438
|
-
* Syncs the client
|
|
3379
|
+
* Syncs the client (NTL followed by chain sync, failing fast on either).
|
|
3439
3380
|
*
|
|
3440
3381
|
* This method coordinates concurrent sync calls using the Web Locks API when available,
|
|
3441
3382
|
* with an in-process mutex fallback for older browsers. If a sync is already in progress,
|
|
@@ -3444,58 +3385,76 @@ class WebClient {
|
|
|
3444
3385
|
* @returns {Promise<SyncSummary>} The sync summary
|
|
3445
3386
|
*/
|
|
3446
3387
|
async syncState() {
|
|
3447
|
-
|
|
3388
|
+
const dbId = this.storeName || "default";
|
|
3389
|
+
const methodId = MethodName.SYNC_STATE;
|
|
3390
|
+
|
|
3391
|
+
try {
|
|
3392
|
+
return await withSyncLock(dbId, methodId, async () => {
|
|
3393
|
+
if (!this.worker) {
|
|
3394
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3395
|
+
return await wasmWebClient.syncStateImpl();
|
|
3396
|
+
}
|
|
3397
|
+
const wasm = await getWasmOrThrow();
|
|
3398
|
+
const serializedSyncSummaryBytes =
|
|
3399
|
+
await this.callMethodWithWorker(methodId);
|
|
3400
|
+
return wasm.SyncSummary.deserialize(
|
|
3401
|
+
new Uint8Array(serializedSyncSummaryBytes)
|
|
3402
|
+
);
|
|
3403
|
+
});
|
|
3404
|
+
} catch (error) {
|
|
3405
|
+
console.error("INDEX.JS: Error in syncState:", error);
|
|
3406
|
+
throw error;
|
|
3407
|
+
}
|
|
3448
3408
|
}
|
|
3449
3409
|
|
|
3450
3410
|
/**
|
|
3451
|
-
*
|
|
3411
|
+
* Fetches private notes from the Note Transport Layer.
|
|
3452
3412
|
*
|
|
3453
|
-
*
|
|
3454
|
-
* with an in-process mutex fallback for older browsers. If a sync is already in progress,
|
|
3455
|
-
* subsequent callers will wait and receive the same result (coalescing behavior).
|
|
3456
|
-
*
|
|
3457
|
-
* @param {number} timeoutMs - Timeout in milliseconds (0 = no timeout)
|
|
3458
|
-
* @returns {Promise<SyncSummary>} The sync summary
|
|
3413
|
+
* @returns {Promise<void>}
|
|
3459
3414
|
*/
|
|
3460
|
-
async
|
|
3461
|
-
// Use storeName as the database ID for lock coordination
|
|
3415
|
+
async syncNoteTransport() {
|
|
3462
3416
|
const dbId = this.storeName || "default";
|
|
3417
|
+
const methodId = MethodName.SYNC_NOTE_TRANSPORT;
|
|
3463
3418
|
|
|
3464
3419
|
try {
|
|
3465
|
-
|
|
3466
|
-
const lockHandle = await acquireSyncLock(dbId, timeoutMs);
|
|
3467
|
-
|
|
3468
|
-
if (!lockHandle.acquired) {
|
|
3469
|
-
// We're coalescing - return the result from the in-progress sync
|
|
3470
|
-
return lockHandle.coalescedResult;
|
|
3471
|
-
}
|
|
3472
|
-
|
|
3473
|
-
// We acquired the lock - perform the sync
|
|
3474
|
-
try {
|
|
3475
|
-
let result;
|
|
3420
|
+
await withSyncLock(dbId, methodId, async () => {
|
|
3476
3421
|
if (!this.worker) {
|
|
3477
3422
|
const wasmWebClient = await this.getWasmWebClient();
|
|
3478
|
-
|
|
3423
|
+
await wasmWebClient.syncNoteTransportImpl();
|
|
3479
3424
|
} else {
|
|
3480
|
-
|
|
3481
|
-
const serializedSyncSummaryBytes = await this.callMethodWithWorker(
|
|
3482
|
-
MethodName.SYNC_STATE
|
|
3483
|
-
);
|
|
3484
|
-
result = wasm.SyncSummary.deserialize(
|
|
3485
|
-
new Uint8Array(serializedSyncSummaryBytes)
|
|
3486
|
-
);
|
|
3425
|
+
await this.callMethodWithWorker(methodId);
|
|
3487
3426
|
}
|
|
3427
|
+
});
|
|
3428
|
+
} catch (error) {
|
|
3429
|
+
console.error("INDEX.JS: Error in syncNoteTransport:", error);
|
|
3430
|
+
throw error;
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3488
3433
|
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3434
|
+
/**
|
|
3435
|
+
* Syncs on-chain state only (no NTL fetch).
|
|
3436
|
+
*
|
|
3437
|
+
* @returns {Promise<SyncSummary>}
|
|
3438
|
+
*/
|
|
3439
|
+
async syncChain() {
|
|
3440
|
+
const dbId = this.storeName || "default";
|
|
3441
|
+
const methodId = MethodName.SYNC_CHAIN;
|
|
3442
|
+
|
|
3443
|
+
try {
|
|
3444
|
+
return await withSyncLock(dbId, methodId, async () => {
|
|
3445
|
+
if (!this.worker) {
|
|
3446
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3447
|
+
return await wasmWebClient.syncChainImpl();
|
|
3448
|
+
}
|
|
3449
|
+
const wasm = await getWasmOrThrow();
|
|
3450
|
+
const serializedSyncSummaryBytes =
|
|
3451
|
+
await this.callMethodWithWorker(methodId);
|
|
3452
|
+
return wasm.SyncSummary.deserialize(
|
|
3453
|
+
new Uint8Array(serializedSyncSummaryBytes)
|
|
3454
|
+
);
|
|
3455
|
+
});
|
|
3497
3456
|
} catch (error) {
|
|
3498
|
-
console.error("INDEX.JS: Error in
|
|
3457
|
+
console.error("INDEX.JS: Error in syncChain:", error);
|
|
3499
3458
|
throw error;
|
|
3500
3459
|
}
|
|
3501
3460
|
}
|
|
@@ -3531,9 +3490,23 @@ class MockWebClient extends WebClient {
|
|
|
3531
3490
|
}
|
|
3532
3491
|
|
|
3533
3492
|
initializeWorker() {
|
|
3493
|
+
// Pass `numThreads` exactly like the real INIT path: every prove runs
|
|
3494
|
+
// inside the worker's own WASM instance, and rayon's pool is
|
|
3495
|
+
// per-instance — without this, mock-client proving (including the
|
|
3496
|
+
// integration suite) silently runs single-threaded.
|
|
3497
|
+
let numThreads = 1;
|
|
3498
|
+
try {
|
|
3499
|
+
if (
|
|
3500
|
+
typeof self !== "undefined" &&
|
|
3501
|
+
self.crossOriginIsolated &&
|
|
3502
|
+
navigator?.hardwareConcurrency
|
|
3503
|
+
) {
|
|
3504
|
+
numThreads = navigator.hardwareConcurrency;
|
|
3505
|
+
}
|
|
3506
|
+
} catch {}
|
|
3534
3507
|
this.worker.postMessage({
|
|
3535
3508
|
action: WorkerAction.INIT_MOCK,
|
|
3536
|
-
args: [this.seed, this.logLevel],
|
|
3509
|
+
args: [this.seed, this.logLevel, numThreads],
|
|
3537
3510
|
});
|
|
3538
3511
|
}
|
|
3539
3512
|
|
|
@@ -3584,59 +3557,119 @@ class MockWebClient extends WebClient {
|
|
|
3584
3557
|
* @returns {Promise<SyncSummary>} The sync summary
|
|
3585
3558
|
*/
|
|
3586
3559
|
async syncState() {
|
|
3587
|
-
|
|
3560
|
+
const dbId = this.storeName || "mock";
|
|
3561
|
+
const methodId = MethodName.SYNC_STATE;
|
|
3562
|
+
|
|
3563
|
+
try {
|
|
3564
|
+
return await withSyncLock(dbId, methodId, async () => {
|
|
3565
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3566
|
+
|
|
3567
|
+
if (!this.worker) {
|
|
3568
|
+
return await wasmWebClient.syncStateImpl();
|
|
3569
|
+
}
|
|
3570
|
+
|
|
3571
|
+
const serializedMockChain = (await wasmWebClient.serializeMockChain())
|
|
3572
|
+
.buffer;
|
|
3573
|
+
const serializedMockNoteTransportNode = (
|
|
3574
|
+
await wasmWebClient.serializeMockNoteTransportNode()
|
|
3575
|
+
).buffer;
|
|
3576
|
+
|
|
3577
|
+
const wasm = await getWasmOrThrow();
|
|
3578
|
+
const serializedSyncSummaryBytes = await this.callMethodWithWorker(
|
|
3579
|
+
MethodName.SYNC_STATE_MOCK,
|
|
3580
|
+
serializedMockChain,
|
|
3581
|
+
serializedMockNoteTransportNode
|
|
3582
|
+
);
|
|
3583
|
+
return wasm.SyncSummary.deserialize(
|
|
3584
|
+
new Uint8Array(serializedSyncSummaryBytes)
|
|
3585
|
+
);
|
|
3586
|
+
});
|
|
3587
|
+
} catch (error) {
|
|
3588
|
+
console.error("INDEX.JS: Error in syncState:", error);
|
|
3589
|
+
throw error;
|
|
3590
|
+
}
|
|
3588
3591
|
}
|
|
3589
3592
|
|
|
3590
3593
|
/**
|
|
3591
|
-
* Syncs the mock
|
|
3594
|
+
* Syncs only the on-chain mock state (no note transport fetch).
|
|
3592
3595
|
*
|
|
3593
|
-
*
|
|
3594
|
-
*
|
|
3596
|
+
* In worker mode, the main-thread mock chain + note-transport-node state
|
|
3597
|
+
* is serialized and shipped to the worker before the sync, so a prior
|
|
3598
|
+
* `proveBlock()` on the main thread is reflected in the worker's WASM
|
|
3599
|
+
* client. The no-worker path uses the main-thread WASM client directly.
|
|
3600
|
+
*
|
|
3601
|
+
* @returns {Promise<SyncSummary>}
|
|
3595
3602
|
*/
|
|
3596
|
-
async
|
|
3603
|
+
async syncChain() {
|
|
3597
3604
|
const dbId = this.storeName || "mock";
|
|
3605
|
+
const methodId = MethodName.SYNC_CHAIN;
|
|
3598
3606
|
|
|
3599
3607
|
try {
|
|
3600
|
-
|
|
3608
|
+
return await withSyncLock(dbId, methodId, async () => {
|
|
3609
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3601
3610
|
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3611
|
+
if (!this.worker) {
|
|
3612
|
+
return await wasmWebClient.syncChainImpl();
|
|
3613
|
+
}
|
|
3605
3614
|
|
|
3606
|
-
|
|
3607
|
-
|
|
3615
|
+
const serializedMockChain = (await wasmWebClient.serializeMockChain())
|
|
3616
|
+
.buffer;
|
|
3617
|
+
const serializedMockNoteTransportNode = (
|
|
3618
|
+
await wasmWebClient.serializeMockNoteTransportNode()
|
|
3619
|
+
).buffer;
|
|
3620
|
+
|
|
3621
|
+
const wasm = await getWasmOrThrow();
|
|
3622
|
+
const serializedSyncSummaryBytes = await this.callMethodWithWorker(
|
|
3623
|
+
MethodName.SYNC_CHAIN_MOCK,
|
|
3624
|
+
serializedMockChain,
|
|
3625
|
+
serializedMockNoteTransportNode
|
|
3626
|
+
);
|
|
3627
|
+
return wasm.SyncSummary.deserialize(
|
|
3628
|
+
new Uint8Array(serializedSyncSummaryBytes)
|
|
3629
|
+
);
|
|
3630
|
+
});
|
|
3631
|
+
} catch (error) {
|
|
3632
|
+
console.error("INDEX.JS: Error in syncChain:", error);
|
|
3633
|
+
throw error;
|
|
3634
|
+
}
|
|
3635
|
+
}
|
|
3636
|
+
|
|
3637
|
+
/**
|
|
3638
|
+
* Syncs only the mock note-transport state (no chain fetch).
|
|
3639
|
+
*
|
|
3640
|
+
* Mirrors {@link MockWebClient#syncChain}: in worker mode, the
|
|
3641
|
+
* main-thread mock chain + note-transport-node state is serialized
|
|
3642
|
+
* and shipped to the worker first.
|
|
3643
|
+
*
|
|
3644
|
+
* @returns {Promise<void>}
|
|
3645
|
+
*/
|
|
3646
|
+
async syncNoteTransport() {
|
|
3647
|
+
const dbId = this.storeName || "mock";
|
|
3648
|
+
const methodId = MethodName.SYNC_NOTE_TRANSPORT;
|
|
3649
|
+
|
|
3650
|
+
try {
|
|
3651
|
+
await withSyncLock(dbId, methodId, async () => {
|
|
3608
3652
|
const wasmWebClient = await this.getWasmWebClient();
|
|
3609
3653
|
|
|
3610
3654
|
if (!this.worker) {
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
let serializedMockChain = (await wasmWebClient.serializeMockChain())
|
|
3614
|
-
.buffer;
|
|
3615
|
-
let serializedMockNoteTransportNode = (
|
|
3616
|
-
await wasmWebClient.serializeMockNoteTransportNode()
|
|
3617
|
-
).buffer;
|
|
3618
|
-
|
|
3619
|
-
const wasm = await getWasmOrThrow();
|
|
3620
|
-
|
|
3621
|
-
const serializedSyncSummaryBytes = await this.callMethodWithWorker(
|
|
3622
|
-
MethodName.SYNC_STATE_MOCK,
|
|
3623
|
-
serializedMockChain,
|
|
3624
|
-
serializedMockNoteTransportNode
|
|
3625
|
-
);
|
|
3626
|
-
|
|
3627
|
-
result = wasm.SyncSummary.deserialize(
|
|
3628
|
-
new Uint8Array(serializedSyncSummaryBytes)
|
|
3629
|
-
);
|
|
3655
|
+
await wasmWebClient.syncNoteTransportImpl();
|
|
3656
|
+
return;
|
|
3630
3657
|
}
|
|
3631
3658
|
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3659
|
+
const serializedMockChain = (await wasmWebClient.serializeMockChain())
|
|
3660
|
+
.buffer;
|
|
3661
|
+
const serializedMockNoteTransportNode = (
|
|
3662
|
+
await wasmWebClient.serializeMockNoteTransportNode()
|
|
3663
|
+
).buffer;
|
|
3664
|
+
|
|
3665
|
+
await this.callMethodWithWorker(
|
|
3666
|
+
MethodName.SYNC_NOTE_TRANSPORT_MOCK,
|
|
3667
|
+
serializedMockChain,
|
|
3668
|
+
serializedMockNoteTransportNode
|
|
3669
|
+
);
|
|
3670
|
+
});
|
|
3638
3671
|
} catch (error) {
|
|
3639
|
-
console.error("INDEX.JS: Error in
|
|
3672
|
+
console.error("INDEX.JS: Error in syncNoteTransport:", error);
|
|
3640
3673
|
throw error;
|
|
3641
3674
|
}
|
|
3642
3675
|
}
|
|
@@ -3774,5 +3807,5 @@ MidenClient._MockWasmWebClient = MockWebClient;
|
|
|
3774
3807
|
MidenClient._getWasmOrThrow = getWasmOrThrow;
|
|
3775
3808
|
_setWebClient(WebClient);
|
|
3776
3809
|
|
|
3777
|
-
export { AccountType, AuthScheme, CompilerResource, Linking, MidenArrays, MidenClient, MockWebClient as MockWasmWebClient, MockWebClient, NoteVisibility, StorageMode, StorageResult, StorageView, WebClient as WasmWebClient, buildSwapTag, createP2IDENote, createP2IDNote, getWasmOrThrow, wordToBigInt };
|
|
3810
|
+
export { AccountType, AuthScheme, CompilerResource, Linking, MidenArrays, MidenClient, MockWebClient as MockWasmWebClient, MockWebClient, NoteVisibility, StorageMode, StorageResult, StorageView, WebClient as WasmWebClient, buildSwapTag, createP2IDENote, createP2IDNote, getWasmOrThrow, withSyncLock, wordToBigInt };
|
|
3778
3811
|
//# sourceMappingURL=index.js.map
|