@miden-sdk/miden-sdk 0.15.0-alpha.5 → 0.15.0-alpha.7
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 +477 -375
- 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 +477 -375
- 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() {
|
|
1862
|
+
this.assertNotTerminated();
|
|
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() {
|
|
1955
1872
|
this.assertNotTerminated();
|
|
1956
|
-
return await this.#inner.
|
|
1873
|
+
return await this.#inner.syncNoteTransport();
|
|
1957
1874
|
}
|
|
1958
1875
|
|
|
1959
1876
|
/**
|
|
@@ -2623,6 +2540,34 @@ const Linking = Object.freeze({
|
|
|
2623
2540
|
Static: "static",
|
|
2624
2541
|
});
|
|
2625
2542
|
|
|
2543
|
+
// Method classification sets — used by scripts/check-method-classification.js to ensure
|
|
2544
|
+
// every WASM export is explicitly categorised. Update when adding new WASM methods.
|
|
2545
|
+
//
|
|
2546
|
+
// Naming note: "SYNC_METHODS" is a historical misnomer. This set groups methods
|
|
2547
|
+
// that are forwarded transparently to the underlying WASM via the Proxy in
|
|
2548
|
+
// `createClientProxy` — meaning they don't need an explicit JS-class wrapper
|
|
2549
|
+
// here. It does NOT mean "the method is synchronous"; several entries
|
|
2550
|
+
// (e.g. newSwapTransactionRequest, newPswapCreateTransactionRequest) are
|
|
2551
|
+
// `async fn` in Rust because they take the client's RNG via an async lock.
|
|
2552
|
+
const SYNC_METHODS = new Set([
|
|
2553
|
+
"buildSwapTag",
|
|
2554
|
+
"createCodeBuilder",
|
|
2555
|
+
"lastAuthError",
|
|
2556
|
+
"newConsumeTransactionRequest",
|
|
2557
|
+
"newMintTransactionRequest",
|
|
2558
|
+
"newPswapCancelTransactionRequest",
|
|
2559
|
+
"newPswapConsumeTransactionRequest",
|
|
2560
|
+
"newPswapCreateTransactionRequest",
|
|
2561
|
+
"newSendTransactionRequest",
|
|
2562
|
+
"newSwapTransactionRequest",
|
|
2563
|
+
"proveBlock",
|
|
2564
|
+
"serializeMockChain",
|
|
2565
|
+
"serializeMockNoteTransportNode",
|
|
2566
|
+
"setDebugMode",
|
|
2567
|
+
"storeIdentifier",
|
|
2568
|
+
"usesMockChain",
|
|
2569
|
+
]);
|
|
2570
|
+
|
|
2626
2571
|
const MOCK_STORE_NAME = "mock_client_db";
|
|
2627
2572
|
|
|
2628
2573
|
const buildTypedArraysExport = (exportObject) => {
|
|
@@ -2736,7 +2681,19 @@ function createClientProxy(instance) {
|
|
|
2736
2681
|
if (target.wasmWebClient && prop in target.wasmWebClient) {
|
|
2737
2682
|
const value = target.wasmWebClient[prop];
|
|
2738
2683
|
if (typeof value === "function") {
|
|
2739
|
-
|
|
2684
|
+
// SYNC_METHODS are safe to bind raw (synchronous in JS, or
|
|
2685
|
+
// documented exceptions). Everything else holds the WASM
|
|
2686
|
+
// client's internal RefCell across its awaits, so it MUST join
|
|
2687
|
+
// `_serializeWasmCall` — an unserialized fallback overlapping
|
|
2688
|
+
// any in-flight call panics with "RefCell already borrowed"
|
|
2689
|
+
// and poisons the instance for every later call.
|
|
2690
|
+
if (typeof prop === "string" && SYNC_METHODS.has(prop)) {
|
|
2691
|
+
return value.bind(target.wasmWebClient);
|
|
2692
|
+
}
|
|
2693
|
+
return (...args) =>
|
|
2694
|
+
target._serializeWasmCall(() =>
|
|
2695
|
+
value.apply(target.wasmWebClient, args)
|
|
2696
|
+
);
|
|
2740
2697
|
}
|
|
2741
2698
|
return value;
|
|
2742
2699
|
}
|
|
@@ -2884,10 +2841,19 @@ class WebClient {
|
|
|
2884
2841
|
this.loadedResolver = resolve;
|
|
2885
2842
|
});
|
|
2886
2843
|
|
|
2887
|
-
// Create a promise that resolves when the worker signals that it is
|
|
2888
|
-
|
|
2844
|
+
// Create a promise that resolves when the worker signals that it is
|
|
2845
|
+
// fully initialized, and rejects if initialization fails. Every
|
|
2846
|
+
// worker-forwarded method awaits `ready` first, so an init failure must
|
|
2847
|
+
// reject it — otherwise those calls would await a promise that never
|
|
2848
|
+
// settles and hang forever.
|
|
2849
|
+
this.ready = new Promise((resolve, reject) => {
|
|
2889
2850
|
this.readyResolver = resolve;
|
|
2851
|
+
this.readyRejecter = reject;
|
|
2890
2852
|
});
|
|
2853
|
+
// Init can fail before any caller awaits `ready`; this no-op handler
|
|
2854
|
+
// suppresses the unhandledrejection event without consuming the
|
|
2855
|
+
// rejection for real awaiters.
|
|
2856
|
+
this.ready.catch(() => {});
|
|
2891
2857
|
|
|
2892
2858
|
// Listen for messages from the worker.
|
|
2893
2859
|
this.worker.addEventListener("message", async (event) => {
|
|
@@ -2951,6 +2917,21 @@ class WebClient {
|
|
|
2951
2917
|
} else {
|
|
2952
2918
|
resolve(result);
|
|
2953
2919
|
}
|
|
2920
|
+
return;
|
|
2921
|
+
}
|
|
2922
|
+
|
|
2923
|
+
// An error with no request attached comes from worker initialization
|
|
2924
|
+
// (INIT is the only requestId-less action that can fail). Reject
|
|
2925
|
+
// `ready` so queued and future method calls fail with the real cause
|
|
2926
|
+
// instead of awaiting forever.
|
|
2927
|
+
if (error && !requestId) {
|
|
2928
|
+
const workerError =
|
|
2929
|
+
error instanceof Error ? error : deserializeError(error);
|
|
2930
|
+
console.error(
|
|
2931
|
+
"WebClient: worker initialization failed:",
|
|
2932
|
+
workerError
|
|
2933
|
+
);
|
|
2934
|
+
this.readyRejecter(workerError);
|
|
2954
2935
|
}
|
|
2955
2936
|
});
|
|
2956
2937
|
|
|
@@ -3291,151 +3272,164 @@ class WebClient {
|
|
|
3291
3272
|
}
|
|
3292
3273
|
|
|
3293
3274
|
async submitNewTransaction(accountId, transactionRequest) {
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3275
|
+
return this._serializeWasmCall(async () => {
|
|
3276
|
+
try {
|
|
3277
|
+
if (!this.worker) {
|
|
3278
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3279
|
+
return await wasmWebClient.submitNewTransaction(
|
|
3280
|
+
accountId,
|
|
3281
|
+
transactionRequest
|
|
3282
|
+
);
|
|
3283
|
+
}
|
|
3302
3284
|
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3285
|
+
const wasm = await getWasmOrThrow();
|
|
3286
|
+
const serializedTransactionRequest = transactionRequest.serialize();
|
|
3287
|
+
const result = await this.callMethodWithWorker(
|
|
3288
|
+
MethodName.SUBMIT_NEW_TRANSACTION,
|
|
3289
|
+
accountId.toString(),
|
|
3290
|
+
serializedTransactionRequest
|
|
3291
|
+
);
|
|
3310
3292
|
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3293
|
+
const transactionResult = wasm.TransactionResult.deserialize(
|
|
3294
|
+
new Uint8Array(result.serializedTransactionResult)
|
|
3295
|
+
);
|
|
3314
3296
|
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3297
|
+
return transactionResult.id();
|
|
3298
|
+
} catch (error) {
|
|
3299
|
+
console.error("INDEX.JS: Error in submitNewTransaction:", error);
|
|
3300
|
+
throw error;
|
|
3301
|
+
}
|
|
3302
|
+
});
|
|
3320
3303
|
}
|
|
3321
3304
|
|
|
3322
3305
|
async submitNewTransactionWithProver(accountId, transactionRequest, prover) {
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3306
|
+
return this._serializeWasmCall(async () => {
|
|
3307
|
+
try {
|
|
3308
|
+
if (!this.worker) {
|
|
3309
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3310
|
+
return await wasmWebClient.submitNewTransactionWithProver(
|
|
3311
|
+
accountId,
|
|
3312
|
+
transactionRequest,
|
|
3313
|
+
prover
|
|
3314
|
+
);
|
|
3315
|
+
}
|
|
3332
3316
|
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3317
|
+
const wasm = await getWasmOrThrow();
|
|
3318
|
+
const serializedTransactionRequest = transactionRequest.serialize();
|
|
3319
|
+
const proverPayload = prover.serialize();
|
|
3320
|
+
const result = await this.callMethodWithWorker(
|
|
3321
|
+
MethodName.SUBMIT_NEW_TRANSACTION_WITH_PROVER,
|
|
3322
|
+
accountId.toString(),
|
|
3323
|
+
serializedTransactionRequest,
|
|
3324
|
+
proverPayload
|
|
3325
|
+
);
|
|
3342
3326
|
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3327
|
+
const transactionResult = wasm.TransactionResult.deserialize(
|
|
3328
|
+
new Uint8Array(result.serializedTransactionResult)
|
|
3329
|
+
);
|
|
3346
3330
|
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3331
|
+
return transactionResult.id();
|
|
3332
|
+
} catch (error) {
|
|
3333
|
+
console.error(
|
|
3334
|
+
"INDEX.JS: Error in submitNewTransactionWithProver:",
|
|
3335
|
+
error
|
|
3336
|
+
);
|
|
3337
|
+
throw error;
|
|
3338
|
+
}
|
|
3339
|
+
});
|
|
3355
3340
|
}
|
|
3356
3341
|
|
|
3357
3342
|
async executeTransaction(accountId, transactionRequest) {
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3343
|
+
return this._serializeWasmCall(async () => {
|
|
3344
|
+
try {
|
|
3345
|
+
if (!this.worker) {
|
|
3346
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3347
|
+
return await wasmWebClient.executeTransaction(
|
|
3348
|
+
accountId,
|
|
3349
|
+
transactionRequest
|
|
3350
|
+
);
|
|
3351
|
+
}
|
|
3366
3352
|
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3353
|
+
const wasm = await getWasmOrThrow();
|
|
3354
|
+
const serializedTransactionRequest = transactionRequest.serialize();
|
|
3355
|
+
const serializedResultBytes = await this.callMethodWithWorker(
|
|
3356
|
+
MethodName.EXECUTE_TRANSACTION,
|
|
3357
|
+
accountId.toString(),
|
|
3358
|
+
serializedTransactionRequest
|
|
3359
|
+
);
|
|
3374
3360
|
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3361
|
+
return wasm.TransactionResult.deserialize(
|
|
3362
|
+
new Uint8Array(serializedResultBytes)
|
|
3363
|
+
);
|
|
3364
|
+
} catch (error) {
|
|
3365
|
+
console.error("INDEX.JS: Error in executeTransaction:", error);
|
|
3366
|
+
throw error;
|
|
3367
|
+
}
|
|
3368
|
+
});
|
|
3382
3369
|
}
|
|
3383
3370
|
|
|
3384
3371
|
async proveTransaction(transactionResult, prover) {
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3372
|
+
return this._serializeWasmCall(async () => {
|
|
3373
|
+
try {
|
|
3374
|
+
if (!this.worker) {
|
|
3375
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3376
|
+
return await wasmWebClient.proveTransaction(
|
|
3377
|
+
transactionResult,
|
|
3378
|
+
prover
|
|
3379
|
+
);
|
|
3380
|
+
}
|
|
3390
3381
|
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3382
|
+
const wasm = await getWasmOrThrow();
|
|
3383
|
+
const serializedTransactionResult = transactionResult.serialize();
|
|
3384
|
+
const proverPayload = prover ? prover.serialize() : null;
|
|
3394
3385
|
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3386
|
+
const serializedProvenBytes = await this.callMethodWithWorker(
|
|
3387
|
+
MethodName.PROVE_TRANSACTION,
|
|
3388
|
+
serializedTransactionResult,
|
|
3389
|
+
proverPayload
|
|
3390
|
+
);
|
|
3400
3391
|
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3392
|
+
return wasm.ProvenTransaction.deserialize(
|
|
3393
|
+
new Uint8Array(serializedProvenBytes)
|
|
3394
|
+
);
|
|
3395
|
+
} catch (error) {
|
|
3396
|
+
console.error("INDEX.JS: Error in proveTransaction:", error);
|
|
3397
|
+
throw error;
|
|
3398
|
+
}
|
|
3399
|
+
});
|
|
3408
3400
|
}
|
|
3409
3401
|
|
|
3410
3402
|
async applyTransaction(transactionResult, submissionHeight) {
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3403
|
+
return this._serializeWasmCall(async () => {
|
|
3404
|
+
try {
|
|
3405
|
+
if (!this.worker) {
|
|
3406
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3407
|
+
return await wasmWebClient.applyTransaction(
|
|
3408
|
+
transactionResult,
|
|
3409
|
+
submissionHeight
|
|
3410
|
+
);
|
|
3411
|
+
}
|
|
3412
|
+
|
|
3413
|
+
const wasm = await getWasmOrThrow();
|
|
3414
|
+
const serializedTransactionResult = transactionResult.serialize();
|
|
3415
|
+
const serializedUpdateBytes = await this.callMethodWithWorker(
|
|
3416
|
+
MethodName.APPLY_TRANSACTION,
|
|
3417
|
+
serializedTransactionResult,
|
|
3416
3418
|
submissionHeight
|
|
3417
3419
|
);
|
|
3418
|
-
}
|
|
3419
3420
|
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
return wasm.TransactionStoreUpdate.deserialize(
|
|
3429
|
-
new Uint8Array(serializedUpdateBytes)
|
|
3430
|
-
);
|
|
3431
|
-
} catch (error) {
|
|
3432
|
-
console.error("INDEX.JS: Error in applyTransaction:", error);
|
|
3433
|
-
throw error;
|
|
3434
|
-
}
|
|
3421
|
+
return wasm.TransactionStoreUpdate.deserialize(
|
|
3422
|
+
new Uint8Array(serializedUpdateBytes)
|
|
3423
|
+
);
|
|
3424
|
+
} catch (error) {
|
|
3425
|
+
console.error("INDEX.JS: Error in applyTransaction:", error);
|
|
3426
|
+
throw error;
|
|
3427
|
+
}
|
|
3428
|
+
});
|
|
3435
3429
|
}
|
|
3436
3430
|
|
|
3437
3431
|
/**
|
|
3438
|
-
* Syncs the client
|
|
3432
|
+
* Syncs the client (NTL followed by chain sync, failing fast on either).
|
|
3439
3433
|
*
|
|
3440
3434
|
* This method coordinates concurrent sync calls using the Web Locks API when available,
|
|
3441
3435
|
* with an in-process mutex fallback for older browsers. If a sync is already in progress,
|
|
@@ -3444,58 +3438,86 @@ class WebClient {
|
|
|
3444
3438
|
* @returns {Promise<SyncSummary>} The sync summary
|
|
3445
3439
|
*/
|
|
3446
3440
|
async syncState() {
|
|
3447
|
-
|
|
3441
|
+
const dbId = this.storeName || "default";
|
|
3442
|
+
const methodId = MethodName.SYNC_STATE;
|
|
3443
|
+
|
|
3444
|
+
try {
|
|
3445
|
+
// The sync lock coalesces concurrent sync callers; the inner
|
|
3446
|
+
// `_serializeWasmCall` keeps the WASM phase from racing any other
|
|
3447
|
+
// serialized method on this instance. Lock order is always
|
|
3448
|
+
// sync lock → chain, so the two can't deadlock.
|
|
3449
|
+
return await withSyncLock(dbId, methodId, async () =>
|
|
3450
|
+
this._serializeWasmCall(async () => {
|
|
3451
|
+
if (!this.worker) {
|
|
3452
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3453
|
+
return await wasmWebClient.syncStateImpl();
|
|
3454
|
+
}
|
|
3455
|
+
const wasm = await getWasmOrThrow();
|
|
3456
|
+
const serializedSyncSummaryBytes =
|
|
3457
|
+
await this.callMethodWithWorker(methodId);
|
|
3458
|
+
return wasm.SyncSummary.deserialize(
|
|
3459
|
+
new Uint8Array(serializedSyncSummaryBytes)
|
|
3460
|
+
);
|
|
3461
|
+
})
|
|
3462
|
+
);
|
|
3463
|
+
} catch (error) {
|
|
3464
|
+
console.error("INDEX.JS: Error in syncState:", error);
|
|
3465
|
+
throw error;
|
|
3466
|
+
}
|
|
3448
3467
|
}
|
|
3449
3468
|
|
|
3450
3469
|
/**
|
|
3451
|
-
*
|
|
3452
|
-
*
|
|
3453
|
-
* This method coordinates concurrent sync calls using the Web Locks API when available,
|
|
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).
|
|
3470
|
+
* Fetches private notes from the Note Transport Layer.
|
|
3456
3471
|
*
|
|
3457
|
-
* @
|
|
3458
|
-
* @returns {Promise<SyncSummary>} The sync summary
|
|
3472
|
+
* @returns {Promise<void>}
|
|
3459
3473
|
*/
|
|
3460
|
-
async
|
|
3461
|
-
// Use storeName as the database ID for lock coordination
|
|
3474
|
+
async syncNoteTransport() {
|
|
3462
3475
|
const dbId = this.storeName || "default";
|
|
3476
|
+
const methodId = MethodName.SYNC_NOTE_TRANSPORT;
|
|
3463
3477
|
|
|
3464
3478
|
try {
|
|
3465
|
-
|
|
3466
|
-
|
|
3479
|
+
await withSyncLock(dbId, methodId, async () =>
|
|
3480
|
+
this._serializeWasmCall(async () => {
|
|
3481
|
+
if (!this.worker) {
|
|
3482
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3483
|
+
await wasmWebClient.syncNoteTransportImpl();
|
|
3484
|
+
} else {
|
|
3485
|
+
await this.callMethodWithWorker(methodId);
|
|
3486
|
+
}
|
|
3487
|
+
})
|
|
3488
|
+
);
|
|
3489
|
+
} catch (error) {
|
|
3490
|
+
console.error("INDEX.JS: Error in syncNoteTransport:", error);
|
|
3491
|
+
throw error;
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3467
3494
|
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3495
|
+
/**
|
|
3496
|
+
* Syncs on-chain state only (no NTL fetch).
|
|
3497
|
+
*
|
|
3498
|
+
* @returns {Promise<SyncSummary>}
|
|
3499
|
+
*/
|
|
3500
|
+
async syncChain() {
|
|
3501
|
+
const dbId = this.storeName || "default";
|
|
3502
|
+
const methodId = MethodName.SYNC_CHAIN;
|
|
3472
3503
|
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3504
|
+
try {
|
|
3505
|
+
return await withSyncLock(dbId, methodId, async () =>
|
|
3506
|
+
this._serializeWasmCall(async () => {
|
|
3507
|
+
if (!this.worker) {
|
|
3508
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3509
|
+
return await wasmWebClient.syncChainImpl();
|
|
3510
|
+
}
|
|
3480
3511
|
const wasm = await getWasmOrThrow();
|
|
3481
|
-
const serializedSyncSummaryBytes =
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
result = wasm.SyncSummary.deserialize(
|
|
3512
|
+
const serializedSyncSummaryBytes =
|
|
3513
|
+
await this.callMethodWithWorker(methodId);
|
|
3514
|
+
return wasm.SyncSummary.deserialize(
|
|
3485
3515
|
new Uint8Array(serializedSyncSummaryBytes)
|
|
3486
3516
|
);
|
|
3487
|
-
}
|
|
3488
|
-
|
|
3489
|
-
// Release the lock with the result
|
|
3490
|
-
releaseSyncLock(dbId, result);
|
|
3491
|
-
return result;
|
|
3492
|
-
} catch (error) {
|
|
3493
|
-
// Release the lock with the error
|
|
3494
|
-
releaseSyncLockWithError(dbId, error);
|
|
3495
|
-
throw error;
|
|
3496
|
-
}
|
|
3517
|
+
})
|
|
3518
|
+
);
|
|
3497
3519
|
} catch (error) {
|
|
3498
|
-
console.error("INDEX.JS: Error in
|
|
3520
|
+
console.error("INDEX.JS: Error in syncChain:", error);
|
|
3499
3521
|
throw error;
|
|
3500
3522
|
}
|
|
3501
3523
|
}
|
|
@@ -3531,9 +3553,23 @@ class MockWebClient extends WebClient {
|
|
|
3531
3553
|
}
|
|
3532
3554
|
|
|
3533
3555
|
initializeWorker() {
|
|
3556
|
+
// Pass `numThreads` exactly like the real INIT path: every prove runs
|
|
3557
|
+
// inside the worker's own WASM instance, and rayon's pool is
|
|
3558
|
+
// per-instance — without this, mock-client proving (including the
|
|
3559
|
+
// integration suite) silently runs single-threaded.
|
|
3560
|
+
let numThreads = 1;
|
|
3561
|
+
try {
|
|
3562
|
+
if (
|
|
3563
|
+
typeof self !== "undefined" &&
|
|
3564
|
+
self.crossOriginIsolated &&
|
|
3565
|
+
navigator?.hardwareConcurrency
|
|
3566
|
+
) {
|
|
3567
|
+
numThreads = navigator.hardwareConcurrency;
|
|
3568
|
+
}
|
|
3569
|
+
} catch {}
|
|
3534
3570
|
this.worker.postMessage({
|
|
3535
3571
|
action: WorkerAction.INIT_MOCK,
|
|
3536
|
-
args: [this.seed, this.logLevel],
|
|
3572
|
+
args: [this.seed, this.logLevel, numThreads],
|
|
3537
3573
|
});
|
|
3538
3574
|
}
|
|
3539
3575
|
|
|
@@ -3584,59 +3620,125 @@ class MockWebClient extends WebClient {
|
|
|
3584
3620
|
* @returns {Promise<SyncSummary>} The sync summary
|
|
3585
3621
|
*/
|
|
3586
3622
|
async syncState() {
|
|
3587
|
-
|
|
3623
|
+
const dbId = this.storeName || "mock";
|
|
3624
|
+
const methodId = MethodName.SYNC_STATE;
|
|
3625
|
+
|
|
3626
|
+
try {
|
|
3627
|
+
return await withSyncLock(dbId, methodId, async () =>
|
|
3628
|
+
this._serializeWasmCall(async () => {
|
|
3629
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3630
|
+
|
|
3631
|
+
if (!this.worker) {
|
|
3632
|
+
return await wasmWebClient.syncStateImpl();
|
|
3633
|
+
}
|
|
3634
|
+
|
|
3635
|
+
const serializedMockChain = (await wasmWebClient.serializeMockChain())
|
|
3636
|
+
.buffer;
|
|
3637
|
+
const serializedMockNoteTransportNode = (
|
|
3638
|
+
await wasmWebClient.serializeMockNoteTransportNode()
|
|
3639
|
+
).buffer;
|
|
3640
|
+
|
|
3641
|
+
const wasm = await getWasmOrThrow();
|
|
3642
|
+
const serializedSyncSummaryBytes = await this.callMethodWithWorker(
|
|
3643
|
+
MethodName.SYNC_STATE_MOCK,
|
|
3644
|
+
serializedMockChain,
|
|
3645
|
+
serializedMockNoteTransportNode
|
|
3646
|
+
);
|
|
3647
|
+
return wasm.SyncSummary.deserialize(
|
|
3648
|
+
new Uint8Array(serializedSyncSummaryBytes)
|
|
3649
|
+
);
|
|
3650
|
+
})
|
|
3651
|
+
);
|
|
3652
|
+
} catch (error) {
|
|
3653
|
+
console.error("INDEX.JS: Error in syncState:", error);
|
|
3654
|
+
throw error;
|
|
3655
|
+
}
|
|
3588
3656
|
}
|
|
3589
3657
|
|
|
3590
3658
|
/**
|
|
3591
|
-
* Syncs the mock
|
|
3659
|
+
* Syncs only the on-chain mock state (no note transport fetch).
|
|
3592
3660
|
*
|
|
3593
|
-
*
|
|
3594
|
-
*
|
|
3661
|
+
* In worker mode, the main-thread mock chain + note-transport-node state
|
|
3662
|
+
* is serialized and shipped to the worker before the sync, so a prior
|
|
3663
|
+
* `proveBlock()` on the main thread is reflected in the worker's WASM
|
|
3664
|
+
* client. The no-worker path uses the main-thread WASM client directly.
|
|
3665
|
+
*
|
|
3666
|
+
* @returns {Promise<SyncSummary>}
|
|
3595
3667
|
*/
|
|
3596
|
-
async
|
|
3668
|
+
async syncChain() {
|
|
3597
3669
|
const dbId = this.storeName || "mock";
|
|
3670
|
+
const methodId = MethodName.SYNC_CHAIN;
|
|
3598
3671
|
|
|
3599
3672
|
try {
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
return lockHandle.coalescedResult;
|
|
3604
|
-
}
|
|
3673
|
+
return await withSyncLock(dbId, methodId, async () =>
|
|
3674
|
+
this._serializeWasmCall(async () => {
|
|
3675
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3605
3676
|
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3677
|
+
if (!this.worker) {
|
|
3678
|
+
return await wasmWebClient.syncChainImpl();
|
|
3679
|
+
}
|
|
3609
3680
|
|
|
3610
|
-
|
|
3611
|
-
result = await wasmWebClient.syncStateImpl();
|
|
3612
|
-
} else {
|
|
3613
|
-
let serializedMockChain = (await wasmWebClient.serializeMockChain())
|
|
3681
|
+
const serializedMockChain = (await wasmWebClient.serializeMockChain())
|
|
3614
3682
|
.buffer;
|
|
3615
|
-
|
|
3683
|
+
const serializedMockNoteTransportNode = (
|
|
3616
3684
|
await wasmWebClient.serializeMockNoteTransportNode()
|
|
3617
3685
|
).buffer;
|
|
3618
3686
|
|
|
3619
3687
|
const wasm = await getWasmOrThrow();
|
|
3620
|
-
|
|
3621
3688
|
const serializedSyncSummaryBytes = await this.callMethodWithWorker(
|
|
3622
|
-
MethodName.
|
|
3689
|
+
MethodName.SYNC_CHAIN_MOCK,
|
|
3623
3690
|
serializedMockChain,
|
|
3624
3691
|
serializedMockNoteTransportNode
|
|
3625
3692
|
);
|
|
3626
|
-
|
|
3627
|
-
result = wasm.SyncSummary.deserialize(
|
|
3693
|
+
return wasm.SyncSummary.deserialize(
|
|
3628
3694
|
new Uint8Array(serializedSyncSummaryBytes)
|
|
3629
3695
|
);
|
|
3630
|
-
}
|
|
3696
|
+
})
|
|
3697
|
+
);
|
|
3698
|
+
} catch (error) {
|
|
3699
|
+
console.error("INDEX.JS: Error in syncChain:", error);
|
|
3700
|
+
throw error;
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3631
3703
|
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3704
|
+
/**
|
|
3705
|
+
* Syncs only the mock note-transport state (no chain fetch).
|
|
3706
|
+
*
|
|
3707
|
+
* Mirrors {@link MockWebClient#syncChain}: in worker mode, the
|
|
3708
|
+
* main-thread mock chain + note-transport-node state is serialized
|
|
3709
|
+
* and shipped to the worker first.
|
|
3710
|
+
*
|
|
3711
|
+
* @returns {Promise<void>}
|
|
3712
|
+
*/
|
|
3713
|
+
async syncNoteTransport() {
|
|
3714
|
+
const dbId = this.storeName || "mock";
|
|
3715
|
+
const methodId = MethodName.SYNC_NOTE_TRANSPORT;
|
|
3716
|
+
|
|
3717
|
+
try {
|
|
3718
|
+
await withSyncLock(dbId, methodId, async () =>
|
|
3719
|
+
this._serializeWasmCall(async () => {
|
|
3720
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
3721
|
+
|
|
3722
|
+
if (!this.worker) {
|
|
3723
|
+
await wasmWebClient.syncNoteTransportImpl();
|
|
3724
|
+
return;
|
|
3725
|
+
}
|
|
3726
|
+
|
|
3727
|
+
const serializedMockChain = (await wasmWebClient.serializeMockChain())
|
|
3728
|
+
.buffer;
|
|
3729
|
+
const serializedMockNoteTransportNode = (
|
|
3730
|
+
await wasmWebClient.serializeMockNoteTransportNode()
|
|
3731
|
+
).buffer;
|
|
3732
|
+
|
|
3733
|
+
await this.callMethodWithWorker(
|
|
3734
|
+
MethodName.SYNC_NOTE_TRANSPORT_MOCK,
|
|
3735
|
+
serializedMockChain,
|
|
3736
|
+
serializedMockNoteTransportNode
|
|
3737
|
+
);
|
|
3738
|
+
})
|
|
3739
|
+
);
|
|
3638
3740
|
} catch (error) {
|
|
3639
|
-
console.error("INDEX.JS: Error in
|
|
3741
|
+
console.error("INDEX.JS: Error in syncNoteTransport:", error);
|
|
3640
3742
|
throw error;
|
|
3641
3743
|
}
|
|
3642
3744
|
}
|
|
@@ -3774,5 +3876,5 @@ MidenClient._MockWasmWebClient = MockWebClient;
|
|
|
3774
3876
|
MidenClient._getWasmOrThrow = getWasmOrThrow;
|
|
3775
3877
|
_setWebClient(WebClient);
|
|
3776
3878
|
|
|
3777
|
-
export { AccountType, AuthScheme, CompilerResource, Linking, MidenArrays, MidenClient, MockWebClient as MockWasmWebClient, MockWebClient, NoteVisibility, StorageMode, StorageResult, StorageView, WebClient as WasmWebClient, buildSwapTag, createP2IDENote, createP2IDNote, getWasmOrThrow, wordToBigInt };
|
|
3879
|
+
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
3880
|
//# sourceMappingURL=index.js.map
|