@miden-sdk/miden-sdk 0.14.3 → 0.14.5

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/index.js CHANGED
@@ -1,5 +1,6 @@
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, NetworkType, Note, NoteAndArgs, NoteAndArgsArray, NoteArray, NoteAssets, NoteAttachment, NoteAttachmentKind, 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, 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, setupLogging } from './Cargo-DanGI-a8.js';
2
+ import { AccountArray as AccountArray$1, AccountIdArray as AccountIdArray$1, FeltArray as FeltArray$1, ForeignAccountArray as ForeignAccountArray$1, NoteAndArgsArray as NoteAndArgsArray$1, NoteArray as NoteArray$1, NoteIdAndArgsArray as NoteIdAndArgsArray$1, NoteRecipientArray as NoteRecipientArray$1, OutputNoteArray as OutputNoteArray$1, StorageSlotArray as StorageSlotArray$1, TransactionScriptInputPairArray as TransactionScriptInputPairArray$1 } from './Cargo-M3382VZc.js';
3
+ export { Account, AccountBuilder, AccountBuilderResult, AccountCode, AccountComponent, AccountComponentCode, AccountDelta, AccountFile, AccountHeader, AccountId, AccountInterface, AccountProof, AccountReader, AccountStatus, AccountStorage, AccountStorageDelta, AccountStorageMode, AccountStorageRequirements, AccountVaultDelta, Address, AdviceInputs, AdviceMap, AssetVault, AuthFalcon512RpoMultisigConfig, AuthSecretKey, BasicFungibleFaucetComponent, BlockHeader, CodeBuilder, CommittedNote, ConsumableNoteRecord, Endpoint, ExecutedTransaction, Felt, FetchedAccount, FetchedNote, FlattenedU8Vec, ForeignAccount, FungibleAsset, FungibleAssetDelta, FungibleAssetDeltaItem, GetProceduresResultItem, InputNote, InputNoteRecord, InputNoteState, InputNotes, IntoUnderlyingByteSource, IntoUnderlyingSink, IntoUnderlyingSource, JsAccountUpdate, JsStateSyncUpdate, JsStorageMapEntry, JsStorageSlot, JsVaultAsset, Library, MerklePath, NetworkId, NetworkType, Note, NoteAndArgs, NoteAssets, NoteAttachment, NoteAttachmentKind, NoteAttachmentScheme, NoteConsumability, NoteConsumptionStatus, NoteDetails, NoteDetailsAndTag, NoteDetailsAndTagArray, NoteExecutionHint, NoteExportFormat, NoteFile, NoteFilter, NoteFilterTypes, NoteHeader, NoteId, NoteIdAndArgs, NoteInclusionProof, NoteLocation, NoteMetadata, NoteRecipient, NoteScript, NoteStorage, NoteSyncBlock, NoteSyncInfo, NoteTag, NoteType, OutputNote, OutputNoteRecord, OutputNoteState, OutputNotes, Package, PartialNote, Poseidon2, ProcedureThreshold, Program, ProvenTransaction, PublicKey, RpcClient, Rpo256, SerializedInputNoteData, SerializedOutputNoteData, SerializedTransactionData, Signature, SigningInputs, SigningInputsType, SlotAndKeys, SparseMerklePath, StorageMap, StorageMapEntry, StorageMapInfo, StorageMapUpdate, StorageSlot, SyncSummary, TestUtils, TokenSymbol, TransactionArgs, TransactionFilter, TransactionId, TransactionProver, TransactionRecord, TransactionRequest, TransactionRequestBuilder, TransactionResult, TransactionScript, TransactionScriptInputPair, TransactionStatus, TransactionStoreUpdate, TransactionSummary, WebClient, WebKeystoreApi, Word, createAuthFalcon512RpoMultisig, exportStore, importStore, initSync, setupLogging } from './Cargo-M3382VZc.js';
3
4
 
4
5
  const WorkerAction = Object.freeze({
5
6
  INIT: "init",
@@ -345,18 +346,31 @@ function resolveStorageMode(mode, wasm) {
345
346
  }
346
347
 
347
348
  /**
348
- * Resolves an auth scheme string to a WASM AuthScheme enum value.
349
+ * Resolves an auth scheme string to a WASM `AuthScheme` enum numeric value.
349
350
  *
350
- * @param {string | undefined} scheme - "falcon" or "ecdsa". Defaults to "falcon".
351
- * @param {object} wasm - The WASM module.
352
- * @returns {number} The AuthScheme enum value.
351
+ * The public `AuthScheme` constant exposes SDK-friendly strings
352
+ * (`"falcon"` / `"ecdsa"`), but low-level wasm-bindgen methods such as
353
+ * `AccountComponent.createAuthComponentFromCommitment(commitment, scheme)`
354
+ * expect the numeric variant from the Rust `AuthScheme` enum. This helper
355
+ * bridges the two so callers never touch wasm-bindgen internals directly.
356
+ *
357
+ * `wasm` is optional: when provided (by internal callers who already have
358
+ * the module loaded), the numeric value is read from the binding itself,
359
+ * keeping the mapping robust if wasm-bindgen ever renumbers the enum. When
360
+ * omitted (public callers who don't have a handle to the WASM module), the
361
+ * hardcoded discriminants below are used — these are pinned to the Rust
362
+ * enum order by a cross-check test in `test/account_component.test.ts`.
363
+ *
364
+ * @param {"falcon" | "ecdsa" | undefined} scheme - Defaults to `"falcon"`.
365
+ * @param {object} [wasm] - Optional WASM module handle.
366
+ * @returns {number} The AuthScheme enum numeric value (1 or 2).
353
367
  */
354
368
  function resolveAuthScheme(scheme, wasm) {
355
369
  if (scheme === "ecdsa") {
356
- return wasm.AuthScheme.AuthEcdsaK256Keccak;
370
+ return wasm?.AuthScheme?.AuthEcdsaK256Keccak ?? 1;
357
371
  }
358
372
  if (scheme === "falcon" || scheme == null) {
359
- return wasm.AuthScheme.AuthRpoFalcon512;
373
+ return wasm?.AuthScheme?.AuthRpoFalcon512 ?? 2;
360
374
  }
361
375
  throw new Error(
362
376
  `Unknown auth scheme: "${scheme}". Expected "falcon" or "ecdsa".`
@@ -874,6 +888,11 @@ class TransactionsResource {
874
888
  ({ accountId, request } = await this.#buildSwapRequest(opts, wasm));
875
889
  break;
876
890
  }
891
+ case "custom": {
892
+ accountId = resolveAccountRef(opts.account, wasm);
893
+ request = opts.request;
894
+ break;
895
+ }
877
896
  default:
878
897
  throw new Error(`Unknown preview operation: ${opts.operation}`);
879
898
  }
@@ -1190,8 +1209,13 @@ class TransactionsResource {
1190
1209
  async #submitOrSubmitWithProver(accountId, request, perCallProver) {
1191
1210
  const result = await this.#inner.executeTransaction(accountId, request);
1192
1211
  const prover = perCallProver ?? this.#client.defaultProver;
1212
+ // Use proveTransactionWithProver (by-reference) when a prover is
1213
+ // provided, so the JS-side handle is NOT consumed by wasm-bindgen.
1214
+ // Passing the prover by value would transfer ownership and invalidate
1215
+ // the JS object after one call, causing silent fallback to local
1216
+ // proving on reuse.
1193
1217
  const proven = prover
1194
- ? await this.#inner.proveTransaction(result, prover)
1218
+ ? await this.#inner.proveTransactionWithProver(result, prover)
1195
1219
  : await this.#inner.proveTransaction(result);
1196
1220
  const txId = result.id();
1197
1221
  const height = await this.#inner.submitProvenTransaction(proven, result);
@@ -1630,6 +1654,32 @@ class MidenClient {
1630
1654
  });
1631
1655
  }
1632
1656
 
1657
+ /**
1658
+ * Resolves once the WASM module is initialized and safe to use.
1659
+ *
1660
+ * Idempotent and shared across callers: the underlying loader memoizes the
1661
+ * in-flight promise, so concurrent `ready()` calls await the same
1662
+ * initialization and post-init callers resolve immediately from a cached
1663
+ * module. Safe to call from `MidenProvider`, tutorial helpers, and any
1664
+ * other consumer simultaneously.
1665
+ *
1666
+ * Useful on the `/lazy` entry (e.g. Next.js / Capacitor), where no
1667
+ * top-level await runs at import time. On the default (eager) entry this
1668
+ * is redundant — importing the module already awaits WASM — but calling it
1669
+ * is still harmless.
1670
+ *
1671
+ * @returns {Promise<void>} Resolves when WASM is initialized.
1672
+ */
1673
+ static async ready() {
1674
+ const getWasm = MidenClient._getWasmOrThrow;
1675
+ if (!getWasm) {
1676
+ throw new Error(
1677
+ "MidenClient not initialized. Import from the SDK package entry point."
1678
+ );
1679
+ }
1680
+ await getWasm();
1681
+ }
1682
+
1633
1683
  /**
1634
1684
  * Creates a mock client for testing.
1635
1685
  *
@@ -1686,6 +1736,54 @@ class MidenClient {
1686
1736
  return await this.#inner.getSyncHeight();
1687
1737
  }
1688
1738
 
1739
+ /**
1740
+ * Resolves once every serialized WASM call that was already on the
1741
+ * internal `_serializeWasmCall` chain when `waitForIdle()` was called
1742
+ * (execute, submit, prove, apply, sync, or account creation) has
1743
+ * settled. Use this from callers that need to perform a non-WASM-side
1744
+ * action — e.g. clearing an in-memory auth key on wallet lock — after
1745
+ * the kernel finishes, so its auth callback doesn't race with the key
1746
+ * being cleared.
1747
+ *
1748
+ * Does NOT wait for calls enqueued after `waitForIdle()` returns —
1749
+ * intentional, so a caller can drain and proceed without being blocked
1750
+ * indefinitely by concurrent workload.
1751
+ *
1752
+ * Caveat for `syncState`: `syncStateWithTimeout` awaits the sync lock
1753
+ * (`acquireSyncLock`, which uses Web Locks) BEFORE putting its WASM
1754
+ * call onto the chain, so a `syncState` that is queued on the sync
1755
+ * lock — but has not yet begun its WASM phase — is not visible to
1756
+ * `waitForIdle` and will not be awaited. Other methods (`newWallet`,
1757
+ * `executeTransaction`, etc.) route through the chain synchronously
1758
+ * on call and are always observed.
1759
+ *
1760
+ * Safe to call at any time; returns immediately if nothing was in
1761
+ * flight.
1762
+ *
1763
+ * @returns {Promise<void>}
1764
+ */
1765
+ async waitForIdle() {
1766
+ this.assertNotTerminated();
1767
+ await this.#inner.waitForIdle();
1768
+ }
1769
+
1770
+ /**
1771
+ * Returns the raw JS value that the most recent sign-callback invocation
1772
+ * threw, or `null` if the last sign call succeeded (or no call has
1773
+ * happened yet).
1774
+ *
1775
+ * Useful for recovering structured metadata (e.g. a `reason: 'locked'`
1776
+ * property) that the kernel-level `auth::request` diagnostic would
1777
+ * otherwise erase. Call immediately after catching a failed
1778
+ * `transactions.submit` / `transactions.send` / `transactions.consume`.
1779
+ *
1780
+ * @returns {any} The raw thrown value, or `null`.
1781
+ */
1782
+ lastAuthError() {
1783
+ this.assertNotTerminated();
1784
+ return this.#inner.lastAuthError();
1785
+ }
1786
+
1689
1787
  /**
1690
1788
  * Terminates the underlying Web Worker. After this, all method calls will throw.
1691
1789
  */
@@ -1922,6 +2020,57 @@ function buildNoteAssets(assets, wasm) {
1922
2020
  return new wasm.NoteAssets(fungibleAssets);
1923
2021
  }
1924
2022
 
2023
+ /**
2024
+ * Non-consuming wrappers for wasm-bindgen-generated array classes.
2025
+ *
2026
+ * The default wasm-bindgen-generated constructor for an exported `Vec<T>`
2027
+ * parameter (e.g. `pub fn new(elements: Option<Vec<Note>>) -> Self`) takes
2028
+ * each input element by value: the Rust-side value is moved out of the
2029
+ * caller's JS handle. The handle is left dangling — its `__wbg_ptr` field
2030
+ * is unchanged so the JS object looks fine, but any subsequent method call
2031
+ * panics inside WASM with the opaque `"null pointer passed to rust"`
2032
+ * error from wasm-bindgen.
2033
+ *
2034
+ * That's a footgun for JS users, who don't expect "this object can no
2035
+ * longer be used" semantics from a constructor like
2036
+ * `new NoteArray([note])`. So we wrap each affected array with a class
2037
+ * that builds the same array via `push(&T)` — which already borrows +
2038
+ * clones — leaving the originals fully usable afterwards.
2039
+ *
2040
+ * The wrapper extends the wasm-bindgen base class, so `instanceof` checks
2041
+ * (including `_assertClass(...)` in other auto-generated wasm-bindgen
2042
+ * methods) keep working transparently.
2043
+ */
2044
+
2045
+
2046
+ function makeSafeArray(Base) {
2047
+ return class extends Base {
2048
+ constructor(elements) {
2049
+ super(); // empty Rust Vec — no consume
2050
+ if (Array.isArray(elements)) {
2051
+ for (const el of elements) {
2052
+ // push(&T) on Base borrows and clones — input handles stay valid.
2053
+ this.push(el);
2054
+ }
2055
+ }
2056
+ }
2057
+ };
2058
+ }
2059
+
2060
+ const AccountArray = makeSafeArray(AccountArray$1);
2061
+ const AccountIdArray = makeSafeArray(AccountIdArray$1);
2062
+ const FeltArray = makeSafeArray(FeltArray$1);
2063
+ const ForeignAccountArray = makeSafeArray(ForeignAccountArray$1);
2064
+ const NoteAndArgsArray = makeSafeArray(NoteAndArgsArray$1);
2065
+ const NoteArray = makeSafeArray(NoteArray$1);
2066
+ const NoteIdAndArgsArray = makeSafeArray(NoteIdAndArgsArray$1);
2067
+ const NoteRecipientArray = makeSafeArray(NoteRecipientArray$1);
2068
+ const OutputNoteArray = makeSafeArray(OutputNoteArray$1);
2069
+ const StorageSlotArray = makeSafeArray(StorageSlotArray$1);
2070
+ const TransactionScriptInputPairArray = makeSafeArray(
2071
+ TransactionScriptInputPairArray$1
2072
+ );
2073
+
1925
2074
  const AccountType = Object.freeze({
1926
2075
  // WASM-compatible numeric values — usable with AccountBuilder directly
1927
2076
  FungibleFaucet: 0,
@@ -1956,6 +2105,43 @@ const Linking = Object.freeze({
1956
2105
  Static: "static",
1957
2106
  });
1958
2107
 
2108
+ // Method classification sets — used by scripts/check-method-classification.js to ensure
2109
+ // every WASM export is explicitly categorised. Update when adding new WASM methods.
2110
+ //
2111
+ // Note on `SYNC_METHODS`: the classifier is "synchronous in JS" — i.e.
2112
+ // `pub fn ...` in Rust, not `pub async fn ...`. Two sub-cases:
2113
+ // 1. Factory methods that return a non-Promise value (`accountReader`
2114
+ // returns `AccountReader`; the transaction-request builders return
2115
+ // `TransactionRequestBuilder`; `createCodeBuilder` returns a builder).
2116
+ // Wrapping these in `_serializeWasmCall` would turn their return
2117
+ // value into `Promise<T>` and break callers that use the result
2118
+ // immediately (e.g. `const reader = client.accountReader(id);
2119
+ // await reader.nonce();`).
2120
+ // 2. Sync methods that still take `&mut self` in Rust (`proveBlock`,
2121
+ // `serializeMockChain`, `setDebugMode`). Safe to opt out because JS
2122
+ // is single-threaded — the event loop cannot interleave another
2123
+ // call during their synchronous execution, so the RefCell borrow
2124
+ // is always released before any other borrow can start.
2125
+ // Do NOT move a sync-in-JS method into `WRITE_METHODS` / `READ_METHODS`
2126
+ // just because it takes `&mut self` or `&self`; wrapping changes its
2127
+ // return shape and breaks every caller.
2128
+ const SYNC_METHODS = new Set([
2129
+ "accountReader",
2130
+ "buildSwapTag",
2131
+ "createCodeBuilder",
2132
+ "lastAuthError",
2133
+ "newConsumeTransactionRequest",
2134
+ "newMintTransactionRequest",
2135
+ "newSendTransactionRequest",
2136
+ "newSwapTransactionRequest",
2137
+ "proveBlock",
2138
+ "serializeMockChain",
2139
+ "serializeMockNoteTransportNode",
2140
+ "setDebugMode",
2141
+ "storeIdentifier",
2142
+ "usesMockChain",
2143
+ ]);
2144
+
1959
2145
  const MOCK_STORE_NAME = "mock_client_db";
1960
2146
 
1961
2147
  const buildTypedArraysExport = (exportObject) => {
@@ -2056,6 +2242,16 @@ const getWasmOrThrow = async () => {
2056
2242
  /**
2057
2243
  * Create a Proxy that forwards missing properties to the underlying WASM
2058
2244
  * WebClient.
2245
+ *
2246
+ * Async proxy-fallback methods (every WASM method that borrows the
2247
+ * WebClient's RefCell — reads included, since `&self` and `&mut self` both
2248
+ * trip wasm-bindgen's "recursive use of an object detected" panic if
2249
+ * another borrow is live) are routed through `_serializeWasmCall` so they
2250
+ * queue on the same chain as the explicitly-wrapped methods.
2251
+ *
2252
+ * `SYNC_METHODS` opts out: they are synchronous in JS and wrapping them
2253
+ * would change their return type to `Promise<T>`, which is a breaking
2254
+ * change for consumers that use them as plain getters or builders.
2059
2255
  */
2060
2256
  function createClientProxy(instance) {
2061
2257
  return new Proxy(instance, {
@@ -2066,7 +2262,13 @@ function createClientProxy(instance) {
2066
2262
  if (target.wasmWebClient && prop in target.wasmWebClient) {
2067
2263
  const value = target.wasmWebClient[prop];
2068
2264
  if (typeof value === "function") {
2069
- return value.bind(target.wasmWebClient);
2265
+ if (typeof prop === "string" && SYNC_METHODS.has(prop)) {
2266
+ return value.bind(target.wasmWebClient);
2267
+ }
2268
+ return (...args) =>
2269
+ target._serializeWasmCall(() =>
2270
+ value.apply(target.wasmWebClient, args)
2271
+ );
2070
2272
  }
2071
2273
  return value;
2072
2274
  }
@@ -2297,6 +2499,13 @@ class WebClient {
2297
2499
  * Serialize a WASM call that requires exclusive (&mut self) access.
2298
2500
  * Concurrent calls are queued and executed one at a time.
2299
2501
  *
2502
+ * Wraps both the direct (in-thread) path and the worker-dispatched path.
2503
+ * On the worker path this is redundant with the worker's own message queue,
2504
+ * but harmless (the chain resolves immediately on the main thread once the
2505
+ * worker's postMessage returns). On the direct path it is load-bearing —
2506
+ * without it, concurrent main-thread callers would panic with
2507
+ * "recursive use of an object detected" (wasm-bindgen's internal RefCell).
2508
+ *
2300
2509
  * @param {() => Promise<any>} fn - The async function to execute.
2301
2510
  * @returns {Promise<any>} The result of fn.
2302
2511
  */
@@ -2306,6 +2515,35 @@ class WebClient {
2306
2515
  return result;
2307
2516
  }
2308
2517
 
2518
+ /**
2519
+ * Returns a promise that resolves once every serialized WASM call that
2520
+ * was already on `_wasmCallChain` when `waitForIdle()` was called has
2521
+ * settled. Use this from callers that need to perform a non-WASM-side
2522
+ * action (e.g. clear an in-memory auth key) AFTER any in-flight
2523
+ * execute / submit / sync has completed, so the WASM kernel's auth
2524
+ * callback doesn't race with the key being cleared.
2525
+ *
2526
+ * Does NOT wait for calls enqueued after `waitForIdle()` returns —
2527
+ * this is intentional, so a caller can drain and then proceed without
2528
+ * being blocked indefinitely by a concurrent workload.
2529
+ *
2530
+ * Caveat for `syncState`: `syncStateWithTimeout` awaits
2531
+ * `acquireSyncLock` (Web Locks) BEFORE wrapping its WASM call in
2532
+ * `_serializeWasmCall`, so a sync that is queued on the sync lock but
2533
+ * has not yet reached its WASM phase is not on the chain and will not
2534
+ * be awaited. Every other serialized method (`executeTransaction`,
2535
+ * `newWallet`, `submitNewTransaction`, `proveTransaction`,
2536
+ * `applyTransaction`, and the proxy-fallback reads) routes through
2537
+ * the chain synchronously on call and is always observed.
2538
+ *
2539
+ * @returns {Promise<void>}
2540
+ */
2541
+ async waitForIdle() {
2542
+ // Chain on `_wasmCallChain`; by the time this resolves, any in-flight
2543
+ // serialized call has settled. Catch so the chain state doesn't leak.
2544
+ await this._wasmCallChain.catch(() => {});
2545
+ }
2546
+
2309
2547
  // TODO: This will soon conflict with some changes in main.
2310
2548
  // More context here:
2311
2549
  // https://github.com/0xMiden/miden-client/pull/1645?notification_referrer_id=NT_kwHOA1yg7NoAJVJlcG9zaXRvcnk7NjU5MzQzNzAyO0lzc3VlOzM3OTY4OTU1Nzk&notifications_query=is%3Aunread#discussion_r2696075480
@@ -2511,147 +2749,171 @@ class WebClient {
2511
2749
  }
2512
2750
 
2513
2751
  async submitNewTransaction(accountId, transactionRequest) {
2514
- try {
2515
- if (!this.worker) {
2516
- const wasmWebClient = await this.getWasmWebClient();
2517
- return await wasmWebClient.submitNewTransaction(
2518
- accountId,
2519
- transactionRequest
2520
- );
2521
- }
2752
+ return this._serializeWasmCall(async () => {
2753
+ try {
2754
+ if (!this.worker) {
2755
+ const wasmWebClient = await this.getWasmWebClient();
2756
+ return await wasmWebClient.submitNewTransaction(
2757
+ accountId,
2758
+ transactionRequest
2759
+ );
2760
+ }
2522
2761
 
2523
- const wasm = await getWasmOrThrow();
2524
- const serializedTransactionRequest = transactionRequest.serialize();
2525
- const result = await this.callMethodWithWorker(
2526
- MethodName.SUBMIT_NEW_TRANSACTION,
2527
- accountId.toString(),
2528
- serializedTransactionRequest
2529
- );
2762
+ const wasm = await getWasmOrThrow();
2763
+ const serializedTransactionRequest = transactionRequest.serialize();
2764
+ const result = await this.callMethodWithWorker(
2765
+ MethodName.SUBMIT_NEW_TRANSACTION,
2766
+ accountId.toString(),
2767
+ serializedTransactionRequest
2768
+ );
2530
2769
 
2531
- const transactionResult = wasm.TransactionResult.deserialize(
2532
- new Uint8Array(result.serializedTransactionResult)
2533
- );
2770
+ const transactionResult = wasm.TransactionResult.deserialize(
2771
+ new Uint8Array(result.serializedTransactionResult)
2772
+ );
2534
2773
 
2535
- return transactionResult.id();
2536
- } catch (error) {
2537
- console.error("INDEX.JS: Error in submitNewTransaction:", error);
2538
- throw error;
2539
- }
2774
+ return transactionResult.id();
2775
+ } catch (error) {
2776
+ console.error("INDEX.JS: Error in submitNewTransaction:", error);
2777
+ throw error;
2778
+ }
2779
+ });
2540
2780
  }
2541
2781
 
2542
2782
  async submitNewTransactionWithProver(accountId, transactionRequest, prover) {
2543
- try {
2544
- if (!this.worker) {
2545
- const wasmWebClient = await this.getWasmWebClient();
2546
- return await wasmWebClient.submitNewTransactionWithProver(
2547
- accountId,
2548
- transactionRequest,
2549
- prover
2550
- );
2551
- }
2783
+ return this._serializeWasmCall(async () => {
2784
+ try {
2785
+ if (!this.worker) {
2786
+ const wasmWebClient = await this.getWasmWebClient();
2787
+ return await wasmWebClient.submitNewTransactionWithProver(
2788
+ accountId,
2789
+ transactionRequest,
2790
+ prover
2791
+ );
2792
+ }
2552
2793
 
2553
- const wasm = await getWasmOrThrow();
2554
- const serializedTransactionRequest = transactionRequest.serialize();
2555
- const proverPayload = prover.serialize();
2556
- const result = await this.callMethodWithWorker(
2557
- MethodName.SUBMIT_NEW_TRANSACTION_WITH_PROVER,
2558
- accountId.toString(),
2559
- serializedTransactionRequest,
2560
- proverPayload
2561
- );
2794
+ const wasm = await getWasmOrThrow();
2795
+ const serializedTransactionRequest = transactionRequest.serialize();
2796
+ const proverPayload = prover.serialize();
2797
+ const result = await this.callMethodWithWorker(
2798
+ MethodName.SUBMIT_NEW_TRANSACTION_WITH_PROVER,
2799
+ accountId.toString(),
2800
+ serializedTransactionRequest,
2801
+ proverPayload
2802
+ );
2562
2803
 
2563
- const transactionResult = wasm.TransactionResult.deserialize(
2564
- new Uint8Array(result.serializedTransactionResult)
2565
- );
2804
+ const transactionResult = wasm.TransactionResult.deserialize(
2805
+ new Uint8Array(result.serializedTransactionResult)
2806
+ );
2566
2807
 
2567
- return transactionResult.id();
2568
- } catch (error) {
2569
- console.error(
2570
- "INDEX.JS: Error in submitNewTransactionWithProver:",
2571
- error
2572
- );
2573
- throw error;
2574
- }
2808
+ return transactionResult.id();
2809
+ } catch (error) {
2810
+ console.error(
2811
+ "INDEX.JS: Error in submitNewTransactionWithProver:",
2812
+ error
2813
+ );
2814
+ throw error;
2815
+ }
2816
+ });
2575
2817
  }
2576
2818
 
2577
2819
  async executeTransaction(accountId, transactionRequest) {
2578
- try {
2579
- if (!this.worker) {
2580
- const wasmWebClient = await this.getWasmWebClient();
2581
- return await wasmWebClient.executeTransaction(
2582
- accountId,
2583
- transactionRequest
2584
- );
2585
- }
2820
+ return this._serializeWasmCall(async () => {
2821
+ try {
2822
+ if (!this.worker) {
2823
+ const wasmWebClient = await this.getWasmWebClient();
2824
+ return await wasmWebClient.executeTransaction(
2825
+ accountId,
2826
+ transactionRequest
2827
+ );
2828
+ }
2586
2829
 
2587
- const wasm = await getWasmOrThrow();
2588
- const serializedTransactionRequest = transactionRequest.serialize();
2589
- const serializedResultBytes = await this.callMethodWithWorker(
2590
- MethodName.EXECUTE_TRANSACTION,
2591
- accountId.toString(),
2592
- serializedTransactionRequest
2593
- );
2830
+ const wasm = await getWasmOrThrow();
2831
+ const serializedTransactionRequest = transactionRequest.serialize();
2832
+ const serializedResultBytes = await this.callMethodWithWorker(
2833
+ MethodName.EXECUTE_TRANSACTION,
2834
+ accountId.toString(),
2835
+ serializedTransactionRequest
2836
+ );
2594
2837
 
2595
- return wasm.TransactionResult.deserialize(
2596
- new Uint8Array(serializedResultBytes)
2597
- );
2598
- } catch (error) {
2599
- console.error("INDEX.JS: Error in executeTransaction:", error);
2600
- throw error;
2601
- }
2838
+ return wasm.TransactionResult.deserialize(
2839
+ new Uint8Array(serializedResultBytes)
2840
+ );
2841
+ } catch (error) {
2842
+ console.error("INDEX.JS: Error in executeTransaction:", error);
2843
+ throw error;
2844
+ }
2845
+ });
2602
2846
  }
2603
2847
 
2604
2848
  async proveTransaction(transactionResult, prover) {
2605
- try {
2606
- if (!this.worker) {
2607
- const wasmWebClient = await this.getWasmWebClient();
2608
- return await wasmWebClient.proveTransaction(transactionResult, prover);
2609
- }
2849
+ return this._serializeWasmCall(async () => {
2850
+ try {
2851
+ if (!this.worker) {
2852
+ const wasmWebClient = await this.getWasmWebClient();
2853
+ return prover
2854
+ ? await wasmWebClient.proveTransactionWithProver(
2855
+ transactionResult,
2856
+ prover
2857
+ )
2858
+ : await wasmWebClient.proveTransaction(transactionResult);
2859
+ }
2610
2860
 
2611
- const wasm = await getWasmOrThrow();
2612
- const serializedTransactionResult = transactionResult.serialize();
2613
- const proverPayload = prover ? prover.serialize() : null;
2861
+ const wasm = await getWasmOrThrow();
2862
+ const serializedTransactionResult = transactionResult.serialize();
2863
+ const proverPayload = prover ? prover.serialize() : null;
2614
2864
 
2615
- const serializedProvenBytes = await this.callMethodWithWorker(
2616
- MethodName.PROVE_TRANSACTION,
2617
- serializedTransactionResult,
2618
- proverPayload
2619
- );
2865
+ const serializedProvenBytes = await this.callMethodWithWorker(
2866
+ MethodName.PROVE_TRANSACTION,
2867
+ serializedTransactionResult,
2868
+ proverPayload
2869
+ );
2620
2870
 
2621
- return wasm.ProvenTransaction.deserialize(
2622
- new Uint8Array(serializedProvenBytes)
2623
- );
2624
- } catch (error) {
2625
- console.error("INDEX.JS: Error in proveTransaction:", error);
2626
- throw error;
2627
- }
2871
+ return wasm.ProvenTransaction.deserialize(
2872
+ new Uint8Array(serializedProvenBytes)
2873
+ );
2874
+ } catch (error) {
2875
+ console.error("INDEX.JS: Error in proveTransaction:", error);
2876
+ throw error;
2877
+ }
2878
+ });
2879
+ }
2880
+
2881
+ // Delegates to `proveTransaction`, which already routes through
2882
+ // `_serializeWasmCall` and dispatches to the WASM `proveTransactionWithProver`
2883
+ // binding when `prover` is present. Kept as a wrapper (rather than elided)
2884
+ // so the method classification lint sees an explicit match for the WASM
2885
+ // method name.
2886
+ async proveTransactionWithProver(transactionResult, prover) {
2887
+ return this.proveTransaction(transactionResult, prover);
2628
2888
  }
2629
2889
 
2630
2890
  async applyTransaction(transactionResult, submissionHeight) {
2631
- try {
2632
- if (!this.worker) {
2633
- const wasmWebClient = await this.getWasmWebClient();
2634
- return await wasmWebClient.applyTransaction(
2635
- transactionResult,
2891
+ return this._serializeWasmCall(async () => {
2892
+ try {
2893
+ if (!this.worker) {
2894
+ const wasmWebClient = await this.getWasmWebClient();
2895
+ return await wasmWebClient.applyTransaction(
2896
+ transactionResult,
2897
+ submissionHeight
2898
+ );
2899
+ }
2900
+
2901
+ const wasm = await getWasmOrThrow();
2902
+ const serializedTransactionResult = transactionResult.serialize();
2903
+ const serializedUpdateBytes = await this.callMethodWithWorker(
2904
+ MethodName.APPLY_TRANSACTION,
2905
+ serializedTransactionResult,
2636
2906
  submissionHeight
2637
2907
  );
2638
- }
2639
-
2640
- const wasm = await getWasmOrThrow();
2641
- const serializedTransactionResult = transactionResult.serialize();
2642
- const serializedUpdateBytes = await this.callMethodWithWorker(
2643
- MethodName.APPLY_TRANSACTION,
2644
- serializedTransactionResult,
2645
- submissionHeight
2646
- );
2647
2908
 
2648
- return wasm.TransactionStoreUpdate.deserialize(
2649
- new Uint8Array(serializedUpdateBytes)
2650
- );
2651
- } catch (error) {
2652
- console.error("INDEX.JS: Error in applyTransaction:", error);
2653
- throw error;
2654
- }
2909
+ return wasm.TransactionStoreUpdate.deserialize(
2910
+ new Uint8Array(serializedUpdateBytes)
2911
+ );
2912
+ } catch (error) {
2913
+ console.error("INDEX.JS: Error in applyTransaction:", error);
2914
+ throw error;
2915
+ }
2916
+ });
2655
2917
  }
2656
2918
 
2657
2919
  /**
@@ -2690,21 +2952,25 @@ class WebClient {
2690
2952
  return lockHandle.coalescedResult;
2691
2953
  }
2692
2954
 
2693
- // We acquired the lock - perform the sync
2955
+ // We acquired the lock - perform the sync. Wrap the actual WASM
2956
+ // call in _serializeWasmCall so it can't race with any other
2957
+ // mutating method (executeTransaction, submitNewTransaction, etc.)
2958
+ // on the same WebClient. The outer coalescing lock stays in place
2959
+ // so concurrent syncState callers still share one in-flight sync.
2694
2960
  try {
2695
- let result;
2696
- if (!this.worker) {
2697
- const wasmWebClient = await this.getWasmWebClient();
2698
- result = await wasmWebClient.syncStateImpl();
2699
- } else {
2961
+ const result = await this._serializeWasmCall(async () => {
2962
+ if (!this.worker) {
2963
+ const wasmWebClient = await this.getWasmWebClient();
2964
+ return await wasmWebClient.syncStateImpl();
2965
+ }
2700
2966
  const wasm = await getWasmOrThrow();
2701
2967
  const serializedSyncSummaryBytes = await this.callMethodWithWorker(
2702
2968
  MethodName.SYNC_STATE
2703
2969
  );
2704
- result = wasm.SyncSummary.deserialize(
2970
+ return wasm.SyncSummary.deserialize(
2705
2971
  new Uint8Array(serializedSyncSummaryBytes)
2706
2972
  );
2707
- }
2973
+ });
2708
2974
 
2709
2975
  // Release the lock with the result
2710
2976
  releaseSyncLock(dbId, result);
@@ -2988,5 +3254,5 @@ MidenClient._MockWasmWebClient = MockWebClient;
2988
3254
  MidenClient._getWasmOrThrow = getWasmOrThrow;
2989
3255
  _setWebClient(WebClient);
2990
3256
 
2991
- export { AccountType, AuthScheme, CompilerResource, Linking, MidenArrays, MidenClient, MockWebClient as MockWasmWebClient, NoteVisibility, StorageMode, WebClient as WasmWebClient, buildSwapTag, createP2IDENote, createP2IDNote, getWasmOrThrow };
3257
+ export { AccountArray, AccountIdArray, AccountType, AuthScheme, CompilerResource, FeltArray, ForeignAccountArray, Linking, MidenArrays, MidenClient, MockWebClient as MockWasmWebClient, NoteAndArgsArray, NoteArray, NoteIdAndArgsArray, NoteRecipientArray, NoteVisibility, OutputNoteArray, StorageMode, StorageSlotArray, TransactionScriptInputPairArray, WebClient as WasmWebClient, buildSwapTag, createP2IDENote, createP2IDNote, getWasmOrThrow, resolveAuthScheme };
2992
3258
  //# sourceMappingURL=index.js.map