@miden-sdk/miden-sdk 0.14.4 → 0.15.0-alpha.4

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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -9
  3. package/dist/{Cargo-Bwjf7IkR.js → Cargo-CVlXCH_2.js} +7105 -6141
  4. package/dist/Cargo-CVlXCH_2.js.map +1 -0
  5. package/dist/api-types.d.ts +17 -47
  6. package/dist/assets/miden_client_web.wasm +0 -0
  7. package/dist/crates/miden_client_web.d.ts +122 -76
  8. package/dist/docs-entry.d.ts +5 -2
  9. package/dist/eager.js +7 -4
  10. package/dist/eager.js.map +1 -1
  11. package/dist/index.d.ts +107 -7
  12. package/dist/index.js +534 -355
  13. package/dist/index.js.map +1 -1
  14. package/dist/wasm.js +1 -1
  15. package/dist/workers/{Cargo-Bwjf7IkR-Cz54YuXA.js → Cargo-CVlXCH_2-CWA-5vlh.js} +7105 -6141
  16. package/dist/workers/Cargo-CVlXCH_2-CWA-5vlh.js.map +1 -0
  17. package/dist/workers/assets/miden_client_web.wasm +0 -0
  18. package/dist/workers/web-client-methods-worker.js +7129 -6159
  19. package/dist/workers/web-client-methods-worker.js.map +1 -1
  20. package/dist/workers/web-client-methods-worker.module.js +23 -19
  21. package/dist/workers/web-client-methods-worker.module.js.map +1 -1
  22. package/js/client.js +327 -0
  23. package/js/node/client-factory.js +117 -0
  24. package/js/node/loader.js +138 -0
  25. package/js/node/napi-compat.js +238 -0
  26. package/js/node-index.js +195 -0
  27. package/js/resources/accounts.js +224 -0
  28. package/js/resources/compiler.js +74 -0
  29. package/js/resources/keystore.js +54 -0
  30. package/js/resources/notes.js +124 -0
  31. package/js/resources/settings.js +30 -0
  32. package/js/resources/tags.js +31 -0
  33. package/js/resources/transactions.js +533 -0
  34. package/js/standalone.js +109 -0
  35. package/js/utils.js +232 -0
  36. package/lazy/package.json +4 -0
  37. package/package.json +62 -40
  38. package/dist/Cargo-Bwjf7IkR.js.map +0 -1
  39. package/dist/workers/Cargo-Bwjf7IkR-Cz54YuXA.js.map +0 -1
package/dist/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, 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-Bwjf7IkR.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, 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, 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, setupLogging } from './Cargo-CVlXCH_2.js';
3
3
 
4
4
  const WorkerAction = Object.freeze({
5
5
  INIT: "init",
@@ -108,6 +108,7 @@ async function acquireSyncLock(dbId, timeoutMs = 0) {
108
108
  }
109
109
 
110
110
  const onResult = (result) => {
111
+ /* v8 ignore next 1 -- timeoutId only set when timeoutMs>0 AND another sync is in progress; combo rare in tests */
111
112
  if (timeoutId) clearTimeout(timeoutId);
112
113
  resolve({ acquired: false, coalescedResult: result });
113
114
  };
@@ -153,6 +154,7 @@ async function acquireSyncLock(dbId, timeoutMs = 0) {
153
154
 
154
155
  navigator.locks
155
156
  .request(lockName, { mode: "exclusive" }, async () => {
157
+ /* v8 ignore next 3 -- race: lock granted after timeout or newer generation */
156
158
  if (timedOut || state.syncGeneration !== currentGeneration) {
157
159
  return;
158
160
  }
@@ -165,6 +167,9 @@ async function acquireSyncLock(dbId, timeoutMs = 0) {
165
167
  });
166
168
  })
167
169
  .catch((err) => {
170
+ /* v8 ignore next 5 -- catch path requires Web Locks rejection combined with
171
+ optional timeout; tested via "rejects when Web Locks request rejects" but
172
+ the timeoutId-set branch needs Web Locks + timeout simultaneously */
168
173
  if (timeoutId) clearTimeout(timeoutId);
169
174
  if (state.syncGeneration === currentGeneration) {
170
175
  state.inProgress = false;
@@ -540,12 +545,21 @@ class AccountsResource {
540
545
  const authComponent =
541
546
  wasm.AccountComponent.createAuthComponentFromSecretKey(opts.auth);
542
547
 
548
+ // Schema commitment from `build()` is not a substitute for contract code; require explicit
549
+ // `components` so auth-only contracts are rejected at this layer.
550
+ const components = opts.components ?? [];
551
+ if (components.length === 0) {
552
+ throw new Error(
553
+ "Contract accounts require at least one non-auth procedure: pass at least one entry in `components`."
554
+ );
555
+ }
556
+
543
557
  let builder = new wasm.AccountBuilder(opts.seed)
544
558
  .accountType(accountTypeEnum)
545
559
  .storageMode(storageMode)
546
560
  .withAuthComponent(authComponent);
547
561
 
548
- for (const component of opts.components ?? []) {
562
+ for (const component of components) {
549
563
  builder = builder.withComponent(component);
550
564
  }
551
565
 
@@ -587,7 +601,9 @@ class AccountsResource {
587
601
  if (!account) {
588
602
  throw new Error(`Account not found: ${id.toString()}`);
589
603
  }
590
- const keys = await this.#inner.keystore.getCommitments(id);
604
+ const keys = this.#inner.keystore
605
+ ? await this.#inner.keystore.getCommitments(id)
606
+ : await this.#inner.getPublicKeyCommitmentsOfAccount(id);
591
607
  return {
592
608
  account,
593
609
  vault: account.vault(),
@@ -602,7 +618,7 @@ class AccountsResource {
602
618
  const wasm = await this.#getWasm();
603
619
  const accountId = resolveAccountRef(accountRef, wasm);
604
620
  const faucetId = resolveAccountRef(tokenRef, wasm);
605
- const reader = this.#inner.accountReader(accountId);
621
+ const reader = await this.#inner.accountReader(accountId);
606
622
  return await reader.getBalance(faucetId);
607
623
  }
608
624
 
@@ -1195,13 +1211,8 @@ class TransactionsResource {
1195
1211
  async #submitOrSubmitWithProver(accountId, request, perCallProver) {
1196
1212
  const result = await this.#inner.executeTransaction(accountId, request);
1197
1213
  const prover = perCallProver ?? this.#client.defaultProver;
1198
- // Use proveTransactionWithProver (by-reference) when a prover is
1199
- // provided, so the JS-side handle is NOT consumed by wasm-bindgen.
1200
- // Passing the prover by value would transfer ownership and invalidate
1201
- // the JS object after one call, causing silent fallback to local
1202
- // proving on reuse.
1203
1214
  const proven = prover
1204
- ? await this.#inner.proveTransactionWithProver(result, prover)
1215
+ ? await this.#inner.proveTransaction(result, prover)
1205
1216
  : await this.#inner.proveTransaction(result);
1206
1217
  const txId = result.id();
1207
1218
  const height = await this.#inner.submitProvenTransaction(proven, result);
@@ -1412,7 +1423,7 @@ class CompilerResource {
1412
1423
  async component({ code, slots = [], supportAllTypes = true }) {
1413
1424
  this.#client?.assertNotTerminated();
1414
1425
  const wasm = await this.#getWasm();
1415
- const builder = this.#inner.createCodeBuilder();
1426
+ const builder = await this.#inner.createCodeBuilder();
1416
1427
  const compiled = builder.compileAccountComponentCode(code);
1417
1428
  const component = wasm.AccountComponent.compile(compiled, slots);
1418
1429
  return supportAllTypes ? component.withSupportsAllTypes() : component;
@@ -1428,7 +1439,7 @@ class CompilerResource {
1428
1439
  this.#client?.assertNotTerminated();
1429
1440
  // Ensure WASM is initialized (result unused — only #inner needs it)
1430
1441
  await this.#getWasm();
1431
- const builder = this.#inner.createCodeBuilder();
1442
+ const builder = await this.#inner.createCodeBuilder();
1432
1443
  linkLibraries(builder, libraries);
1433
1444
  return builder.compileTxScript(code);
1434
1445
  }
@@ -1442,7 +1453,7 @@ class CompilerResource {
1442
1453
  async noteScript({ code, libraries = [] }) {
1443
1454
  this.#client?.assertNotTerminated();
1444
1455
  await this.#getWasm();
1445
- const builder = this.#inner.createCodeBuilder();
1456
+ const builder = await this.#inner.createCodeBuilder();
1446
1457
  linkLibraries(builder, libraries);
1447
1458
  return builder.compileNoteScript(code);
1448
1459
  }
@@ -1478,32 +1489,47 @@ class KeystoreResource {
1478
1489
 
1479
1490
  async insert(accountId, secretKey) {
1480
1491
  this.#client.assertNotTerminated();
1481
- const ks = this.#inner.keystore;
1482
- return await ks.insert(accountId, secretKey);
1492
+ if (this.#inner.keystore) {
1493
+ return await this.#inner.keystore.insert(accountId, secretKey);
1494
+ }
1495
+ return await this.#inner.addAccountSecretKeyToWebStore(
1496
+ accountId,
1497
+ secretKey
1498
+ );
1483
1499
  }
1484
1500
 
1485
1501
  async get(pubKeyCommitment) {
1486
1502
  this.#client.assertNotTerminated();
1487
- const ks = this.#inner.keystore;
1488
- return await ks.get(pubKeyCommitment);
1503
+ if (this.#inner.keystore) {
1504
+ return await this.#inner.keystore.get(pubKeyCommitment);
1505
+ }
1506
+ return await this.#inner.getAccountAuthByPubKeyCommitment(pubKeyCommitment);
1489
1507
  }
1490
1508
 
1491
1509
  async remove(pubKeyCommitment) {
1492
1510
  this.#client.assertNotTerminated();
1493
- const ks = this.#inner.keystore;
1494
- return await ks.remove(pubKeyCommitment);
1511
+ if (this.#inner.keystore) {
1512
+ return await this.#inner.keystore.remove(pubKeyCommitment);
1513
+ }
1514
+ throw new Error("remove() is not supported on this platform");
1495
1515
  }
1496
1516
 
1497
1517
  async getCommitments(accountId) {
1498
1518
  this.#client.assertNotTerminated();
1499
- const ks = this.#inner.keystore;
1500
- return await ks.getCommitments(accountId);
1519
+ if (this.#inner.keystore) {
1520
+ return await this.#inner.keystore.getCommitments(accountId);
1521
+ }
1522
+ return await this.#inner.getPublicKeyCommitmentsOfAccount(accountId);
1501
1523
  }
1502
1524
 
1503
1525
  async getAccountId(pubKeyCommitment) {
1504
1526
  this.#client.assertNotTerminated();
1505
- const ks = this.#inner.keystore;
1506
- return await ks.getAccountId(pubKeyCommitment);
1527
+ if (this.#inner.keystore) {
1528
+ return await this.#inner.keystore.getAccountId(pubKeyCommitment);
1529
+ }
1530
+ const account =
1531
+ await this.#inner.getAccountByKeyCommitment(pubKeyCommitment);
1532
+ return account ? account.id() : undefined;
1507
1533
  }
1508
1534
  }
1509
1535
 
@@ -1576,14 +1602,16 @@ class MidenClient {
1576
1602
  options?.storeName,
1577
1603
  options.keystore.getKey,
1578
1604
  options.keystore.insertKey,
1579
- options.keystore.sign
1605
+ options.keystore.sign,
1606
+ options?.debugMode
1580
1607
  );
1581
1608
  } else {
1582
1609
  inner = await WebClientClass.createClient(
1583
1610
  rpcUrl,
1584
1611
  noteTransportUrl,
1585
1612
  seed,
1586
- options?.storeName
1613
+ options?.storeName,
1614
+ options?.debugMode
1587
1615
  );
1588
1616
  }
1589
1617
 
@@ -1640,32 +1668,6 @@ class MidenClient {
1640
1668
  });
1641
1669
  }
1642
1670
 
1643
- /**
1644
- * Resolves once the WASM module is initialized and safe to use.
1645
- *
1646
- * Idempotent and shared across callers: the underlying loader memoizes the
1647
- * in-flight promise, so concurrent `ready()` calls await the same
1648
- * initialization and post-init callers resolve immediately from a cached
1649
- * module. Safe to call from `MidenProvider`, tutorial helpers, and any
1650
- * other consumer simultaneously.
1651
- *
1652
- * Useful on the `/lazy` entry (e.g. Next.js / Capacitor), where no
1653
- * top-level await runs at import time. On the default (eager) entry this
1654
- * is redundant — importing the module already awaits WASM — but calling it
1655
- * is still harmless.
1656
- *
1657
- * @returns {Promise<void>} Resolves when WASM is initialized.
1658
- */
1659
- static async ready() {
1660
- const getWasm = MidenClient._getWasmOrThrow;
1661
- if (!getWasm) {
1662
- throw new Error(
1663
- "MidenClient not initialized. Import from the SDK package entry point."
1664
- );
1665
- }
1666
- await getWasm();
1667
- }
1668
-
1669
1671
  /**
1670
1672
  * Creates a mock client for testing.
1671
1673
  *
@@ -1722,54 +1724,6 @@ class MidenClient {
1722
1724
  return await this.#inner.getSyncHeight();
1723
1725
  }
1724
1726
 
1725
- /**
1726
- * Resolves once every serialized WASM call that was already on the
1727
- * internal `_serializeWasmCall` chain when `waitForIdle()` was called
1728
- * (execute, submit, prove, apply, sync, or account creation) has
1729
- * settled. Use this from callers that need to perform a non-WASM-side
1730
- * action — e.g. clearing an in-memory auth key on wallet lock — after
1731
- * the kernel finishes, so its auth callback doesn't race with the key
1732
- * being cleared.
1733
- *
1734
- * Does NOT wait for calls enqueued after `waitForIdle()` returns —
1735
- * intentional, so a caller can drain and proceed without being blocked
1736
- * indefinitely by concurrent workload.
1737
- *
1738
- * Caveat for `syncState`: `syncStateWithTimeout` awaits the sync lock
1739
- * (`acquireSyncLock`, which uses Web Locks) BEFORE putting its WASM
1740
- * call onto the chain, so a `syncState` that is queued on the sync
1741
- * lock — but has not yet begun its WASM phase — is not visible to
1742
- * `waitForIdle` and will not be awaited. Other methods (`newWallet`,
1743
- * `executeTransaction`, etc.) route through the chain synchronously
1744
- * on call and are always observed.
1745
- *
1746
- * Safe to call at any time; returns immediately if nothing was in
1747
- * flight.
1748
- *
1749
- * @returns {Promise<void>}
1750
- */
1751
- async waitForIdle() {
1752
- this.assertNotTerminated();
1753
- await this.#inner.waitForIdle();
1754
- }
1755
-
1756
- /**
1757
- * Returns the raw JS value that the most recent sign-callback invocation
1758
- * threw, or `null` if the last sign call succeeded (or no call has
1759
- * happened yet).
1760
- *
1761
- * Useful for recovering structured metadata (e.g. a `reason: 'locked'`
1762
- * property) that the kernel-level `auth::request` diagnostic would
1763
- * otherwise erase. Call immediately after catching a failed
1764
- * `transactions.submit` / `transactions.send` / `transactions.consume`.
1765
- *
1766
- * @returns {any} The raw thrown value, or `null`.
1767
- */
1768
- lastAuthError() {
1769
- this.assertNotTerminated();
1770
- return this.#inner.lastAuthError();
1771
- }
1772
-
1773
1727
  /**
1774
1728
  * Terminates the underlying Web Worker. After this, all method calls will throw.
1775
1729
  */
@@ -1791,9 +1745,9 @@ class MidenClient {
1791
1745
  *
1792
1746
  * @returns {string} The store identifier.
1793
1747
  */
1794
- storeIdentifier() {
1748
+ async storeIdentifier() {
1795
1749
  this.assertNotTerminated();
1796
- return this.#inner.storeIdentifier();
1750
+ return await this.#inner.storeIdentifier();
1797
1751
  }
1798
1752
 
1799
1753
  // ── Mock-only methods ──
@@ -2006,6 +1960,339 @@ function buildNoteAssets(assets, wasm) {
2006
1960
  return new wasm.NoteAssets(fungibleAssets);
2007
1961
  }
2008
1962
 
1963
+ /**
1964
+ * StorageView wraps the raw WASM AccountStorage to provide a developer-friendly
1965
+ * (and AI-agent-friendly) API.
1966
+ *
1967
+ * Key behavior: `getItem()` returns a `StorageResult` that works intuitively for
1968
+ * both Value and StorageMap slots. The result has `.toBigInt()`, `.toHex()`, and
1969
+ * `.toString()` methods that do the right thing automatically. For StorageMap slots,
1970
+ * `.entries` provides access to all map entries.
1971
+ *
1972
+ * Numeric ergonomics: `StorageResult` is usable directly in template strings,
1973
+ * JSX, and arithmetic via `toString()` (lossless, BigInt-backed) and `valueOf()`
1974
+ * (returns a JS number for values that fit, throws on overflow — never silently
1975
+ * corrupts). For exact u64 access use `.toBigInt()`.
1976
+ *
1977
+ * The raw WASM AccountStorage is still accessible via `.raw` for advanced use cases
1978
+ * that need the original behavior (e.g., comparing map commitment roots).
1979
+ */
1980
+ /** @param {string} hex @param {typeof Word} WordClass @returns {Word | undefined} */
1981
+ function hexToWord(hex, WordClass) {
1982
+ if (!hex || !WordClass) return undefined;
1983
+ try {
1984
+ return WordClass.fromHex(hex);
1985
+ } catch {
1986
+ return undefined;
1987
+ }
1988
+ }
1989
+
1990
+ class StorageView {
1991
+ #storage;
1992
+ #WordClass;
1993
+
1994
+ /**
1995
+ * @param {AccountStorage} wasmStorage
1996
+ * @param {typeof Word} WordClass
1997
+ */
1998
+ constructor(wasmStorage, WordClass) {
1999
+ this.#storage = wasmStorage;
2000
+ this.#WordClass = WordClass;
2001
+ }
2002
+
2003
+ /**
2004
+ * The raw WASM AccountStorage, for cases where you need the original
2005
+ * primitive behavior (e.g., reading map commitment roots via raw.getItem()).
2006
+ */
2007
+ get raw() {
2008
+ return this.#storage;
2009
+ }
2010
+
2011
+ /**
2012
+ * Returns the commitment to the full account storage.
2013
+ */
2014
+ commitment() {
2015
+ return this.#storage.commitment();
2016
+ }
2017
+
2018
+ /**
2019
+ * Returns the names of all storage slots on this account.
2020
+ * @returns {string[]}
2021
+ */
2022
+ getSlotNames() {
2023
+ return this.#storage.getSlotNames();
2024
+ }
2025
+
2026
+ /**
2027
+ * Returns a StorageResult for the given slot.
2028
+ *
2029
+ * The result has convenience methods that work for both Value and StorageMap slots:
2030
+ * - `.toBigInt()` — first felt as BigInt (full u64 precision)
2031
+ * - `.toHex()` — first felt's Word as hex string
2032
+ * - `.toString()` — renders as the BigInt value (works in JSX: {result})
2033
+ * - `.isMap` — true if this is a StorageMap slot
2034
+ * - `.entries` — all map entries (undefined for Value slots)
2035
+ * - `.word` — the underlying Word value
2036
+ *
2037
+ * The result is also usable directly in arithmetic (`+result`, `result * 2`)
2038
+ * via `valueOf()`, which returns a JS number for values that fit and throws
2039
+ * `RangeError` for values exceeding `Number.MAX_SAFE_INTEGER` — use `.toBigInt()`
2040
+ * for exact access to large u64 values.
2041
+ *
2042
+ * For explicit key-based map reads, use `getMapItem(slotName, key)`.
2043
+ * For the raw commitment hash, use `raw.getItem(slotName)`.
2044
+ *
2045
+ * @param {string} slotName
2046
+ * @returns {StorageResult | undefined}
2047
+ */
2048
+ getItem(slotName) {
2049
+ // Type detection + value retrieval in one pass.
2050
+ // We call getMapEntries to detect maps, but defer parsing the entries
2051
+ // until .entries is actually accessed (lazy). Only the first entry's
2052
+ // Word is parsed eagerly for the convenience methods (toBigInt, etc.).
2053
+ const rawEntries = this.#storage.getMapEntries(slotName);
2054
+ if (rawEntries !== undefined && rawEntries !== null) {
2055
+ // StorageMap — parse only the first entry eagerly
2056
+ const firstWord =
2057
+ rawEntries.length > 0
2058
+ ? hexToWord(rawEntries[0].value, this.#WordClass)
2059
+ : undefined;
2060
+ return new StorageResult(firstWord, true, rawEntries, this.#WordClass);
2061
+ }
2062
+
2063
+ // Value slot — use raw getItem
2064
+ const word = this.#storage.getItem(slotName);
2065
+ if (!word) return undefined;
2066
+ return new StorageResult(word, false, undefined, this.#WordClass);
2067
+ }
2068
+
2069
+ /**
2070
+ * Returns the value for a key in a StorageMap slot.
2071
+ * Delegates directly to the raw WASM method.
2072
+ *
2073
+ * @param {string} slotName
2074
+ * @param {Word} key
2075
+ * @returns {Word | undefined}
2076
+ */
2077
+ getMapItem(slotName, key) {
2078
+ return this.#storage.getMapItem(slotName, key);
2079
+ }
2080
+
2081
+ /**
2082
+ * Get all key-value pairs from a StorageMap slot.
2083
+ * Returns undefined if the slot isn't a map, or an empty array if the map is empty.
2084
+ */
2085
+ getMapEntries(slotName) {
2086
+ return this.#storage.getMapEntries(slotName);
2087
+ }
2088
+
2089
+ /**
2090
+ * Returns the commitment root of a storage slot as a Word.
2091
+ *
2092
+ * For Value slots, this is the stored Word itself.
2093
+ * For StorageMap slots, this is the Merkle root hash of the map — useful for:
2094
+ * - Verifying state hasn't changed between transactions
2095
+ * - Merkle inclusion proofs against the account state
2096
+ * - Comparing map state across accounts or sync cycles
2097
+ *
2098
+ * This is the raw protocol-level value. For reading stored data, use `getItem()`.
2099
+ *
2100
+ * @param {string} slotName
2101
+ * @returns {Word | undefined}
2102
+ */
2103
+ getCommitment(slotName) {
2104
+ return this.#storage.getItem(slotName);
2105
+ }
2106
+ }
2107
+
2108
+ /**
2109
+ * Result of reading a storage slot. Works for both Value and StorageMap slots.
2110
+ *
2111
+ * Provides a unified interface so code like `storage.getItem(name).toBigInt()`
2112
+ * works regardless of the underlying slot type.
2113
+ *
2114
+ * For StorageMap slots, the convenience methods (toHex, toBigInt) operate on
2115
+ * the first entry's value. The full map data is available via `.entries`.
2116
+ * Note: Miden storage maps are Merkle-based, so "first" is determined by key hash
2117
+ * order — deterministic for a given map state, but not meaningful as an ordering.
2118
+ */
2119
+ class StorageResult {
2120
+ #word;
2121
+ #isMap;
2122
+ #rawEntries; // Raw JsStorageMapEntry[] from WASM — parsed lazily
2123
+ #parsedEntries; // Parsed entries with Word objects — created on first .entries access
2124
+ #WordClass;
2125
+
2126
+ /**
2127
+ * @param {Word | undefined} word — the primary Word value (first entry for maps)
2128
+ * @param {boolean} isMap — whether this came from a StorageMap slot
2129
+ * @param {Array | undefined} rawEntries — raw WASM entries (parsed lazily on .entries access)
2130
+ * @param {typeof Word} WordClass — Word constructor for hex parsing
2131
+ */
2132
+ constructor(word, isMap, rawEntries, WordClass) {
2133
+ this.#word = word;
2134
+ this.#isMap = isMap;
2135
+ this.#rawEntries = rawEntries;
2136
+ this.#WordClass = WordClass;
2137
+ }
2138
+
2139
+ /** True if this slot is a StorageMap. */
2140
+ get isMap() {
2141
+ return this.#isMap;
2142
+ }
2143
+
2144
+ /**
2145
+ * All entries from a StorageMap slot (lazily parsed on first access).
2146
+ * Each entry has { key: string (hex), value: string (hex), word: Word | undefined }.
2147
+ * Returns undefined for Value slots.
2148
+ */
2149
+ get entries() {
2150
+ if (!this.#isMap) return undefined;
2151
+ if (this.#parsedEntries) return this.#parsedEntries;
2152
+ if (!this.#rawEntries) return [];
2153
+
2154
+ // Parse entries lazily — only when the user actually accesses .entries
2155
+ this.#parsedEntries = this.#rawEntries.map((e) => ({
2156
+ key: e.key,
2157
+ value: e.value,
2158
+ word: hexToWord(e.value, this.#WordClass),
2159
+ }));
2160
+ this.#rawEntries = undefined; // Free raw entries
2161
+ return this.#parsedEntries;
2162
+ }
2163
+
2164
+ /**
2165
+ * The underlying Word value.
2166
+ * For Value slots: the stored Word.
2167
+ * For StorageMap slots: the first entry's value as a Word (or undefined if empty).
2168
+ */
2169
+ get word() {
2170
+ return this.#word;
2171
+ }
2172
+
2173
+ /**
2174
+ * Returns all four Felts of the stored Word as an array.
2175
+ * Pass-through to Word.toFelts() — ensures code that expects a Word-like
2176
+ * object (e.g., `result.toFelts()[0].asInt()`) works on StorageResult.
2177
+ * @returns {Felt[]}
2178
+ */
2179
+ toFelts() {
2180
+ if (!this.#word) return [];
2181
+ return this.#word.toFelts();
2182
+ }
2183
+
2184
+ /**
2185
+ * The first Felt of the stored Word.
2186
+ * Returns the WASM Felt object — use .asInt() to get its BigInt value.
2187
+ * @returns {Felt | undefined}
2188
+ */
2189
+ felt() {
2190
+ if (!this.#word) return undefined;
2191
+ const felts = this.#word.toFelts();
2192
+ return felts?.[0];
2193
+ }
2194
+
2195
+ /**
2196
+ * First felt as a BigInt. Preserves full u64 precision.
2197
+ * @returns {bigint}
2198
+ */
2199
+ toBigInt() {
2200
+ if (!this.#word) return 0n;
2201
+ return wordToBigInt(this.#word);
2202
+ }
2203
+
2204
+ /**
2205
+ * The Word's hex representation.
2206
+ * For Value slots: the stored Word hex.
2207
+ * For StorageMap slots: the first entry's value Word hex.
2208
+ * @returns {string}
2209
+ */
2210
+ toHex() {
2211
+ if (!this.#word) return "0x" + "0".repeat(64);
2212
+ return this.#word.toHex();
2213
+ }
2214
+
2215
+ /**
2216
+ * Renders as the BigInt value (lossless). Makes `{storageResult}` work in JSX
2217
+ * and template literals: `` `value: ${result}` ``.
2218
+ * @returns {string}
2219
+ */
2220
+ toString() {
2221
+ return this.toBigInt().toString();
2222
+ }
2223
+
2224
+ /**
2225
+ * JSON serialization — returns the value as a string to avoid
2226
+ * precision loss for large u64 felt values.
2227
+ */
2228
+ toJSON() {
2229
+ return this.toBigInt().toString();
2230
+ }
2231
+
2232
+ /**
2233
+ * Allows `+result`, `result * 2`, etc. to work as expected.
2234
+ *
2235
+ * Returns a JS number for values that fit in `Number.MAX_SAFE_INTEGER`
2236
+ * (2^53 - 1). For larger u64 values, throws `RangeError` rather than
2237
+ * silently losing precision — use `.toBigInt()` to access the exact value.
2238
+ *
2239
+ * @returns {number}
2240
+ * @throws {RangeError} if the underlying felt exceeds Number.MAX_SAFE_INTEGER
2241
+ */
2242
+ valueOf() {
2243
+ const big = this.toBigInt();
2244
+ if (big > BigInt(Number.MAX_SAFE_INTEGER)) {
2245
+ throw new RangeError(
2246
+ `StorageResult value ${big} exceeds Number.MAX_SAFE_INTEGER ` +
2247
+ `(${Number.MAX_SAFE_INTEGER}) — use .toBigInt() to read the exact value.`
2248
+ );
2249
+ }
2250
+ return Number(big);
2251
+ }
2252
+ }
2253
+
2254
+ /**
2255
+ * Convert a Word's first felt to a BigInt.
2256
+ * Uses BigInt to preserve full u64 precision (felts are u64-backed).
2257
+ * Handles the little-endian byte order of felt serialization.
2258
+ *
2259
+ * @param {Word} word
2260
+ * @returns {bigint}
2261
+ */
2262
+ function wordToBigInt(word) {
2263
+ try {
2264
+ const hex = word.toHex();
2265
+ // Word.toHex() returns "0x" + 64 hex chars (4 felts × 16 hex chars each).
2266
+ // Each felt is serialized as 8 little-endian bytes, so we take the first 16
2267
+ // hex chars (first felt) and reverse the byte pairs to get the integer value.
2268
+ const feltHex = hex.slice(2, 18);
2269
+ const bytes = feltHex.match(/../g);
2270
+ if (!bytes) return 0n;
2271
+ return BigInt("0x" + bytes.reverse().join(""));
2272
+ } catch {
2273
+ return 0n;
2274
+ }
2275
+ }
2276
+
2277
+ /**
2278
+ * Install the StorageView wrapper on Account.prototype.storage().
2279
+ * After this, `account.storage()` returns a StorageView instead of raw AccountStorage.
2280
+ *
2281
+ * @param {object} wasmModule — the loaded WASM module containing Account, Word, etc.
2282
+ */
2283
+ function installStorageView(wasmModule) {
2284
+ const AccountProto = wasmModule.Account?.prototype;
2285
+ if (!AccountProto || !AccountProto.storage) return;
2286
+
2287
+ const originalStorage = AccountProto.storage;
2288
+ const WordClass = wasmModule.Word;
2289
+
2290
+ AccountProto.storage = function () {
2291
+ const raw = originalStorage.call(this);
2292
+ return new StorageView(raw, WordClass);
2293
+ };
2294
+ }
2295
+
2009
2296
  const AccountType = Object.freeze({
2010
2297
  // WASM-compatible numeric values — usable with AccountBuilder directly
2011
2298
  FungibleFaucet: 0,
@@ -2040,43 +2327,6 @@ const Linking = Object.freeze({
2040
2327
  Static: "static",
2041
2328
  });
2042
2329
 
2043
- // Method classification sets — used by scripts/check-method-classification.js to ensure
2044
- // every WASM export is explicitly categorised. Update when adding new WASM methods.
2045
- //
2046
- // Note on `SYNC_METHODS`: the classifier is "synchronous in JS" — i.e.
2047
- // `pub fn ...` in Rust, not `pub async fn ...`. Two sub-cases:
2048
- // 1. Factory methods that return a non-Promise value (`accountReader`
2049
- // returns `AccountReader`; the transaction-request builders return
2050
- // `TransactionRequestBuilder`; `createCodeBuilder` returns a builder).
2051
- // Wrapping these in `_serializeWasmCall` would turn their return
2052
- // value into `Promise<T>` and break callers that use the result
2053
- // immediately (e.g. `const reader = client.accountReader(id);
2054
- // await reader.nonce();`).
2055
- // 2. Sync methods that still take `&mut self` in Rust (`proveBlock`,
2056
- // `serializeMockChain`, `setDebugMode`). Safe to opt out because JS
2057
- // is single-threaded — the event loop cannot interleave another
2058
- // call during their synchronous execution, so the RefCell borrow
2059
- // is always released before any other borrow can start.
2060
- // Do NOT move a sync-in-JS method into `WRITE_METHODS` / `READ_METHODS`
2061
- // just because it takes `&mut self` or `&self`; wrapping changes its
2062
- // return shape and breaks every caller.
2063
- const SYNC_METHODS = new Set([
2064
- "accountReader",
2065
- "buildSwapTag",
2066
- "createCodeBuilder",
2067
- "lastAuthError",
2068
- "newConsumeTransactionRequest",
2069
- "newMintTransactionRequest",
2070
- "newSendTransactionRequest",
2071
- "newSwapTransactionRequest",
2072
- "proveBlock",
2073
- "serializeMockChain",
2074
- "serializeMockNoteTransportNode",
2075
- "setDebugMode",
2076
- "storeIdentifier",
2077
- "usesMockChain",
2078
- ]);
2079
-
2080
2330
  const MOCK_STORE_NAME = "mock_client_db";
2081
2331
 
2082
2332
  const buildTypedArraysExport = (exportObject) => {
@@ -2133,6 +2383,9 @@ const ensureWasm = async () => {
2133
2383
  }
2134
2384
  // Set WASM module for standalone utilities
2135
2385
  _setWasm(module);
2386
+ // Install StorageView: account.storage() now returns a developer-friendly
2387
+ // wrapper that makes getItem() work correctly for StorageMap slots.
2388
+ installStorageView(module);
2136
2389
  }
2137
2390
  return module;
2138
2391
  });
@@ -2177,16 +2430,6 @@ const getWasmOrThrow = async () => {
2177
2430
  /**
2178
2431
  * Create a Proxy that forwards missing properties to the underlying WASM
2179
2432
  * WebClient.
2180
- *
2181
- * Async proxy-fallback methods (every WASM method that borrows the
2182
- * WebClient's RefCell — reads included, since `&self` and `&mut self` both
2183
- * trip wasm-bindgen's "recursive use of an object detected" panic if
2184
- * another borrow is live) are routed through `_serializeWasmCall` so they
2185
- * queue on the same chain as the explicitly-wrapped methods.
2186
- *
2187
- * `SYNC_METHODS` opts out: they are synchronous in JS and wrapping them
2188
- * would change their return type to `Promise<T>`, which is a breaking
2189
- * change for consumers that use them as plain getters or builders.
2190
2433
  */
2191
2434
  function createClientProxy(instance) {
2192
2435
  return new Proxy(instance, {
@@ -2197,13 +2440,7 @@ function createClientProxy(instance) {
2197
2440
  if (target.wasmWebClient && prop in target.wasmWebClient) {
2198
2441
  const value = target.wasmWebClient[prop];
2199
2442
  if (typeof value === "function") {
2200
- if (typeof prop === "string" && SYNC_METHODS.has(prop)) {
2201
- return value.bind(target.wasmWebClient);
2202
- }
2203
- return (...args) =>
2204
- target._serializeWasmCall(() =>
2205
- value.apply(target.wasmWebClient, args)
2206
- );
2443
+ return value.bind(target.wasmWebClient);
2207
2444
  }
2208
2445
  return value;
2209
2446
  }
@@ -2434,13 +2671,6 @@ class WebClient {
2434
2671
  * Serialize a WASM call that requires exclusive (&mut self) access.
2435
2672
  * Concurrent calls are queued and executed one at a time.
2436
2673
  *
2437
- * Wraps both the direct (in-thread) path and the worker-dispatched path.
2438
- * On the worker path this is redundant with the worker's own message queue,
2439
- * but harmless (the chain resolves immediately on the main thread once the
2440
- * worker's postMessage returns). On the direct path it is load-bearing —
2441
- * without it, concurrent main-thread callers would panic with
2442
- * "recursive use of an object detected" (wasm-bindgen's internal RefCell).
2443
- *
2444
2674
  * @param {() => Promise<any>} fn - The async function to execute.
2445
2675
  * @returns {Promise<any>} The result of fn.
2446
2676
  */
@@ -2450,35 +2680,6 @@ class WebClient {
2450
2680
  return result;
2451
2681
  }
2452
2682
 
2453
- /**
2454
- * Returns a promise that resolves once every serialized WASM call that
2455
- * was already on `_wasmCallChain` when `waitForIdle()` was called has
2456
- * settled. Use this from callers that need to perform a non-WASM-side
2457
- * action (e.g. clear an in-memory auth key) AFTER any in-flight
2458
- * execute / submit / sync has completed, so the WASM kernel's auth
2459
- * callback doesn't race with the key being cleared.
2460
- *
2461
- * Does NOT wait for calls enqueued after `waitForIdle()` returns —
2462
- * this is intentional, so a caller can drain and then proceed without
2463
- * being blocked indefinitely by a concurrent workload.
2464
- *
2465
- * Caveat for `syncState`: `syncStateWithTimeout` awaits
2466
- * `acquireSyncLock` (Web Locks) BEFORE wrapping its WASM call in
2467
- * `_serializeWasmCall`, so a sync that is queued on the sync lock but
2468
- * has not yet reached its WASM phase is not on the chain and will not
2469
- * be awaited. Every other serialized method (`executeTransaction`,
2470
- * `newWallet`, `submitNewTransaction`, `proveTransaction`,
2471
- * `applyTransaction`, and the proxy-fallback reads) routes through
2472
- * the chain synchronously on call and is always observed.
2473
- *
2474
- * @returns {Promise<void>}
2475
- */
2476
- async waitForIdle() {
2477
- // Chain on `_wasmCallChain`; by the time this resolves, any in-flight
2478
- // serialized call has settled. Catch so the chain state doesn't leak.
2479
- await this._wasmCallChain.catch(() => {});
2480
- }
2481
-
2482
2683
  // TODO: This will soon conflict with some changes in main.
2483
2684
  // More context here:
2484
2685
  // https://github.com/0xMiden/miden-client/pull/1645?notification_referrer_id=NT_kwHOA1yg7NoAJVJlcG9zaXRvcnk7NjU5MzQzNzAyO0lzc3VlOzM3OTY4OTU1Nzk&notifications_query=is%3Aunread#discussion_r2696075480
@@ -2684,171 +2885,147 @@ class WebClient {
2684
2885
  }
2685
2886
 
2686
2887
  async submitNewTransaction(accountId, transactionRequest) {
2687
- return this._serializeWasmCall(async () => {
2688
- try {
2689
- if (!this.worker) {
2690
- const wasmWebClient = await this.getWasmWebClient();
2691
- return await wasmWebClient.submitNewTransaction(
2692
- accountId,
2693
- transactionRequest
2694
- );
2695
- }
2696
-
2697
- const wasm = await getWasmOrThrow();
2698
- const serializedTransactionRequest = transactionRequest.serialize();
2699
- const result = await this.callMethodWithWorker(
2700
- MethodName.SUBMIT_NEW_TRANSACTION,
2701
- accountId.toString(),
2702
- serializedTransactionRequest
2888
+ try {
2889
+ if (!this.worker) {
2890
+ const wasmWebClient = await this.getWasmWebClient();
2891
+ return await wasmWebClient.submitNewTransaction(
2892
+ accountId,
2893
+ transactionRequest
2703
2894
  );
2895
+ }
2704
2896
 
2705
- const transactionResult = wasm.TransactionResult.deserialize(
2706
- new Uint8Array(result.serializedTransactionResult)
2707
- );
2897
+ const wasm = await getWasmOrThrow();
2898
+ const serializedTransactionRequest = transactionRequest.serialize();
2899
+ const result = await this.callMethodWithWorker(
2900
+ MethodName.SUBMIT_NEW_TRANSACTION,
2901
+ accountId.toString(),
2902
+ serializedTransactionRequest
2903
+ );
2708
2904
 
2709
- return transactionResult.id();
2710
- } catch (error) {
2711
- console.error("INDEX.JS: Error in submitNewTransaction:", error);
2712
- throw error;
2713
- }
2714
- });
2905
+ const transactionResult = wasm.TransactionResult.deserialize(
2906
+ new Uint8Array(result.serializedTransactionResult)
2907
+ );
2908
+
2909
+ return transactionResult.id();
2910
+ } catch (error) {
2911
+ console.error("INDEX.JS: Error in submitNewTransaction:", error);
2912
+ throw error;
2913
+ }
2715
2914
  }
2716
2915
 
2717
2916
  async submitNewTransactionWithProver(accountId, transactionRequest, prover) {
2718
- return this._serializeWasmCall(async () => {
2719
- try {
2720
- if (!this.worker) {
2721
- const wasmWebClient = await this.getWasmWebClient();
2722
- return await wasmWebClient.submitNewTransactionWithProver(
2723
- accountId,
2724
- transactionRequest,
2725
- prover
2726
- );
2727
- }
2728
-
2729
- const wasm = await getWasmOrThrow();
2730
- const serializedTransactionRequest = transactionRequest.serialize();
2731
- const proverPayload = prover.serialize();
2732
- const result = await this.callMethodWithWorker(
2733
- MethodName.SUBMIT_NEW_TRANSACTION_WITH_PROVER,
2734
- accountId.toString(),
2735
- serializedTransactionRequest,
2736
- proverPayload
2917
+ try {
2918
+ if (!this.worker) {
2919
+ const wasmWebClient = await this.getWasmWebClient();
2920
+ return await wasmWebClient.submitNewTransactionWithProver(
2921
+ accountId,
2922
+ transactionRequest,
2923
+ prover
2737
2924
  );
2925
+ }
2738
2926
 
2739
- const transactionResult = wasm.TransactionResult.deserialize(
2740
- new Uint8Array(result.serializedTransactionResult)
2741
- );
2927
+ const wasm = await getWasmOrThrow();
2928
+ const serializedTransactionRequest = transactionRequest.serialize();
2929
+ const proverPayload = prover.serialize();
2930
+ const result = await this.callMethodWithWorker(
2931
+ MethodName.SUBMIT_NEW_TRANSACTION_WITH_PROVER,
2932
+ accountId.toString(),
2933
+ serializedTransactionRequest,
2934
+ proverPayload
2935
+ );
2742
2936
 
2743
- return transactionResult.id();
2744
- } catch (error) {
2745
- console.error(
2746
- "INDEX.JS: Error in submitNewTransactionWithProver:",
2747
- error
2748
- );
2749
- throw error;
2750
- }
2751
- });
2937
+ const transactionResult = wasm.TransactionResult.deserialize(
2938
+ new Uint8Array(result.serializedTransactionResult)
2939
+ );
2940
+
2941
+ return transactionResult.id();
2942
+ } catch (error) {
2943
+ console.error(
2944
+ "INDEX.JS: Error in submitNewTransactionWithProver:",
2945
+ error
2946
+ );
2947
+ throw error;
2948
+ }
2752
2949
  }
2753
2950
 
2754
2951
  async executeTransaction(accountId, transactionRequest) {
2755
- return this._serializeWasmCall(async () => {
2756
- try {
2757
- if (!this.worker) {
2758
- const wasmWebClient = await this.getWasmWebClient();
2759
- return await wasmWebClient.executeTransaction(
2760
- accountId,
2761
- transactionRequest
2762
- );
2763
- }
2764
-
2765
- const wasm = await getWasmOrThrow();
2766
- const serializedTransactionRequest = transactionRequest.serialize();
2767
- const serializedResultBytes = await this.callMethodWithWorker(
2768
- MethodName.EXECUTE_TRANSACTION,
2769
- accountId.toString(),
2770
- serializedTransactionRequest
2771
- );
2772
-
2773
- return wasm.TransactionResult.deserialize(
2774
- new Uint8Array(serializedResultBytes)
2952
+ try {
2953
+ if (!this.worker) {
2954
+ const wasmWebClient = await this.getWasmWebClient();
2955
+ return await wasmWebClient.executeTransaction(
2956
+ accountId,
2957
+ transactionRequest
2775
2958
  );
2776
- } catch (error) {
2777
- console.error("INDEX.JS: Error in executeTransaction:", error);
2778
- throw error;
2779
2959
  }
2780
- });
2960
+
2961
+ const wasm = await getWasmOrThrow();
2962
+ const serializedTransactionRequest = transactionRequest.serialize();
2963
+ const serializedResultBytes = await this.callMethodWithWorker(
2964
+ MethodName.EXECUTE_TRANSACTION,
2965
+ accountId.toString(),
2966
+ serializedTransactionRequest
2967
+ );
2968
+
2969
+ return wasm.TransactionResult.deserialize(
2970
+ new Uint8Array(serializedResultBytes)
2971
+ );
2972
+ } catch (error) {
2973
+ console.error("INDEX.JS: Error in executeTransaction:", error);
2974
+ throw error;
2975
+ }
2781
2976
  }
2782
2977
 
2783
2978
  async proveTransaction(transactionResult, prover) {
2784
- return this._serializeWasmCall(async () => {
2785
- try {
2786
- if (!this.worker) {
2787
- const wasmWebClient = await this.getWasmWebClient();
2788
- return prover
2789
- ? await wasmWebClient.proveTransactionWithProver(
2790
- transactionResult,
2791
- prover
2792
- )
2793
- : await wasmWebClient.proveTransaction(transactionResult);
2794
- }
2795
-
2796
- const wasm = await getWasmOrThrow();
2797
- const serializedTransactionResult = transactionResult.serialize();
2798
- const proverPayload = prover ? prover.serialize() : null;
2979
+ try {
2980
+ if (!this.worker) {
2981
+ const wasmWebClient = await this.getWasmWebClient();
2982
+ return await wasmWebClient.proveTransaction(transactionResult, prover);
2983
+ }
2799
2984
 
2800
- const serializedProvenBytes = await this.callMethodWithWorker(
2801
- MethodName.PROVE_TRANSACTION,
2802
- serializedTransactionResult,
2803
- proverPayload
2804
- );
2985
+ const wasm = await getWasmOrThrow();
2986
+ const serializedTransactionResult = transactionResult.serialize();
2987
+ const proverPayload = prover ? prover.serialize() : null;
2805
2988
 
2806
- return wasm.ProvenTransaction.deserialize(
2807
- new Uint8Array(serializedProvenBytes)
2808
- );
2809
- } catch (error) {
2810
- console.error("INDEX.JS: Error in proveTransaction:", error);
2811
- throw error;
2812
- }
2813
- });
2814
- }
2989
+ const serializedProvenBytes = await this.callMethodWithWorker(
2990
+ MethodName.PROVE_TRANSACTION,
2991
+ serializedTransactionResult,
2992
+ proverPayload
2993
+ );
2815
2994
 
2816
- // Delegates to `proveTransaction`, which already routes through
2817
- // `_serializeWasmCall` and dispatches to the WASM `proveTransactionWithProver`
2818
- // binding when `prover` is present. Kept as a wrapper (rather than elided)
2819
- // so the method classification lint sees an explicit match for the WASM
2820
- // method name.
2821
- async proveTransactionWithProver(transactionResult, prover) {
2822
- return this.proveTransaction(transactionResult, prover);
2995
+ return wasm.ProvenTransaction.deserialize(
2996
+ new Uint8Array(serializedProvenBytes)
2997
+ );
2998
+ } catch (error) {
2999
+ console.error("INDEX.JS: Error in proveTransaction:", error);
3000
+ throw error;
3001
+ }
2823
3002
  }
2824
3003
 
2825
3004
  async applyTransaction(transactionResult, submissionHeight) {
2826
- return this._serializeWasmCall(async () => {
2827
- try {
2828
- if (!this.worker) {
2829
- const wasmWebClient = await this.getWasmWebClient();
2830
- return await wasmWebClient.applyTransaction(
2831
- transactionResult,
2832
- submissionHeight
2833
- );
2834
- }
2835
-
2836
- const wasm = await getWasmOrThrow();
2837
- const serializedTransactionResult = transactionResult.serialize();
2838
- const serializedUpdateBytes = await this.callMethodWithWorker(
2839
- MethodName.APPLY_TRANSACTION,
2840
- serializedTransactionResult,
3005
+ try {
3006
+ if (!this.worker) {
3007
+ const wasmWebClient = await this.getWasmWebClient();
3008
+ return await wasmWebClient.applyTransaction(
3009
+ transactionResult,
2841
3010
  submissionHeight
2842
3011
  );
2843
-
2844
- return wasm.TransactionStoreUpdate.deserialize(
2845
- new Uint8Array(serializedUpdateBytes)
2846
- );
2847
- } catch (error) {
2848
- console.error("INDEX.JS: Error in applyTransaction:", error);
2849
- throw error;
2850
3012
  }
2851
- });
3013
+
3014
+ const wasm = await getWasmOrThrow();
3015
+ const serializedTransactionResult = transactionResult.serialize();
3016
+ const serializedUpdateBytes = await this.callMethodWithWorker(
3017
+ MethodName.APPLY_TRANSACTION,
3018
+ serializedTransactionResult,
3019
+ submissionHeight
3020
+ );
3021
+
3022
+ return wasm.TransactionStoreUpdate.deserialize(
3023
+ new Uint8Array(serializedUpdateBytes)
3024
+ );
3025
+ } catch (error) {
3026
+ console.error("INDEX.JS: Error in applyTransaction:", error);
3027
+ throw error;
3028
+ }
2852
3029
  }
2853
3030
 
2854
3031
  /**
@@ -2887,25 +3064,21 @@ class WebClient {
2887
3064
  return lockHandle.coalescedResult;
2888
3065
  }
2889
3066
 
2890
- // We acquired the lock - perform the sync. Wrap the actual WASM
2891
- // call in _serializeWasmCall so it can't race with any other
2892
- // mutating method (executeTransaction, submitNewTransaction, etc.)
2893
- // on the same WebClient. The outer coalescing lock stays in place
2894
- // so concurrent syncState callers still share one in-flight sync.
3067
+ // We acquired the lock - perform the sync
2895
3068
  try {
2896
- const result = await this._serializeWasmCall(async () => {
2897
- if (!this.worker) {
2898
- const wasmWebClient = await this.getWasmWebClient();
2899
- return await wasmWebClient.syncStateImpl();
2900
- }
3069
+ let result;
3070
+ if (!this.worker) {
3071
+ const wasmWebClient = await this.getWasmWebClient();
3072
+ result = await wasmWebClient.syncStateImpl();
3073
+ } else {
2901
3074
  const wasm = await getWasmOrThrow();
2902
3075
  const serializedSyncSummaryBytes = await this.callMethodWithWorker(
2903
3076
  MethodName.SYNC_STATE
2904
3077
  );
2905
- return wasm.SyncSummary.deserialize(
3078
+ result = wasm.SyncSummary.deserialize(
2906
3079
  new Uint8Array(serializedSyncSummaryBytes)
2907
3080
  );
2908
- });
3081
+ }
2909
3082
 
2910
3083
  // Release the lock with the result
2911
3084
  releaseSyncLock(dbId, result);
@@ -2984,9 +3157,9 @@ class MockWebClient extends WebClient {
2984
3157
  // Wait for the underlying wasmWebClient to be initialized.
2985
3158
  const wasmWebClient = await instance.getWasmWebClient();
2986
3159
  await wasmWebClient.createMockClient(
2987
- seed,
2988
- serializedMockChain,
2989
- serializedMockNoteTransportNode
3160
+ seed ?? null,
3161
+ serializedMockChain ?? null,
3162
+ serializedMockNoteTransportNode ?? null
2990
3163
  );
2991
3164
 
2992
3165
  // Wait for the worker to be ready
@@ -3031,9 +3204,11 @@ class MockWebClient extends WebClient {
3031
3204
  if (!this.worker) {
3032
3205
  result = await wasmWebClient.syncStateImpl();
3033
3206
  } else {
3034
- let serializedMockChain = wasmWebClient.serializeMockChain().buffer;
3035
- let serializedMockNoteTransportNode =
3036
- wasmWebClient.serializeMockNoteTransportNode().buffer;
3207
+ let serializedMockChain = (await wasmWebClient.serializeMockChain())
3208
+ .buffer;
3209
+ let serializedMockNoteTransportNode = (
3210
+ await wasmWebClient.serializeMockNoteTransportNode()
3211
+ ).buffer;
3037
3212
 
3038
3213
  const wasm = await getWasmOrThrow();
3039
3214
 
@@ -3069,9 +3244,11 @@ class MockWebClient extends WebClient {
3069
3244
  const wasmWebClient = await this.getWasmWebClient();
3070
3245
  const wasm = await getWasmOrThrow();
3071
3246
  const serializedTransactionRequest = transactionRequest.serialize();
3072
- const serializedMockChain = wasmWebClient.serializeMockChain().buffer;
3073
- const serializedMockNoteTransportNode =
3074
- wasmWebClient.serializeMockNoteTransportNode().buffer;
3247
+ const serializedMockChain = (await wasmWebClient.serializeMockChain())
3248
+ .buffer;
3249
+ const serializedMockNoteTransportNode = (
3250
+ await wasmWebClient.serializeMockNoteTransportNode()
3251
+ ).buffer;
3075
3252
 
3076
3253
  const result = await this.callMethodWithWorker(
3077
3254
  MethodName.SUBMIT_NEW_TRANSACTION_MOCK,
@@ -3123,9 +3300,11 @@ class MockWebClient extends WebClient {
3123
3300
  const wasm = await getWasmOrThrow();
3124
3301
  const serializedTransactionRequest = transactionRequest.serialize();
3125
3302
  const proverPayload = prover.serialize();
3126
- const serializedMockChain = wasmWebClient.serializeMockChain().buffer;
3127
- const serializedMockNoteTransportNode =
3128
- wasmWebClient.serializeMockNoteTransportNode().buffer;
3303
+ const serializedMockChain = (await wasmWebClient.serializeMockChain())
3304
+ .buffer;
3305
+ const serializedMockNoteTransportNode = (
3306
+ await wasmWebClient.serializeMockNoteTransportNode()
3307
+ ).buffer;
3129
3308
 
3130
3309
  const result = await this.callMethodWithWorker(
3131
3310
  MethodName.SUBMIT_NEW_TRANSACTION_WITH_PROVER_MOCK,
@@ -3189,5 +3368,5 @@ MidenClient._MockWasmWebClient = MockWebClient;
3189
3368
  MidenClient._getWasmOrThrow = getWasmOrThrow;
3190
3369
  _setWebClient(WebClient);
3191
3370
 
3192
- export { AccountType, AuthScheme, CompilerResource, Linking, MidenArrays, MidenClient, MockWebClient as MockWasmWebClient, NoteVisibility, StorageMode, WebClient as WasmWebClient, buildSwapTag, createP2IDENote, createP2IDNote, getWasmOrThrow };
3371
+ export { AccountType, AuthScheme, CompilerResource, Linking, MidenArrays, MidenClient, MockWebClient as MockWasmWebClient, MockWebClient, NoteVisibility, StorageMode, StorageResult, StorageView, WebClient as WasmWebClient, buildSwapTag, createP2IDENote, createP2IDNote, getWasmOrThrow, wordToBigInt };
3193
3372
  //# sourceMappingURL=index.js.map