@miden-sdk/miden-sdk 0.15.0-alpha.4 → 0.15.0-alpha.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/README.md +139 -9
- package/dist/mt/Cargo-smJQCGjz.js +26146 -0
- package/dist/mt/Cargo-smJQCGjz.js.map +1 -0
- package/dist/{api-types.d.ts → mt/api-types.d.ts} +154 -4
- package/dist/mt/assets/miden_client_web.wasm +0 -0
- package/dist/mt/crates/miden_client_web.d.ts +4791 -0
- package/dist/mt/eager.js +38 -0
- package/dist/mt/eager.js.map +1 -0
- package/dist/{index.d.ts → mt/index.d.ts} +4 -2
- package/dist/mt/index.js +3778 -0
- package/dist/mt/index.js.map +1 -0
- package/dist/{wasm.js → mt/wasm.js} +1 -1
- package/dist/mt/wasm.js.map +1 -0
- package/dist/mt/workerHelpers.js +28 -0
- package/dist/mt/workers/Cargo-smJQCGjz-q4GYXDiD.js +26147 -0
- package/dist/mt/workers/Cargo-smJQCGjz-q4GYXDiD.js.map +1 -0
- package/dist/mt/workers/assets/miden_client_web.wasm +0 -0
- package/dist/mt/workers/web-client-methods-worker.js +26885 -0
- package/dist/mt/workers/web-client-methods-worker.js.map +1 -0
- package/dist/{workers → mt/workers}/web-client-methods-worker.module.js +17 -1
- package/dist/mt/workers/web-client-methods-worker.module.js.map +1 -0
- package/dist/mt/workers/workerHelpers.js +28 -0
- package/dist/{Cargo-CVlXCH_2.js → st/Cargo-CG4XszZo.js} +698 -495
- package/dist/st/Cargo-CG4XszZo.js.map +1 -0
- package/dist/st/api-types.d.ts +1140 -0
- package/dist/{workers → st}/assets/miden_client_web.wasm +0 -0
- package/dist/{crates → st/crates}/miden_client_web.d.ts +342 -196
- package/dist/st/docs-entry.d.ts +38 -0
- package/dist/{eager.js → st/eager.js} +1 -1
- package/dist/st/eager.js.map +1 -0
- package/dist/st/index.d.ts +182 -0
- package/dist/{index.js → st/index.js} +425 -19
- package/dist/st/index.js.map +1 -0
- package/dist/st/wasm.js +23 -0
- package/dist/st/wasm.js.map +1 -0
- package/dist/{workers/Cargo-CVlXCH_2-CWA-5vlh.js → st/workers/Cargo-CG4XszZo-S7EHAZSa.js} +698 -495
- package/dist/st/workers/Cargo-CG4XszZo-S7EHAZSa.js.map +1 -0
- package/dist/{assets → st/workers/assets}/miden_client_web.wasm +0 -0
- package/dist/{workers → st/workers}/web-client-methods-worker.js +715 -496
- package/dist/st/workers/web-client-methods-worker.js.map +1 -0
- package/dist/st/workers/web-client-methods-worker.module.js +575 -0
- package/dist/st/workers/web-client-methods-worker.module.js.map +1 -0
- package/js/client.js +166 -2
- package/js/node/napi-compat.js +15 -0
- package/js/node-index.js +0 -1
- package/js/resources/accounts.js +4 -6
- package/js/resources/transactions.js +134 -0
- package/lazy/package.json +2 -2
- package/mt/lazy/package.json +4 -0
- package/mt/package.json +4 -0
- package/package.json +30 -15
- package/dist/Cargo-CVlXCH_2.js.map +0 -1
- package/dist/eager.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/wasm.js.map +0 -1
- package/dist/workers/Cargo-CVlXCH_2-CWA-5vlh.js.map +0 -1
- package/dist/workers/web-client-methods-worker.js.map +0 -1
- package/dist/workers/web-client-methods-worker.module.js.map +0 -1
- /package/dist/{docs-entry.d.ts → mt/docs-entry.d.ts} +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
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,
|
|
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, sequentialSumBench, setupLogging } from './Cargo-CG4XszZo.js';
|
|
3
3
|
|
|
4
4
|
const WorkerAction = Object.freeze({
|
|
5
5
|
INIT: "init",
|
|
6
6
|
INIT_MOCK: "initMock",
|
|
7
|
+
INIT_THREAD_POOL: "initThreadPool",
|
|
7
8
|
CALL_METHOD: "callMethod",
|
|
8
9
|
EXECUTE_CALLBACK: "executeCallback",
|
|
9
10
|
});
|
|
@@ -504,6 +505,7 @@ class AccountsResource {
|
|
|
504
505
|
return await this.#inner.newFaucet(
|
|
505
506
|
storageMode,
|
|
506
507
|
type === 1 || type === "NonFungibleFaucet",
|
|
508
|
+
opts.name ?? opts.symbol,
|
|
507
509
|
opts.symbol,
|
|
508
510
|
opts.decimals,
|
|
509
511
|
BigInt(opts.maxSupply),
|
|
@@ -536,11 +538,9 @@ class AccountsResource {
|
|
|
536
538
|
if (!opts.auth)
|
|
537
539
|
throw new Error("Contract creation requires an 'auth' (AuthSecretKey)");
|
|
538
540
|
|
|
539
|
-
//
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
? wasm.AccountType.RegularAccountUpdatableCode
|
|
543
|
-
: wasm.AccountType.RegularAccountImmutableCode;
|
|
541
|
+
// The 0.15 protocol has no code-mutability distinction, so the `type`
|
|
542
|
+
// ("ImmutableContract" / "MutableContract") only steers routing here; the
|
|
543
|
+
// account's on-chain visibility is set entirely by `storageMode`.
|
|
544
544
|
const storageMode = resolveStorageMode(opts.storage ?? "public", wasm);
|
|
545
545
|
const authComponent =
|
|
546
546
|
wasm.AccountComponent.createAuthComponentFromSecretKey(opts.auth);
|
|
@@ -555,7 +555,6 @@ class AccountsResource {
|
|
|
555
555
|
}
|
|
556
556
|
|
|
557
557
|
let builder = new wasm.AccountBuilder(opts.seed)
|
|
558
|
-
.accountType(accountTypeEnum)
|
|
559
558
|
.storageMode(storageMode)
|
|
560
559
|
.withAuthComponent(authComponent);
|
|
561
560
|
|
|
@@ -866,6 +865,72 @@ class TransactionsResource {
|
|
|
866
865
|
return { txId, result };
|
|
867
866
|
}
|
|
868
867
|
|
|
868
|
+
/** Create a partial-swap (PSWAP) note. See {@link PswapCreateOptions}. */
|
|
869
|
+
async pswapCreate(opts) {
|
|
870
|
+
this.#client.assertNotTerminated();
|
|
871
|
+
const wasm = await this.#getWasm();
|
|
872
|
+
const { accountId, request } = await this.#buildPswapCreateRequest(
|
|
873
|
+
opts,
|
|
874
|
+
wasm
|
|
875
|
+
);
|
|
876
|
+
|
|
877
|
+
const { txId, result } = await this.#submitOrSubmitWithProver(
|
|
878
|
+
accountId,
|
|
879
|
+
request,
|
|
880
|
+
opts.prover
|
|
881
|
+
);
|
|
882
|
+
|
|
883
|
+
if (opts.waitForConfirmation) {
|
|
884
|
+
await this.waitFor(txId.toHex(), { timeout: opts.timeout });
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
return { txId, result };
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/** Consume (fully or partially fill) a PSWAP note. See {@link PswapConsumeOptions}. */
|
|
891
|
+
async pswapConsume(opts) {
|
|
892
|
+
this.#client.assertNotTerminated();
|
|
893
|
+
const wasm = await this.#getWasm();
|
|
894
|
+
const { accountId, request } = await this.#buildPswapConsumeRequest(
|
|
895
|
+
opts,
|
|
896
|
+
wasm
|
|
897
|
+
);
|
|
898
|
+
|
|
899
|
+
const { txId, result } = await this.#submitOrSubmitWithProver(
|
|
900
|
+
accountId,
|
|
901
|
+
request,
|
|
902
|
+
opts.prover
|
|
903
|
+
);
|
|
904
|
+
|
|
905
|
+
if (opts.waitForConfirmation) {
|
|
906
|
+
await this.waitFor(txId.toHex(), { timeout: opts.timeout });
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
return { txId, result };
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
/** Cancel a PSWAP note as its creator and reclaim the offered asset. See {@link PswapCancelOptions}. */
|
|
913
|
+
async pswapCancel(opts) {
|
|
914
|
+
this.#client.assertNotTerminated();
|
|
915
|
+
const wasm = await this.#getWasm();
|
|
916
|
+
const { accountId, request } = await this.#buildPswapCancelRequest(
|
|
917
|
+
opts,
|
|
918
|
+
wasm
|
|
919
|
+
);
|
|
920
|
+
|
|
921
|
+
const { txId, result } = await this.#submitOrSubmitWithProver(
|
|
922
|
+
accountId,
|
|
923
|
+
request,
|
|
924
|
+
opts.prover
|
|
925
|
+
);
|
|
926
|
+
|
|
927
|
+
if (opts.waitForConfirmation) {
|
|
928
|
+
await this.waitFor(txId.toHex(), { timeout: opts.timeout });
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
return { txId, result };
|
|
932
|
+
}
|
|
933
|
+
|
|
869
934
|
async preview(opts) {
|
|
870
935
|
this.#client.assertNotTerminated();
|
|
871
936
|
const wasm = await this.#getWasm();
|
|
@@ -890,6 +955,27 @@ class TransactionsResource {
|
|
|
890
955
|
({ accountId, request } = await this.#buildSwapRequest(opts, wasm));
|
|
891
956
|
break;
|
|
892
957
|
}
|
|
958
|
+
case "pswapCreate": {
|
|
959
|
+
({ accountId, request } = await this.#buildPswapCreateRequest(
|
|
960
|
+
opts,
|
|
961
|
+
wasm
|
|
962
|
+
));
|
|
963
|
+
break;
|
|
964
|
+
}
|
|
965
|
+
case "pswapConsume": {
|
|
966
|
+
({ accountId, request } = await this.#buildPswapConsumeRequest(
|
|
967
|
+
opts,
|
|
968
|
+
wasm
|
|
969
|
+
));
|
|
970
|
+
break;
|
|
971
|
+
}
|
|
972
|
+
case "pswapCancel": {
|
|
973
|
+
({ accountId, request } = await this.#buildPswapCancelRequest(
|
|
974
|
+
opts,
|
|
975
|
+
wasm
|
|
976
|
+
));
|
|
977
|
+
break;
|
|
978
|
+
}
|
|
893
979
|
case "custom": {
|
|
894
980
|
accountId = resolveAccountRef(opts.account, wasm);
|
|
895
981
|
request = opts.request;
|
|
@@ -1176,6 +1262,53 @@ class TransactionsResource {
|
|
|
1176
1262
|
return { accountId, request };
|
|
1177
1263
|
}
|
|
1178
1264
|
|
|
1265
|
+
async #buildPswapCreateRequest(opts, wasm) {
|
|
1266
|
+
const accountId = resolveAccountRef(opts.account, wasm);
|
|
1267
|
+
const offeredFaucetId = resolveAccountRef(opts.offer.token, wasm);
|
|
1268
|
+
const requestedFaucetId = resolveAccountRef(opts.request.token, wasm);
|
|
1269
|
+
const noteType = resolveNoteType(opts.type, wasm);
|
|
1270
|
+
const paybackNoteType = resolveNoteType(
|
|
1271
|
+
opts.paybackType ?? opts.type,
|
|
1272
|
+
wasm
|
|
1273
|
+
);
|
|
1274
|
+
|
|
1275
|
+
const request = await this.#inner.newPswapCreateTransactionRequest(
|
|
1276
|
+
accountId,
|
|
1277
|
+
offeredFaucetId,
|
|
1278
|
+
BigInt(opts.offer.amount),
|
|
1279
|
+
requestedFaucetId,
|
|
1280
|
+
BigInt(opts.request.amount),
|
|
1281
|
+
noteType,
|
|
1282
|
+
paybackNoteType
|
|
1283
|
+
);
|
|
1284
|
+
return { accountId, request };
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
async #buildPswapConsumeRequest(opts, wasm) {
|
|
1288
|
+
const accountId = resolveAccountRef(opts.account, wasm);
|
|
1289
|
+
const note = await this.#resolveNoteInput(opts.note);
|
|
1290
|
+
const noteFillAmount = opts.noteFillAmount ?? 0n;
|
|
1291
|
+
|
|
1292
|
+
const request = await this.#inner.newPswapConsumeTransactionRequest(
|
|
1293
|
+
note,
|
|
1294
|
+
accountId,
|
|
1295
|
+
BigInt(opts.fillAmount),
|
|
1296
|
+
BigInt(noteFillAmount)
|
|
1297
|
+
);
|
|
1298
|
+
return { accountId, request };
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
async #buildPswapCancelRequest(opts, wasm) {
|
|
1302
|
+
const accountId = resolveAccountRef(opts.account, wasm);
|
|
1303
|
+
const note = await this.#resolveNoteInput(opts.note);
|
|
1304
|
+
|
|
1305
|
+
const request = await this.#inner.newPswapCancelTransactionRequest(
|
|
1306
|
+
note,
|
|
1307
|
+
accountId
|
|
1308
|
+
);
|
|
1309
|
+
return { accountId, request };
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1179
1312
|
async #resolveNoteInput(input) {
|
|
1180
1313
|
if (typeof input === "string") {
|
|
1181
1314
|
const record = await this.#inner.getInputNote(input);
|
|
@@ -1565,6 +1698,80 @@ class MidenClient {
|
|
|
1565
1698
|
this.keystore = new KeystoreResource(inner, this);
|
|
1566
1699
|
}
|
|
1567
1700
|
|
|
1701
|
+
/**
|
|
1702
|
+
* Escape hatch: runs `fn` with exclusive access to the proxied JS
|
|
1703
|
+
* WebClient that backs this MidenClient.
|
|
1704
|
+
*
|
|
1705
|
+
* The proxy forwards missing properties to the underlying wasm-bindgen
|
|
1706
|
+
* `WebClient`, so `fn` can reach lower-level methods like
|
|
1707
|
+
* `executeTransaction`, `proveTransaction[WithProver]`,
|
|
1708
|
+
* `submitProvenTransaction`, `applyTransaction`,
|
|
1709
|
+
* `newSendTransactionRequest`, `newConsumeTransactionRequest`, etc.
|
|
1710
|
+
*
|
|
1711
|
+
* Intended for advanced consumers that need to split the bundled
|
|
1712
|
+
* execute → prove → submit → apply pipeline across contexts — for example,
|
|
1713
|
+
* a Chrome MV3 extension that runs `executeTransaction` in its service
|
|
1714
|
+
* worker, dispatches the prove step to a `chrome.offscreen` document
|
|
1715
|
+
* (where wasm-bindgen-rayon can spawn a real thread pool), then runs
|
|
1716
|
+
* `submitProvenTransaction` + `applyTransaction` back in the SW.
|
|
1717
|
+
*
|
|
1718
|
+
* The callback runs inside `_serializeWasmCall`, so the WASM RefCell is
|
|
1719
|
+
* held for the duration of `fn`. Concurrent SDK calls (sync, other
|
|
1720
|
+
* transactions, etc.) queue on the same chain and run after `fn`
|
|
1721
|
+
* settles. Without this serialization, raw inner-client access would
|
|
1722
|
+
* race the proxy's chain and trip wasm-bindgen's "recursive use of an
|
|
1723
|
+
* object detected" panic.
|
|
1724
|
+
*
|
|
1725
|
+
* Re-entrancy: while `fn` is running, the underlying client's
|
|
1726
|
+
* `_withInnerLockDepth` counter is bumped so that `_serializeWasmCall`
|
|
1727
|
+
* invocations made BY `fn` (or any proxy-dispatched method it calls)
|
|
1728
|
+
* run inline rather than enqueuing on the chain. Without this, every
|
|
1729
|
+
* `await inner.X(...)` inside `fn` would enqueue behind the outer
|
|
1730
|
+
* `_withInnerWebClient` slot which is itself awaiting `fn` —
|
|
1731
|
+
* a classic re-entrant-lock deadlock. The depth counter restores the
|
|
1732
|
+
* intent of the docstring above: the lock is held for the duration
|
|
1733
|
+
* of `fn`, and inner-client calls "borrow" that already-held lock
|
|
1734
|
+
* instead of trying to re-acquire it.
|
|
1735
|
+
*
|
|
1736
|
+
* SAFETY CONTRACT for re-entrancy: callers MUST hold an external
|
|
1737
|
+
* mutex preventing concurrent access to this same client instance
|
|
1738
|
+
* via other code paths during `fn`. The chain still serializes
|
|
1739
|
+
* against external callers — they queue behind the outer slot — but
|
|
1740
|
+
* if an external task runs during one of `fn`'s awaits and calls
|
|
1741
|
+
* into the SDK, it will see `_withInnerLockDepth > 0` and run
|
|
1742
|
+
* inline, racing wasm-bindgen's borrow check. The wallet pattern
|
|
1743
|
+
* (own outer mutex around `_withInnerWebClient`) satisfies this.
|
|
1744
|
+
*
|
|
1745
|
+
* Stability: marked `@internal`. The shape of the proxied client is
|
|
1746
|
+
* intentionally not part of the documented public API and may change
|
|
1747
|
+
* between SDK versions. If you depend on this method, pin the SDK
|
|
1748
|
+
* version and test the lower-level surface carefully on each upgrade.
|
|
1749
|
+
* If your use case is common enough to warrant a stable public API,
|
|
1750
|
+
* file an issue.
|
|
1751
|
+
*
|
|
1752
|
+
* @internal
|
|
1753
|
+
* @template T
|
|
1754
|
+
* @param {(inner: object) => Promise<T>} fn - Async callback receiving
|
|
1755
|
+
* the proxied JS WebClient. Must not return references that escape
|
|
1756
|
+
* the callback's lifetime (the lock is released on settle).
|
|
1757
|
+
* @returns {Promise<T>} The resolved value of `fn`.
|
|
1758
|
+
*/
|
|
1759
|
+
_withInnerWebClient(fn) {
|
|
1760
|
+
this.assertNotTerminated();
|
|
1761
|
+
if (typeof fn !== "function") {
|
|
1762
|
+
throw new TypeError("_withInnerWebClient: fn must be a function");
|
|
1763
|
+
}
|
|
1764
|
+
const inner = this.#inner;
|
|
1765
|
+
return inner._serializeWasmCall(async () => {
|
|
1766
|
+
inner._withInnerLockDepth = (inner._withInnerLockDepth || 0) + 1;
|
|
1767
|
+
try {
|
|
1768
|
+
return await fn(inner);
|
|
1769
|
+
} finally {
|
|
1770
|
+
inner._withInnerLockDepth--;
|
|
1771
|
+
}
|
|
1772
|
+
});
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1568
1775
|
/**
|
|
1569
1776
|
* Creates and initializes a new MidenClient.
|
|
1570
1777
|
*
|
|
@@ -1593,6 +1800,13 @@ class MidenClient {
|
|
|
1593
1800
|
const rpcUrl = resolveRpcUrl(options?.rpcUrl);
|
|
1594
1801
|
const noteTransportUrl = resolveNoteTransportUrl(options?.noteTransportUrl);
|
|
1595
1802
|
|
|
1803
|
+
// `useWorker: false` opts out of the Web Worker shim that wraps every
|
|
1804
|
+
// WASM call. The shim exists to keep the main thread responsive in
|
|
1805
|
+
// browser/extension contexts, but it serializes the prover via
|
|
1806
|
+
// `TransactionProver.serialize()` — a format that has no encoding for
|
|
1807
|
+
// `newCallbackProver(jsFn)` and silently downgrades it to `"local"`.
|
|
1808
|
+
// Mobile/Tauri/native-prover consumers must pass `useWorker: false`.
|
|
1809
|
+
const useWorker = options?.useWorker;
|
|
1596
1810
|
let inner;
|
|
1597
1811
|
if (options?.keystore) {
|
|
1598
1812
|
inner = await WebClientClass.createClientWithExternalKeystore(
|
|
@@ -1603,7 +1817,8 @@ class MidenClient {
|
|
|
1603
1817
|
options.keystore.getKey,
|
|
1604
1818
|
options.keystore.insertKey,
|
|
1605
1819
|
options.keystore.sign,
|
|
1606
|
-
options?.debugMode
|
|
1820
|
+
options?.debugMode,
|
|
1821
|
+
useWorker
|
|
1607
1822
|
);
|
|
1608
1823
|
} else {
|
|
1609
1824
|
inner = await WebClientClass.createClient(
|
|
@@ -1611,7 +1826,8 @@ class MidenClient {
|
|
|
1611
1826
|
noteTransportUrl,
|
|
1612
1827
|
seed,
|
|
1613
1828
|
options?.storeName,
|
|
1614
|
-
options?.debugMode
|
|
1829
|
+
options?.debugMode,
|
|
1830
|
+
useWorker
|
|
1615
1831
|
);
|
|
1616
1832
|
}
|
|
1617
1833
|
|
|
@@ -1668,6 +1884,32 @@ class MidenClient {
|
|
|
1668
1884
|
});
|
|
1669
1885
|
}
|
|
1670
1886
|
|
|
1887
|
+
/**
|
|
1888
|
+
* Resolves once the WASM module is initialized and safe to use.
|
|
1889
|
+
*
|
|
1890
|
+
* Idempotent and shared across callers: the underlying loader memoizes the
|
|
1891
|
+
* in-flight promise, so concurrent `ready()` calls await the same
|
|
1892
|
+
* initialization and post-init callers resolve immediately from a cached
|
|
1893
|
+
* module. Safe to call from `MidenProvider`, tutorial helpers, and any
|
|
1894
|
+
* other consumer simultaneously.
|
|
1895
|
+
*
|
|
1896
|
+
* Useful on the `/lazy` entry (e.g. Next.js / Capacitor), where no
|
|
1897
|
+
* top-level await runs at import time. On the default (eager) entry this
|
|
1898
|
+
* is redundant — importing the module already awaits WASM — but calling it
|
|
1899
|
+
* is still harmless.
|
|
1900
|
+
*
|
|
1901
|
+
* @returns {Promise<void>} Resolves when WASM is initialized.
|
|
1902
|
+
*/
|
|
1903
|
+
static async ready() {
|
|
1904
|
+
const getWasm = MidenClient._getWasmOrThrow;
|
|
1905
|
+
if (!getWasm) {
|
|
1906
|
+
throw new Error(
|
|
1907
|
+
"MidenClient not initialized. Import from the SDK package entry point."
|
|
1908
|
+
);
|
|
1909
|
+
}
|
|
1910
|
+
await getWasm();
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1671
1913
|
/**
|
|
1672
1914
|
* Creates a mock client for testing.
|
|
1673
1915
|
*
|
|
@@ -1724,6 +1966,61 @@ class MidenClient {
|
|
|
1724
1966
|
return await this.#inner.getSyncHeight();
|
|
1725
1967
|
}
|
|
1726
1968
|
|
|
1969
|
+
/**
|
|
1970
|
+
* Resolves once every serialized WASM call that was already on the
|
|
1971
|
+
* internal `_serializeWasmCall` chain when `waitForIdle()` was called
|
|
1972
|
+
* (execute, submit, prove, apply, sync, or account creation) has
|
|
1973
|
+
* settled. Use this from callers that need to perform a non-WASM-side
|
|
1974
|
+
* action — e.g. clearing an in-memory auth key on wallet lock — after
|
|
1975
|
+
* the kernel finishes, so its auth callback doesn't race with the key
|
|
1976
|
+
* being cleared.
|
|
1977
|
+
*
|
|
1978
|
+
* Does NOT wait for calls enqueued after `waitForIdle()` returns —
|
|
1979
|
+
* intentional, so a caller can drain and proceed without being blocked
|
|
1980
|
+
* indefinitely by concurrent workload.
|
|
1981
|
+
*
|
|
1982
|
+
* Caveat for `syncState`: `syncStateWithTimeout` awaits the sync lock
|
|
1983
|
+
* (`acquireSyncLock`, which uses Web Locks) BEFORE putting its WASM
|
|
1984
|
+
* call onto the chain, so a `syncState` that is queued on the sync
|
|
1985
|
+
* lock — but has not yet begun its WASM phase — is not visible to
|
|
1986
|
+
* `waitForIdle` and will not be awaited. Other methods (`newWallet`,
|
|
1987
|
+
* `executeTransaction`, etc.) route through the chain synchronously
|
|
1988
|
+
* on call and are always observed.
|
|
1989
|
+
*
|
|
1990
|
+
* Safe to call at any time; returns immediately if nothing was in
|
|
1991
|
+
* flight.
|
|
1992
|
+
*
|
|
1993
|
+
* @returns {Promise<void>}
|
|
1994
|
+
*/
|
|
1995
|
+
async waitForIdle() {
|
|
1996
|
+
this.assertNotTerminated();
|
|
1997
|
+
await this.#inner.waitForIdle();
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
/**
|
|
2001
|
+
* Returns the raw JS value that the most recent sign-callback invocation
|
|
2002
|
+
* threw, or `null` if the last sign call succeeded (or no call has
|
|
2003
|
+
* happened yet).
|
|
2004
|
+
*
|
|
2005
|
+
* Useful for recovering structured metadata (e.g. a `reason: 'locked'`
|
|
2006
|
+
* property) that the kernel-level `auth::request` diagnostic would
|
|
2007
|
+
* otherwise erase. Call immediately after catching a failed
|
|
2008
|
+
* `transactions.submit` / `transactions.send` / `transactions.consume`.
|
|
2009
|
+
*
|
|
2010
|
+
* Meaningful only with `useWorker: false`: under the worker shim the
|
|
2011
|
+
* sign callback fires against the worker's WASM keystore, while this
|
|
2012
|
+
* accessor reads the main-thread instance — which never signed — so it
|
|
2013
|
+
* returns `null`. Consumers that need this signal (e.g. external
|
|
2014
|
+
* keystores with lock-aware sign callbacks) already require
|
|
2015
|
+
* `useWorker: false` for the callback to be reachable at all.
|
|
2016
|
+
*
|
|
2017
|
+
* @returns {any} The raw thrown value, or `null`.
|
|
2018
|
+
*/
|
|
2019
|
+
lastAuthError() {
|
|
2020
|
+
this.assertNotTerminated();
|
|
2021
|
+
return this.#inner.lastAuthError();
|
|
2022
|
+
}
|
|
2023
|
+
|
|
1727
2024
|
/**
|
|
1728
2025
|
* Terminates the underlying Web Worker. After this, all method calls will throw.
|
|
1729
2026
|
*/
|
|
@@ -2319,7 +2616,6 @@ const NoteVisibility = Object.freeze({
|
|
|
2319
2616
|
const StorageMode = Object.freeze({
|
|
2320
2617
|
Public: "public",
|
|
2321
2618
|
Private: "private",
|
|
2322
|
-
Network: "network",
|
|
2323
2619
|
});
|
|
2324
2620
|
|
|
2325
2621
|
const Linking = Object.freeze({
|
|
@@ -2513,6 +2809,15 @@ class WebClient {
|
|
|
2513
2809
|
* @param {string | undefined} [logLevel] - Optional log verbosity level
|
|
2514
2810
|
* ("error", "warn", "info", "debug", "trace", "off", or "none").
|
|
2515
2811
|
* When set, Rust tracing output is routed to the browser console.
|
|
2812
|
+
* @param {boolean} [useWorker=true] - When `false`, skip the Web Worker shim
|
|
2813
|
+
* and call the wasm-bindgen `WebClient` directly on the current thread.
|
|
2814
|
+
* The worker exists to keep the main thread responsive during WASM work
|
|
2815
|
+
* in browser/extension contexts, but it serializes the prover argument
|
|
2816
|
+
* via `TransactionProver.serialize()` — a format that has no encoding
|
|
2817
|
+
* for `newCallbackProver(jsFn)` and silently downgrades it to `"local"`.
|
|
2818
|
+
* Consumers that hand a `CallbackProver` (e.g. native iOS/Android plug-in
|
|
2819
|
+
* provers in Capacitor apps, or any other JS-side prover bridge) need
|
|
2820
|
+
* `useWorker: false` so the prover handle reaches the WASM binding intact.
|
|
2516
2821
|
*/
|
|
2517
2822
|
constructor(
|
|
2518
2823
|
rpcUrl,
|
|
@@ -2522,7 +2827,8 @@ class WebClient {
|
|
|
2522
2827
|
getKeyCb,
|
|
2523
2828
|
insertKeyCb,
|
|
2524
2829
|
signCb,
|
|
2525
|
-
logLevel
|
|
2830
|
+
logLevel,
|
|
2831
|
+
useWorker = true
|
|
2526
2832
|
) {
|
|
2527
2833
|
this.rpcUrl = rpcUrl;
|
|
2528
2834
|
this.noteTransportUrl = noteTransportUrl;
|
|
@@ -2532,9 +2838,12 @@ class WebClient {
|
|
|
2532
2838
|
this.insertKeyCb = insertKeyCb;
|
|
2533
2839
|
this.signCb = signCb;
|
|
2534
2840
|
this.logLevel = logLevel;
|
|
2841
|
+
this.useWorker = useWorker !== false;
|
|
2535
2842
|
|
|
2536
|
-
// Check if Web Workers are available
|
|
2537
|
-
|
|
2843
|
+
// Check if Web Workers are available AND the caller didn't opt out via
|
|
2844
|
+
// `useWorker: false`. The opt-out is load-bearing for `CallbackProver`
|
|
2845
|
+
// consumers — see the constructor doc above.
|
|
2846
|
+
if (this.useWorker && typeof Worker !== "undefined") {
|
|
2538
2847
|
console.log("WebClient: Web Workers are available.");
|
|
2539
2848
|
// Pick between the module and classic worker variants at runtime — see
|
|
2540
2849
|
// `WebClient.workerMode` below. Both branches keep the
|
|
@@ -2648,8 +2957,12 @@ class WebClient {
|
|
|
2648
2957
|
// Once the worker script has loaded, initialize the worker.
|
|
2649
2958
|
this.loaded.then(() => this.initializeWorker());
|
|
2650
2959
|
} else {
|
|
2651
|
-
console.log(
|
|
2652
|
-
|
|
2960
|
+
console.log(
|
|
2961
|
+
this.useWorker
|
|
2962
|
+
? "WebClient: Web Workers are not available."
|
|
2963
|
+
: "WebClient: Web Worker shim disabled by caller (useWorker=false)."
|
|
2964
|
+
);
|
|
2965
|
+
// Worker not available or explicitly disabled; set up fallback values.
|
|
2653
2966
|
this.worker = null;
|
|
2654
2967
|
this.pendingRequests = null;
|
|
2655
2968
|
this.loaded = Promise.resolve();
|
|
@@ -2665,25 +2978,99 @@ class WebClient {
|
|
|
2665
2978
|
// would panic with "recursive use of an object detected" due to
|
|
2666
2979
|
// wasm-bindgen's internal RefCell.
|
|
2667
2980
|
this._wasmCallChain = Promise.resolve();
|
|
2981
|
+
// Depth counter for `_withInnerWebClient` re-entrancy. While > 0,
|
|
2982
|
+
// `_serializeWasmCall` runs its callback inline instead of queueing
|
|
2983
|
+
// it on the chain — see the comment on `_serializeWasmCall` for the
|
|
2984
|
+
// safety contract.
|
|
2985
|
+
this._withInnerLockDepth = 0;
|
|
2668
2986
|
}
|
|
2669
2987
|
|
|
2670
2988
|
/**
|
|
2671
2989
|
* Serialize a WASM call that requires exclusive (&mut self) access.
|
|
2672
2990
|
* Concurrent calls are queued and executed one at a time.
|
|
2673
2991
|
*
|
|
2992
|
+
* Wraps both the direct (in-thread) path and the worker-dispatched path.
|
|
2993
|
+
* On the worker path this is redundant with the worker's own message queue,
|
|
2994
|
+
* but harmless (the chain resolves immediately on the main thread once the
|
|
2995
|
+
* worker's postMessage returns). On the direct path it is load-bearing —
|
|
2996
|
+
* without it, concurrent main-thread callers would panic with
|
|
2997
|
+
* "recursive use of an object detected" (wasm-bindgen's internal RefCell).
|
|
2998
|
+
*
|
|
2999
|
+
* Re-entrancy: when invoked from inside a `_withInnerWebClient(fn)`
|
|
3000
|
+
* callback — detected via `_withInnerLockDepth > 0` — `fn` runs inline
|
|
3001
|
+
* (no chain enqueue). The outer `_withInnerWebClient` invocation
|
|
3002
|
+
* already holds the chain via its own wrapping `_serializeWasmCall`,
|
|
3003
|
+
* so enqueueing the inner call would deadlock (the inner queues
|
|
3004
|
+
* behind the outer; the outer awaits the inner). The inline run is
|
|
3005
|
+
* safe because the chain still serializes against external callers
|
|
3006
|
+
* — they queue behind the outer call's chain slot, which only resolves
|
|
3007
|
+
* after `fn` (including all inline re-entries) settles. Callers of
|
|
3008
|
+
* `_withInnerWebClient` MUST hold an external mutex preventing
|
|
3009
|
+
* concurrent access via other code paths on this same instance during
|
|
3010
|
+
* the callback; without that, an external task running between two
|
|
3011
|
+
* awaits inside `fn` would race wasm-bindgen's borrow check.
|
|
3012
|
+
*
|
|
2674
3013
|
* @param {() => Promise<any>} fn - The async function to execute.
|
|
2675
3014
|
* @returns {Promise<any>} The result of fn.
|
|
2676
3015
|
*/
|
|
2677
3016
|
_serializeWasmCall(fn) {
|
|
3017
|
+
if (this._withInnerLockDepth > 0) {
|
|
3018
|
+
return Promise.resolve().then(fn);
|
|
3019
|
+
}
|
|
2678
3020
|
const result = this._wasmCallChain.catch(() => {}).then(fn);
|
|
2679
3021
|
this._wasmCallChain = result.catch(() => {});
|
|
2680
3022
|
return result;
|
|
2681
3023
|
}
|
|
2682
3024
|
|
|
3025
|
+
/**
|
|
3026
|
+
* Returns a promise that resolves once every serialized WASM call that
|
|
3027
|
+
* was already on `_wasmCallChain` when `waitForIdle()` was called has
|
|
3028
|
+
* settled. Use this from callers that need to perform a non-WASM-side
|
|
3029
|
+
* action (e.g. clear an in-memory auth key) AFTER any in-flight
|
|
3030
|
+
* execute / submit / sync has completed, so the WASM kernel's auth
|
|
3031
|
+
* callback doesn't race with the key being cleared.
|
|
3032
|
+
*
|
|
3033
|
+
* Does NOT wait for calls enqueued after `waitForIdle()` returns —
|
|
3034
|
+
* this is intentional, so a caller can drain and then proceed without
|
|
3035
|
+
* being blocked indefinitely by a concurrent workload.
|
|
3036
|
+
*
|
|
3037
|
+
* Caveat for `syncState`: `syncStateWithTimeout` awaits
|
|
3038
|
+
* `acquireSyncLock` (Web Locks) BEFORE wrapping its WASM call in
|
|
3039
|
+
* `_serializeWasmCall`, so a sync that is queued on the sync lock but
|
|
3040
|
+
* has not yet reached its WASM phase is not on the chain and will not
|
|
3041
|
+
* be awaited. Every other serialized method (`executeTransaction`,
|
|
3042
|
+
* `newWallet`, `submitNewTransaction`, `proveTransaction`,
|
|
3043
|
+
* `applyTransaction`, and the proxy-fallback reads) routes through
|
|
3044
|
+
* the chain synchronously on call and is always observed.
|
|
3045
|
+
*
|
|
3046
|
+
* @returns {Promise<void>}
|
|
3047
|
+
*/
|
|
3048
|
+
async waitForIdle() {
|
|
3049
|
+
// Chain on `_wasmCallChain`; by the time this resolves, any in-flight
|
|
3050
|
+
// serialized call has settled. Catch so the chain state doesn't leak.
|
|
3051
|
+
await this._wasmCallChain.catch(() => {});
|
|
3052
|
+
}
|
|
3053
|
+
|
|
2683
3054
|
// TODO: This will soon conflict with some changes in main.
|
|
2684
3055
|
// More context here:
|
|
2685
3056
|
// https://github.com/0xMiden/miden-client/pull/1645?notification_referrer_id=NT_kwHOA1yg7NoAJVJlcG9zaXRvcnk7NjU5MzQzNzAyO0lzc3VlOzM3OTY4OTU1Nzk¬ifications_query=is%3Aunread#discussion_r2696075480
|
|
2686
3057
|
initializeWorker() {
|
|
3058
|
+
// Pass `numThreads` to the worker so it can call `wasm.initThreadPool(n)`
|
|
3059
|
+
// inside its OWN WASM instance — the SDK worker's instance is separate
|
|
3060
|
+
// from the main thread's, and rayon's global pool is per-instance.
|
|
3061
|
+
// Default: navigator.hardwareConcurrency (or 1 if unavailable for any
|
|
3062
|
+
// reason — e.g. the page isn't crossOriginIsolated, in which case the
|
|
3063
|
+
// worker will skip pool init and parallelism falls back to sequential).
|
|
3064
|
+
let numThreads = 1;
|
|
3065
|
+
try {
|
|
3066
|
+
if (
|
|
3067
|
+
typeof self !== "undefined" &&
|
|
3068
|
+
self.crossOriginIsolated &&
|
|
3069
|
+
navigator?.hardwareConcurrency
|
|
3070
|
+
) {
|
|
3071
|
+
numThreads = navigator.hardwareConcurrency;
|
|
3072
|
+
}
|
|
3073
|
+
} catch {}
|
|
2687
3074
|
this.worker.postMessage({
|
|
2688
3075
|
action: WorkerAction.INIT,
|
|
2689
3076
|
args: [
|
|
@@ -2695,6 +3082,7 @@ class WebClient {
|
|
|
2695
3082
|
!!this.insertKeyCb,
|
|
2696
3083
|
!!this.signCb,
|
|
2697
3084
|
this.logLevel,
|
|
3085
|
+
numThreads,
|
|
2698
3086
|
],
|
|
2699
3087
|
});
|
|
2700
3088
|
}
|
|
@@ -2723,9 +3111,19 @@ class WebClient {
|
|
|
2723
3111
|
* @param {string} seed - The seed for the account.
|
|
2724
3112
|
* @param {string | undefined} network - Optional name for the store. Setting this allows multiple clients to be used in the same browser.
|
|
2725
3113
|
* @param {string | undefined} logLevel - Optional log verbosity level ("error", "warn", "info", "debug", "trace", "off", or "none").
|
|
3114
|
+
* @param {boolean} [useWorker=true] - When `false`, bypass the Web Worker shim
|
|
3115
|
+
* and run WASM calls on the current thread. Required for `CallbackProver`
|
|
3116
|
+
* consumers (the worker path serializes the prover and loses the callback).
|
|
2726
3117
|
* @returns {Promise<WebClient>} The fully initialized WebClient.
|
|
2727
3118
|
*/
|
|
2728
|
-
static async createClient(
|
|
3119
|
+
static async createClient(
|
|
3120
|
+
rpcUrl,
|
|
3121
|
+
noteTransportUrl,
|
|
3122
|
+
seed,
|
|
3123
|
+
network,
|
|
3124
|
+
logLevel,
|
|
3125
|
+
useWorker = true
|
|
3126
|
+
) {
|
|
2729
3127
|
// Construct the instance (synchronously).
|
|
2730
3128
|
const instance = new WebClient(
|
|
2731
3129
|
rpcUrl,
|
|
@@ -2735,7 +3133,8 @@ class WebClient {
|
|
|
2735
3133
|
undefined,
|
|
2736
3134
|
undefined,
|
|
2737
3135
|
undefined,
|
|
2738
|
-
logLevel
|
|
3136
|
+
logLevel,
|
|
3137
|
+
useWorker
|
|
2739
3138
|
);
|
|
2740
3139
|
|
|
2741
3140
|
// Set up logging on the main thread before creating the client.
|
|
@@ -2766,6 +3165,9 @@ class WebClient {
|
|
|
2766
3165
|
* @param {Function | undefined} insertKeyCb - The insert key callback.
|
|
2767
3166
|
* @param {Function | undefined} signCb - The sign callback.
|
|
2768
3167
|
* @param {string | undefined} logLevel - Optional log verbosity level ("error", "warn", "info", "debug", "trace", "off", or "none").
|
|
3168
|
+
* @param {boolean} [useWorker=true] - When `false`, bypass the Web Worker shim
|
|
3169
|
+
* and run WASM calls on the current thread. Required for `CallbackProver`
|
|
3170
|
+
* consumers (the worker path serializes the prover and loses the callback).
|
|
2769
3171
|
* @returns {Promise<WebClient>} The fully initialized WebClient.
|
|
2770
3172
|
*/
|
|
2771
3173
|
static async createClientWithExternalKeystore(
|
|
@@ -2776,7 +3178,8 @@ class WebClient {
|
|
|
2776
3178
|
getKeyCb,
|
|
2777
3179
|
insertKeyCb,
|
|
2778
3180
|
signCb,
|
|
2779
|
-
logLevel
|
|
3181
|
+
logLevel,
|
|
3182
|
+
useWorker = true
|
|
2780
3183
|
) {
|
|
2781
3184
|
// Construct the instance (synchronously).
|
|
2782
3185
|
const instance = new WebClient(
|
|
@@ -2787,7 +3190,8 @@ class WebClient {
|
|
|
2787
3190
|
getKeyCb,
|
|
2788
3191
|
insertKeyCb,
|
|
2789
3192
|
signCb,
|
|
2790
|
-
logLevel
|
|
3193
|
+
logLevel,
|
|
3194
|
+
useWorker
|
|
2791
3195
|
);
|
|
2792
3196
|
|
|
2793
3197
|
// Set up logging on the main thread before creating the client.
|
|
@@ -2852,6 +3256,7 @@ class WebClient {
|
|
|
2852
3256
|
async newFaucet(
|
|
2853
3257
|
storageMode,
|
|
2854
3258
|
nonFungible,
|
|
3259
|
+
tokenName,
|
|
2855
3260
|
tokenSymbol,
|
|
2856
3261
|
decimals,
|
|
2857
3262
|
maxSupply,
|
|
@@ -2862,6 +3267,7 @@ class WebClient {
|
|
|
2862
3267
|
return await wasmWebClient.newFaucet(
|
|
2863
3268
|
storageMode,
|
|
2864
3269
|
nonFungible,
|
|
3270
|
+
tokenName,
|
|
2865
3271
|
tokenSymbol,
|
|
2866
3272
|
decimals,
|
|
2867
3273
|
maxSupply,
|