@miden-sdk/miden-sdk 0.13.2 → 0.14.0-alpha
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 +104 -43
- package/dist/{Cargo-e77f9a02.js → Cargo-D064yzd4.js} +7250 -7428
- package/dist/Cargo-D064yzd4.js.map +1 -0
- package/dist/api-types.d.ts +521 -0
- package/dist/assets/miden_client_web.wasm +0 -0
- package/dist/crates/miden_client_web.d.ts +3658 -3312
- package/dist/docs-entry.d.ts +36 -0
- package/dist/index.d.ts +27 -109
- package/dist/index.js +1302 -106
- package/dist/index.js.map +1 -1
- package/dist/wasm.js +1 -1
- package/dist/wasm.js.map +1 -1
- package/dist/workers/{Cargo-e77f9a02-e77f9a02.js → Cargo-D064yzd4-D064yzd4.js} +7250 -7428
- package/dist/workers/Cargo-D064yzd4-D064yzd4.js.map +1 -0
- package/dist/workers/assets/miden_client_web.wasm +0 -0
- package/dist/workers/web-client-methods-worker.js +43 -45
- package/dist/workers/web-client-methods-worker.js.map +1 -1
- package/package.json +15 -3
- package/dist/Cargo-e77f9a02.js.map +0 -1
- package/dist/workers/Cargo-e77f9a02-e77f9a02.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, AccountStorage, AccountStorageDelta, AccountStorageMode, AccountStorageRequirements,
|
|
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, 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, NoteSyncInfo, NoteTag, NoteType, OutputNote, OutputNoteArray, OutputNoteRecord, OutputNoteState, OutputNotes, OutputNotesArray, Package, PartialNote, ProcedureThreshold, Program, ProvenTransaction, PublicKey, RpcClient, Rpo256, SerializedInputNoteData, SerializedOutputNoteData, SerializedTransactionData, Signature, SigningInputs, SigningInputsType, SlotAndKeys, SparseMerklePath, StorageMap, StorageSlot, StorageSlotArray, SyncSummary, TestUtils, TokenSymbol, TransactionArgs, TransactionFilter, TransactionId, TransactionProver, TransactionRecord, TransactionRequest, TransactionRequestBuilder, TransactionResult, TransactionScript, TransactionScriptInputPair, TransactionScriptInputPairArray, TransactionStatus, TransactionStoreUpdate, TransactionSummary, WebClient, Word, createAuthFalcon512RpoMultisig, initSync, setupLogging } from './Cargo-D064yzd4.js';
|
|
3
3
|
|
|
4
4
|
const WorkerAction = Object.freeze({
|
|
5
5
|
INIT: "init",
|
|
@@ -16,8 +16,7 @@ const CallbackType = Object.freeze({
|
|
|
16
16
|
|
|
17
17
|
const MethodName = Object.freeze({
|
|
18
18
|
CREATE_CLIENT: "createClient",
|
|
19
|
-
|
|
20
|
-
NEW_FAUCET: "newFaucet",
|
|
19
|
+
APPLY_TRANSACTION: "applyTransaction",
|
|
21
20
|
EXECUTE_TRANSACTION: "executeTransaction",
|
|
22
21
|
PROVE_TRANSACTION: "proveTransaction",
|
|
23
22
|
SUBMIT_NEW_TRANSACTION: "submitNewTransaction",
|
|
@@ -239,13 +238,1210 @@ function releaseSyncLockWithError(dbId, error) {
|
|
|
239
238
|
}
|
|
240
239
|
}
|
|
241
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Shared utility functions for the MidenClient resource classes.
|
|
243
|
+
* Each function accepts a `wasm` parameter (the WASM module) for constructing typed objects.
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Resolves an AccountRef (string | Account | AccountId) to an AccountId.
|
|
248
|
+
*
|
|
249
|
+
* - Strings starting with `0x`/`0X` are parsed as hex via `AccountId.fromHex()`.
|
|
250
|
+
* - Other strings are parsed as bech32 via `AccountId.fromBech32()`.
|
|
251
|
+
* - Objects with an `.id()` method (Account) are resolved by calling `.id()`.
|
|
252
|
+
* - Otherwise, the value is assumed to be an AccountId pass-through.
|
|
253
|
+
*
|
|
254
|
+
* @param {string | Account | AccountId} ref - The account reference to resolve.
|
|
255
|
+
* @param {object} wasm - The WASM module.
|
|
256
|
+
* @returns {AccountId} The resolved AccountId.
|
|
257
|
+
*/
|
|
258
|
+
function resolveAccountRef(ref, wasm) {
|
|
259
|
+
if (ref == null) {
|
|
260
|
+
throw new Error("Account reference cannot be null or undefined");
|
|
261
|
+
}
|
|
262
|
+
if (typeof ref === "string") {
|
|
263
|
+
if (ref.startsWith("0x") || ref.startsWith("0X")) {
|
|
264
|
+
return wasm.AccountId.fromHex(ref);
|
|
265
|
+
}
|
|
266
|
+
return wasm.AccountId.fromBech32(ref);
|
|
267
|
+
}
|
|
268
|
+
if (ref && typeof ref.id === "function") {
|
|
269
|
+
return ref.id();
|
|
270
|
+
}
|
|
271
|
+
return ref;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Resolves an AccountRef to a WASM Address object.
|
|
276
|
+
*
|
|
277
|
+
* - Strings starting with bech32 prefixes (`m`) are parsed via `Address.fromBech32()`.
|
|
278
|
+
* - Strings starting with `0x`/`0X` are parsed as hex AccountId, then wrapped in Address.
|
|
279
|
+
* - Account objects are resolved via `.id()` then wrapped in Address.
|
|
280
|
+
* - AccountId objects are wrapped in Address directly.
|
|
281
|
+
*
|
|
282
|
+
* @param {string | Account | AccountId} ref - The account reference to resolve.
|
|
283
|
+
* @param {object} wasm - The WASM module.
|
|
284
|
+
* @returns {Address} The resolved Address.
|
|
285
|
+
*/
|
|
286
|
+
function resolveAddress(ref, wasm) {
|
|
287
|
+
if (ref == null) {
|
|
288
|
+
throw new Error("Address reference cannot be null or undefined");
|
|
289
|
+
}
|
|
290
|
+
if (typeof ref === "string") {
|
|
291
|
+
if (ref.startsWith("0x") || ref.startsWith("0X")) {
|
|
292
|
+
const accountId = wasm.AccountId.fromHex(ref);
|
|
293
|
+
return wasm.Address.fromAccountId(accountId, undefined);
|
|
294
|
+
}
|
|
295
|
+
return wasm.Address.fromBech32(ref);
|
|
296
|
+
}
|
|
297
|
+
if (ref && typeof ref.id === "function") {
|
|
298
|
+
const accountId = ref.id();
|
|
299
|
+
return wasm.Address.fromAccountId(accountId, undefined);
|
|
300
|
+
}
|
|
301
|
+
return wasm.Address.fromAccountId(ref, undefined);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Resolves a NoteVisibility string to a WASM NoteType value.
|
|
306
|
+
*
|
|
307
|
+
* @param {string | undefined} type - "public" or "private". Defaults to "public".
|
|
308
|
+
* @param {object} wasm - The WASM module.
|
|
309
|
+
* @returns {number} The NoteType enum value.
|
|
310
|
+
*/
|
|
311
|
+
function resolveNoteType(type, wasm) {
|
|
312
|
+
if (type === "private") {
|
|
313
|
+
return wasm.NoteType.Private;
|
|
314
|
+
}
|
|
315
|
+
if (type === "public" || type == null) {
|
|
316
|
+
return wasm.NoteType.Public;
|
|
317
|
+
}
|
|
318
|
+
throw new Error(
|
|
319
|
+
`Unknown note type: "${type}". Expected "public" or "private".`
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Resolves a storage mode string to a WASM AccountStorageMode instance.
|
|
325
|
+
*
|
|
326
|
+
* @param {string | undefined} mode - "private", "public", or "network". Defaults to "private".
|
|
327
|
+
* @param {object} wasm - The WASM module.
|
|
328
|
+
* @returns {AccountStorageMode} The storage mode instance.
|
|
329
|
+
*/
|
|
330
|
+
function resolveStorageMode(mode, wasm) {
|
|
331
|
+
switch (mode) {
|
|
332
|
+
case "public":
|
|
333
|
+
return wasm.AccountStorageMode.public();
|
|
334
|
+
case "network":
|
|
335
|
+
return wasm.AccountStorageMode.network();
|
|
336
|
+
case "private":
|
|
337
|
+
case undefined:
|
|
338
|
+
case null:
|
|
339
|
+
return wasm.AccountStorageMode.private();
|
|
340
|
+
default:
|
|
341
|
+
throw new Error(
|
|
342
|
+
`Unknown storage mode: "${mode}". Expected "private", "public", or "network".`
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Resolves an auth scheme string to a WASM AuthScheme enum value.
|
|
349
|
+
*
|
|
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.
|
|
353
|
+
*/
|
|
354
|
+
function resolveAuthScheme(scheme, wasm) {
|
|
355
|
+
if (scheme === "ecdsa") {
|
|
356
|
+
return wasm.AuthScheme.AuthEcdsaK256Keccak;
|
|
357
|
+
}
|
|
358
|
+
if (scheme === "falcon" || scheme == null) {
|
|
359
|
+
return wasm.AuthScheme.AuthRpoFalcon512;
|
|
360
|
+
}
|
|
361
|
+
throw new Error(
|
|
362
|
+
`Unknown auth scheme: "${scheme}". Expected "falcon" or "ecdsa".`
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Resolves a simplified AccountType string to a boolean `mutable` flag
|
|
368
|
+
* for the underlying WASM `newWallet()` / `importPublicAccountFromSeed()` calls.
|
|
369
|
+
*
|
|
370
|
+
* @param {string | undefined} accountType - "MutableWallet", "ImmutableWallet", or undefined.
|
|
371
|
+
* Defaults to mutable wallet when undefined.
|
|
372
|
+
* @returns {boolean} Whether the account code is mutable.
|
|
373
|
+
*/
|
|
374
|
+
function resolveAccountMutability(accountType) {
|
|
375
|
+
if (accountType == null || accountType === "MutableWallet") {
|
|
376
|
+
return true;
|
|
377
|
+
}
|
|
378
|
+
if (accountType === "ImmutableWallet") {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
throw new Error(
|
|
382
|
+
`Unknown wallet account type: "${accountType}". Expected "MutableWallet" or "ImmutableWallet".`
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Hashes a seed value. Strings are hashed via SHA-256 to produce a 32-byte Uint8Array.
|
|
388
|
+
* Uint8Array values are passed through unchanged.
|
|
389
|
+
*
|
|
390
|
+
* @param {string | Uint8Array} seed - The seed to hash.
|
|
391
|
+
* @returns {Promise<Uint8Array>} The hashed seed.
|
|
392
|
+
*/
|
|
393
|
+
async function hashSeed(seed) {
|
|
394
|
+
if (seed instanceof Uint8Array) {
|
|
395
|
+
return seed;
|
|
396
|
+
}
|
|
397
|
+
if (typeof seed === "string") {
|
|
398
|
+
const encoded = new TextEncoder().encode(seed);
|
|
399
|
+
const hash = await crypto.subtle.digest("SHA-256", encoded);
|
|
400
|
+
return new Uint8Array(hash);
|
|
401
|
+
}
|
|
402
|
+
throw new TypeError(
|
|
403
|
+
`Invalid seed type: expected string or Uint8Array, got ${typeof seed}`
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
class AccountsResource {
|
|
408
|
+
#inner;
|
|
409
|
+
#getWasm;
|
|
410
|
+
#client;
|
|
411
|
+
|
|
412
|
+
constructor(inner, getWasm, client) {
|
|
413
|
+
this.#inner = inner;
|
|
414
|
+
this.#getWasm = getWasm;
|
|
415
|
+
this.#client = client;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
async create(opts) {
|
|
419
|
+
this.#client.assertNotTerminated();
|
|
420
|
+
const wasm = await this.#getWasm();
|
|
421
|
+
|
|
422
|
+
if (opts?.type === "FungibleFaucet") {
|
|
423
|
+
const storageMode = resolveStorageMode(opts.storage ?? "public", wasm);
|
|
424
|
+
const authScheme = resolveAuthScheme(opts.auth, wasm);
|
|
425
|
+
return await this.#inner.newFaucet(
|
|
426
|
+
storageMode,
|
|
427
|
+
false,
|
|
428
|
+
opts.symbol,
|
|
429
|
+
opts.decimals,
|
|
430
|
+
BigInt(opts.maxSupply),
|
|
431
|
+
authScheme
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Default: wallet (mutable or immutable based on type)
|
|
436
|
+
const mutable = resolveAccountMutability(opts?.type);
|
|
437
|
+
const storageMode = resolveStorageMode(opts?.storage ?? "private", wasm);
|
|
438
|
+
const authScheme = resolveAuthScheme(opts?.auth, wasm);
|
|
439
|
+
const seed = opts?.seed ? await hashSeed(opts.seed) : undefined;
|
|
440
|
+
return await this.#inner.newWallet(storageMode, mutable, authScheme, seed);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
async get(ref) {
|
|
444
|
+
this.#client.assertNotTerminated();
|
|
445
|
+
const wasm = await this.#getWasm();
|
|
446
|
+
const id = resolveAccountRef(ref, wasm);
|
|
447
|
+
const account = await this.#inner.getAccount(id);
|
|
448
|
+
return account ?? null;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
async list() {
|
|
452
|
+
this.#client.assertNotTerminated();
|
|
453
|
+
return await this.#inner.getAccounts();
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async getDetails(ref) {
|
|
457
|
+
this.#client.assertNotTerminated();
|
|
458
|
+
const wasm = await this.#getWasm();
|
|
459
|
+
const id = resolveAccountRef(ref, wasm);
|
|
460
|
+
const account = await this.#inner.getAccount(id);
|
|
461
|
+
if (!account) {
|
|
462
|
+
throw new Error(`Account not found: ${id.toString()}`);
|
|
463
|
+
}
|
|
464
|
+
const keys = await this.#inner.getPublicKeyCommitmentsOfAccount(id);
|
|
465
|
+
return {
|
|
466
|
+
account,
|
|
467
|
+
vault: account.vault(),
|
|
468
|
+
storage: account.storage(),
|
|
469
|
+
code: account.code() ?? null,
|
|
470
|
+
keys,
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
async getBalance(accountRef, tokenRef) {
|
|
475
|
+
this.#client.assertNotTerminated();
|
|
476
|
+
const wasm = await this.#getWasm();
|
|
477
|
+
const accountId = resolveAccountRef(accountRef, wasm);
|
|
478
|
+
const faucetId = resolveAccountRef(tokenRef, wasm);
|
|
479
|
+
const reader = this.#inner.accountReader(accountId);
|
|
480
|
+
return await reader.getBalance(faucetId);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
async import(input) {
|
|
484
|
+
this.#client.assertNotTerminated();
|
|
485
|
+
const wasm = await this.#getWasm();
|
|
486
|
+
|
|
487
|
+
if (typeof input === "string") {
|
|
488
|
+
// Import by ID (hex or bech32 string)
|
|
489
|
+
const id = resolveAccountRef(input, wasm);
|
|
490
|
+
await this.#inner.importAccountById(id);
|
|
491
|
+
return await this.#inner.getAccount(id);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (input.file) {
|
|
495
|
+
// Extract accountId before importAccountFile — WASM consumes the
|
|
496
|
+
// AccountFile by value, invalidating the JS wrapper after the call.
|
|
497
|
+
const accountId =
|
|
498
|
+
typeof input.file.accountId === "function"
|
|
499
|
+
? input.file.accountId()
|
|
500
|
+
: null;
|
|
501
|
+
await this.#inner.importAccountFile(input.file);
|
|
502
|
+
if (accountId) {
|
|
503
|
+
return await this.#inner.getAccount(accountId);
|
|
504
|
+
}
|
|
505
|
+
throw new Error(
|
|
506
|
+
"Could not determine account ID from AccountFile. " +
|
|
507
|
+
"Ensure the file contains a valid account."
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
if (input.seed) {
|
|
512
|
+
// Import public account from seed
|
|
513
|
+
const authScheme = resolveAuthScheme(input.auth, wasm);
|
|
514
|
+
const mutable = resolveAccountMutability(input.type);
|
|
515
|
+
return await this.#inner.importPublicAccountFromSeed(
|
|
516
|
+
input.seed,
|
|
517
|
+
mutable,
|
|
518
|
+
authScheme
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
throw new Error(
|
|
523
|
+
"Invalid import input: expected a string, { file }, or { seed }"
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
async export(ref) {
|
|
528
|
+
this.#client.assertNotTerminated();
|
|
529
|
+
const wasm = await this.#getWasm();
|
|
530
|
+
const id = resolveAccountRef(ref, wasm);
|
|
531
|
+
return await this.#inner.exportAccountFile(id);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
async addAddress(ref, addr) {
|
|
535
|
+
this.#client.assertNotTerminated();
|
|
536
|
+
const wasm = await this.#getWasm();
|
|
537
|
+
const id = resolveAccountRef(ref, wasm);
|
|
538
|
+
const address = wasm.Address.fromBech32(addr);
|
|
539
|
+
await this.#inner.insertAccountAddress(id, address);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
async removeAddress(ref, addr) {
|
|
543
|
+
this.#client.assertNotTerminated();
|
|
544
|
+
const wasm = await this.#getWasm();
|
|
545
|
+
const id = resolveAccountRef(ref, wasm);
|
|
546
|
+
const address = wasm.Address.fromBech32(addr);
|
|
547
|
+
await this.#inner.removeAccountAddress(id, address);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
class TransactionsResource {
|
|
552
|
+
#inner;
|
|
553
|
+
#getWasm;
|
|
554
|
+
#client;
|
|
555
|
+
|
|
556
|
+
constructor(inner, getWasm, client) {
|
|
557
|
+
this.#inner = inner;
|
|
558
|
+
this.#getWasm = getWasm;
|
|
559
|
+
this.#client = client;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
async send(opts) {
|
|
563
|
+
this.#client.assertNotTerminated();
|
|
564
|
+
const wasm = await this.#getWasm();
|
|
565
|
+
const { accountId, request } = await this.#buildSendRequest(opts, wasm);
|
|
566
|
+
|
|
567
|
+
const txId = await this.#submitOrSubmitWithProver(
|
|
568
|
+
accountId,
|
|
569
|
+
request,
|
|
570
|
+
opts.prover
|
|
571
|
+
);
|
|
572
|
+
|
|
573
|
+
if (opts.waitForConfirmation) {
|
|
574
|
+
await this.waitFor(txId.toHex(), { timeout: opts.timeout });
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
return txId;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
async mint(opts) {
|
|
581
|
+
this.#client.assertNotTerminated();
|
|
582
|
+
const wasm = await this.#getWasm();
|
|
583
|
+
const { accountId, request } = await this.#buildMintRequest(opts, wasm);
|
|
584
|
+
|
|
585
|
+
const txId = await this.#submitOrSubmitWithProver(
|
|
586
|
+
accountId,
|
|
587
|
+
request,
|
|
588
|
+
opts.prover
|
|
589
|
+
);
|
|
590
|
+
|
|
591
|
+
if (opts.waitForConfirmation) {
|
|
592
|
+
await this.waitFor(txId.toHex(), { timeout: opts.timeout });
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return txId;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
async consume(opts) {
|
|
599
|
+
this.#client.assertNotTerminated();
|
|
600
|
+
const wasm = await this.#getWasm();
|
|
601
|
+
const { accountId, request } = await this.#buildConsumeRequest(opts, wasm);
|
|
602
|
+
|
|
603
|
+
const txId = await this.#submitOrSubmitWithProver(
|
|
604
|
+
accountId,
|
|
605
|
+
request,
|
|
606
|
+
opts.prover
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
if (opts.waitForConfirmation) {
|
|
610
|
+
await this.waitFor(txId.toHex(), { timeout: opts.timeout });
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return txId;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
async consumeAll(opts) {
|
|
617
|
+
this.#client.assertNotTerminated();
|
|
618
|
+
const wasm = await this.#getWasm();
|
|
619
|
+
|
|
620
|
+
// getConsumableNotes takes AccountId by value (consumed by WASM).
|
|
621
|
+
// Save hex so we can reconstruct for submitNewTransaction.
|
|
622
|
+
const accountId = resolveAccountRef(opts.account, wasm);
|
|
623
|
+
const accountIdHex = accountId.toString();
|
|
624
|
+
const consumable = await this.#inner.getConsumableNotes(accountId);
|
|
625
|
+
|
|
626
|
+
if (!consumable || consumable.length === 0) {
|
|
627
|
+
return { txId: null, consumed: 0, remaining: 0 };
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
const total = consumable.length;
|
|
631
|
+
const toConsume =
|
|
632
|
+
opts.maxNotes != null ? consumable.slice(0, opts.maxNotes) : consumable;
|
|
633
|
+
|
|
634
|
+
if (toConsume.length === 0) {
|
|
635
|
+
return { txId: null, consumed: 0, remaining: total };
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const notes = toConsume.map((c) => c.inputNoteRecord().toNote());
|
|
639
|
+
|
|
640
|
+
const request = await this.#inner.newConsumeTransactionRequest(notes);
|
|
641
|
+
|
|
642
|
+
const txId = await this.#submitOrSubmitWithProver(
|
|
643
|
+
wasm.AccountId.fromHex(accountIdHex),
|
|
644
|
+
request,
|
|
645
|
+
opts.prover
|
|
646
|
+
);
|
|
647
|
+
|
|
648
|
+
if (opts.waitForConfirmation) {
|
|
649
|
+
await this.waitFor(txId.toHex(), { timeout: opts.timeout });
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
return {
|
|
653
|
+
txId,
|
|
654
|
+
consumed: toConsume.length,
|
|
655
|
+
remaining: total - toConsume.length,
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
async swap(opts) {
|
|
660
|
+
this.#client.assertNotTerminated();
|
|
661
|
+
const wasm = await this.#getWasm();
|
|
662
|
+
const { accountId, request } = await this.#buildSwapRequest(opts, wasm);
|
|
663
|
+
|
|
664
|
+
const txId = await this.#submitOrSubmitWithProver(
|
|
665
|
+
accountId,
|
|
666
|
+
request,
|
|
667
|
+
opts.prover
|
|
668
|
+
);
|
|
669
|
+
|
|
670
|
+
if (opts.waitForConfirmation) {
|
|
671
|
+
await this.waitFor(txId.toHex(), { timeout: opts.timeout });
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
return txId;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
async preview(opts) {
|
|
678
|
+
this.#client.assertNotTerminated();
|
|
679
|
+
const wasm = await this.#getWasm();
|
|
680
|
+
|
|
681
|
+
let accountId;
|
|
682
|
+
let request;
|
|
683
|
+
|
|
684
|
+
switch (opts.operation) {
|
|
685
|
+
case "send": {
|
|
686
|
+
({ accountId, request } = await this.#buildSendRequest(opts, wasm));
|
|
687
|
+
break;
|
|
688
|
+
}
|
|
689
|
+
case "mint": {
|
|
690
|
+
({ accountId, request } = await this.#buildMintRequest(opts, wasm));
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
case "consume": {
|
|
694
|
+
({ accountId, request } = await this.#buildConsumeRequest(opts, wasm));
|
|
695
|
+
break;
|
|
696
|
+
}
|
|
697
|
+
case "swap": {
|
|
698
|
+
({ accountId, request } = await this.#buildSwapRequest(opts, wasm));
|
|
699
|
+
break;
|
|
700
|
+
}
|
|
701
|
+
default:
|
|
702
|
+
throw new Error(`Unknown preview operation: ${opts.operation}`);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
return await this.#inner.executeForSummary(accountId, request);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
async submit(account, request, opts) {
|
|
709
|
+
this.#client.assertNotTerminated();
|
|
710
|
+
const wasm = await this.#getWasm();
|
|
711
|
+
const accountId = resolveAccountRef(account, wasm);
|
|
712
|
+
return await this.#submitOrSubmitWithProver(
|
|
713
|
+
accountId,
|
|
714
|
+
request,
|
|
715
|
+
opts?.prover
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
async list(query) {
|
|
720
|
+
this.#client.assertNotTerminated();
|
|
721
|
+
const wasm = await this.#getWasm();
|
|
722
|
+
|
|
723
|
+
let filter;
|
|
724
|
+
if (!query) {
|
|
725
|
+
filter = wasm.TransactionFilter.all();
|
|
726
|
+
} else if (query.status === "uncommitted") {
|
|
727
|
+
filter = wasm.TransactionFilter.uncommitted();
|
|
728
|
+
} else if (query.ids) {
|
|
729
|
+
const txIds = query.ids.map((id) => wasm.TransactionId.fromHex(id));
|
|
730
|
+
filter = wasm.TransactionFilter.ids(txIds);
|
|
731
|
+
} else if (query.expiredBefore !== undefined) {
|
|
732
|
+
filter = wasm.TransactionFilter.expiredBefore(query.expiredBefore);
|
|
733
|
+
} else {
|
|
734
|
+
filter = wasm.TransactionFilter.all();
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
return await this.#inner.getTransactions(filter);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Polls for transaction confirmation.
|
|
742
|
+
*
|
|
743
|
+
* @param {string} txId - Transaction ID hex string.
|
|
744
|
+
* @param {WaitOptions} [opts] - Polling options.
|
|
745
|
+
* @param {number} [opts.timeout=60000] - Wall-clock polling timeout in
|
|
746
|
+
* milliseconds. This is NOT a block height — it controls how long the
|
|
747
|
+
* client waits before giving up. Set to 0 to disable the timeout and poll
|
|
748
|
+
* indefinitely until the transaction is committed or discarded.
|
|
749
|
+
* @param {number} [opts.interval=5000] - Polling interval in ms.
|
|
750
|
+
* @param {function} [opts.onProgress] - Called with the current status on
|
|
751
|
+
* each poll iteration ("pending", "submitted", or "committed").
|
|
752
|
+
*/
|
|
753
|
+
async waitFor(txId, opts) {
|
|
754
|
+
this.#client.assertNotTerminated();
|
|
755
|
+
const timeout = opts?.timeout ?? 60_000;
|
|
756
|
+
const interval = opts?.interval ?? 5_000;
|
|
757
|
+
const start = Date.now();
|
|
758
|
+
|
|
759
|
+
const wasm = await this.#getWasm();
|
|
760
|
+
|
|
761
|
+
while (true) {
|
|
762
|
+
const elapsed = Date.now() - start;
|
|
763
|
+
if (timeout > 0 && elapsed >= timeout) {
|
|
764
|
+
throw new Error(
|
|
765
|
+
`Transaction confirmation timed out after ${timeout}ms`
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
try {
|
|
770
|
+
await this.#inner.syncStateWithTimeout(0);
|
|
771
|
+
} catch {
|
|
772
|
+
// Sync may fail transiently; continue polling
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// Recreate filter each iteration — WASM consumes it by value
|
|
776
|
+
const filter = wasm.TransactionFilter.ids([
|
|
777
|
+
wasm.TransactionId.fromHex(txId),
|
|
778
|
+
]);
|
|
779
|
+
const txs = await this.#inner.getTransactions(filter);
|
|
780
|
+
|
|
781
|
+
if (txs && txs.length > 0) {
|
|
782
|
+
const tx = txs[0];
|
|
783
|
+
const status = tx.transactionStatus?.();
|
|
784
|
+
|
|
785
|
+
if (status) {
|
|
786
|
+
if (status.isCommitted()) {
|
|
787
|
+
opts?.onProgress?.("committed");
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
if (status.isDiscarded()) {
|
|
791
|
+
throw new Error(`Transaction rejected: ${txId}`);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
opts?.onProgress?.("submitted");
|
|
796
|
+
} else {
|
|
797
|
+
opts?.onProgress?.("pending");
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// ── Shared request builders ──
|
|
805
|
+
|
|
806
|
+
async #buildSendRequest(opts, wasm) {
|
|
807
|
+
const accountId = resolveAccountRef(opts.account, wasm);
|
|
808
|
+
const targetId = resolveAccountRef(opts.to, wasm);
|
|
809
|
+
const faucetId = resolveAccountRef(opts.token, wasm);
|
|
810
|
+
const noteType = resolveNoteType(opts.type, wasm);
|
|
811
|
+
const amount = BigInt(opts.amount);
|
|
812
|
+
|
|
813
|
+
const request = await this.#inner.newSendTransactionRequest(
|
|
814
|
+
accountId,
|
|
815
|
+
targetId,
|
|
816
|
+
faucetId,
|
|
817
|
+
noteType,
|
|
818
|
+
amount,
|
|
819
|
+
opts.reclaimAfter,
|
|
820
|
+
opts.timelockUntil
|
|
821
|
+
);
|
|
822
|
+
return { accountId, request };
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
async #buildMintRequest(opts, wasm) {
|
|
826
|
+
const accountId = resolveAccountRef(opts.account, wasm);
|
|
827
|
+
const targetId = resolveAccountRef(opts.to, wasm);
|
|
828
|
+
const noteType = resolveNoteType(opts.type, wasm);
|
|
829
|
+
const amount = BigInt(opts.amount);
|
|
830
|
+
|
|
831
|
+
// WASM signature: newMintTransactionRequest(target, faucet, noteType, amount)
|
|
832
|
+
const request = await this.#inner.newMintTransactionRequest(
|
|
833
|
+
targetId,
|
|
834
|
+
accountId,
|
|
835
|
+
noteType,
|
|
836
|
+
amount
|
|
837
|
+
);
|
|
838
|
+
return { accountId, request };
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
async #buildConsumeRequest(opts, wasm) {
|
|
842
|
+
const accountId = resolveAccountRef(opts.account, wasm);
|
|
843
|
+
const noteInputs = Array.isArray(opts.notes) ? opts.notes : [opts.notes];
|
|
844
|
+
const notes = await Promise.all(
|
|
845
|
+
noteInputs.map((input) => this.#resolveNoteInput(input))
|
|
846
|
+
);
|
|
847
|
+
const request = await this.#inner.newConsumeTransactionRequest(notes);
|
|
848
|
+
return { accountId, request };
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
async #buildSwapRequest(opts, wasm) {
|
|
852
|
+
const accountId = resolveAccountRef(opts.account, wasm);
|
|
853
|
+
const offeredFaucetId = resolveAccountRef(opts.offer.token, wasm);
|
|
854
|
+
const requestedFaucetId = resolveAccountRef(opts.request.token, wasm);
|
|
855
|
+
const noteType = resolveNoteType(opts.type, wasm);
|
|
856
|
+
const paybackNoteType = resolveNoteType(
|
|
857
|
+
opts.paybackType ?? opts.type,
|
|
858
|
+
wasm
|
|
859
|
+
);
|
|
860
|
+
|
|
861
|
+
const request = await this.#inner.newSwapTransactionRequest(
|
|
862
|
+
accountId,
|
|
863
|
+
offeredFaucetId,
|
|
864
|
+
BigInt(opts.offer.amount),
|
|
865
|
+
requestedFaucetId,
|
|
866
|
+
BigInt(opts.request.amount),
|
|
867
|
+
noteType,
|
|
868
|
+
paybackNoteType
|
|
869
|
+
);
|
|
870
|
+
return { accountId, request };
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
async #resolveNoteInput(input) {
|
|
874
|
+
if (typeof input === "string") {
|
|
875
|
+
const record = await this.#inner.getInputNote(input);
|
|
876
|
+
if (!record) {
|
|
877
|
+
throw new Error(`Note not found: ${input}`);
|
|
878
|
+
}
|
|
879
|
+
return record.toNote();
|
|
880
|
+
}
|
|
881
|
+
// InputNoteRecord — unwrap to Note
|
|
882
|
+
if (input && typeof input.toNote === "function") {
|
|
883
|
+
return input.toNote();
|
|
884
|
+
}
|
|
885
|
+
// NoteId — look up the note by its hex ID
|
|
886
|
+
if (input && input.constructor?.name === "NoteId") {
|
|
887
|
+
const hex = input.toString();
|
|
888
|
+
const record = await this.#inner.getInputNote(hex);
|
|
889
|
+
if (!record) {
|
|
890
|
+
throw new Error(`Note not found: ${hex}`);
|
|
891
|
+
}
|
|
892
|
+
return record.toNote();
|
|
893
|
+
}
|
|
894
|
+
// Assume it's already a Note object
|
|
895
|
+
return input;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
async #submitOrSubmitWithProver(accountId, request, perCallProver) {
|
|
899
|
+
const prover = perCallProver ?? this.#client.defaultProver;
|
|
900
|
+
if (prover) {
|
|
901
|
+
return await this.#inner.submitNewTransactionWithProver(
|
|
902
|
+
accountId,
|
|
903
|
+
request,
|
|
904
|
+
prover
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
return await this.#inner.submitNewTransaction(accountId, request);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
class NotesResource {
|
|
912
|
+
#inner;
|
|
913
|
+
#getWasm;
|
|
914
|
+
#client;
|
|
915
|
+
|
|
916
|
+
constructor(inner, getWasm, client) {
|
|
917
|
+
this.#inner = inner;
|
|
918
|
+
this.#getWasm = getWasm;
|
|
919
|
+
this.#client = client;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
async list(query) {
|
|
923
|
+
this.#client.assertNotTerminated();
|
|
924
|
+
const wasm = await this.#getWasm();
|
|
925
|
+
const filter = buildNoteFilter(query, wasm);
|
|
926
|
+
return await this.#inner.getInputNotes(filter);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
async get(noteId) {
|
|
930
|
+
this.#client.assertNotTerminated();
|
|
931
|
+
const result = await this.#inner.getInputNote(noteId);
|
|
932
|
+
return result ?? null;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
async listSent(query) {
|
|
936
|
+
this.#client.assertNotTerminated();
|
|
937
|
+
const wasm = await this.#getWasm();
|
|
938
|
+
const filter = buildNoteFilter(query, wasm);
|
|
939
|
+
return await this.#inner.getOutputNotes(filter);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
async listAvailable(opts) {
|
|
943
|
+
this.#client.assertNotTerminated();
|
|
944
|
+
const wasm = await this.#getWasm();
|
|
945
|
+
const accountId = resolveAccountRef(opts.account, wasm);
|
|
946
|
+
return await this.#inner.getConsumableNotes(accountId);
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
async import(noteFile) {
|
|
950
|
+
this.#client.assertNotTerminated();
|
|
951
|
+
return await this.#inner.importNoteFile(noteFile);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
async export(noteId, opts) {
|
|
955
|
+
this.#client.assertNotTerminated();
|
|
956
|
+
const wasm = await this.#getWasm();
|
|
957
|
+
const format = opts?.format ?? wasm.NoteExportFormat.Full;
|
|
958
|
+
return await this.#inner.exportNoteFile(noteId, format);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
async fetchPrivate(opts) {
|
|
962
|
+
this.#client.assertNotTerminated();
|
|
963
|
+
if (opts?.mode === "all") {
|
|
964
|
+
await this.#inner.fetchAllPrivateNotes();
|
|
965
|
+
} else {
|
|
966
|
+
await this.#inner.fetchPrivateNotes();
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
async sendPrivate(opts) {
|
|
971
|
+
this.#client.assertNotTerminated();
|
|
972
|
+
const wasm = await this.#getWasm();
|
|
973
|
+
const noteRecord = await this.#inner.getInputNote(opts.noteId);
|
|
974
|
+
if (!noteRecord) {
|
|
975
|
+
throw new Error(`Note not found: ${opts.noteId}`);
|
|
976
|
+
}
|
|
977
|
+
const note = noteRecord.toNote();
|
|
978
|
+
const address = resolveAddress(opts.to, wasm);
|
|
979
|
+
await this.#inner.sendPrivateNote(note, address);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
function buildNoteFilter(query, wasm) {
|
|
984
|
+
if (!query) {
|
|
985
|
+
return new wasm.NoteFilter(wasm.NoteFilterTypes.All, undefined);
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
if (query.ids) {
|
|
989
|
+
const noteIds = query.ids.map((id) => wasm.NoteId.fromHex(id));
|
|
990
|
+
return new wasm.NoteFilter(wasm.NoteFilterTypes.List, noteIds);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
if (query.status) {
|
|
994
|
+
const statusMap = {
|
|
995
|
+
consumed: wasm.NoteFilterTypes.Consumed,
|
|
996
|
+
committed: wasm.NoteFilterTypes.Committed,
|
|
997
|
+
expected: wasm.NoteFilterTypes.Expected,
|
|
998
|
+
processing: wasm.NoteFilterTypes.Processing,
|
|
999
|
+
unverified: wasm.NoteFilterTypes.Unverified,
|
|
1000
|
+
};
|
|
1001
|
+
const filterType = statusMap[query.status];
|
|
1002
|
+
if (filterType === undefined) {
|
|
1003
|
+
throw new Error(`Unknown note status: ${query.status}`);
|
|
1004
|
+
}
|
|
1005
|
+
return new wasm.NoteFilter(filterType, undefined);
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
return new wasm.NoteFilter(wasm.NoteFilterTypes.All, undefined);
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
class TagsResource {
|
|
1012
|
+
#inner;
|
|
1013
|
+
#client;
|
|
1014
|
+
|
|
1015
|
+
constructor(inner, getWasm, client) {
|
|
1016
|
+
this.#inner = inner;
|
|
1017
|
+
this.#client = client;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
async add(tag) {
|
|
1021
|
+
this.#client.assertNotTerminated();
|
|
1022
|
+
await this.#inner.addTag(String(tag));
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
async remove(tag) {
|
|
1026
|
+
this.#client.assertNotTerminated();
|
|
1027
|
+
await this.#inner.removeTag(String(tag));
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
async list() {
|
|
1031
|
+
this.#client.assertNotTerminated();
|
|
1032
|
+
const tags = await this.#inner.listTags();
|
|
1033
|
+
return Array.from(tags).map((t) => {
|
|
1034
|
+
const n = Number(t);
|
|
1035
|
+
if (Number.isNaN(n)) {
|
|
1036
|
+
throw new Error(`Invalid tag value: ${t}`);
|
|
1037
|
+
}
|
|
1038
|
+
return n;
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
class SettingsResource {
|
|
1044
|
+
#inner;
|
|
1045
|
+
#client;
|
|
1046
|
+
|
|
1047
|
+
constructor(inner, _getWasm, client) {
|
|
1048
|
+
this.#inner = inner;
|
|
1049
|
+
this.#client = client;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
async get(key) {
|
|
1053
|
+
this.#client.assertNotTerminated();
|
|
1054
|
+
const value = await this.#inner.getSetting(key);
|
|
1055
|
+
return value === undefined ? null : value;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
async set(key, value) {
|
|
1059
|
+
this.#client.assertNotTerminated();
|
|
1060
|
+
await this.#inner.setSetting(key, value);
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
async remove(key) {
|
|
1064
|
+
this.#client.assertNotTerminated();
|
|
1065
|
+
await this.#inner.removeSetting(key);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
async listKeys() {
|
|
1069
|
+
this.#client.assertNotTerminated();
|
|
1070
|
+
return await this.#inner.listSettingKeys();
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
/**
|
|
1075
|
+
* MidenClient wraps the existing proxy-wrapped WebClient with a resource-based API.
|
|
1076
|
+
*
|
|
1077
|
+
* Resource classes receive the proxy client and call its methods, handling all type
|
|
1078
|
+
* conversions (string -> AccountId, number -> BigInt, string -> enum).
|
|
1079
|
+
*/
|
|
1080
|
+
class MidenClient {
|
|
1081
|
+
// Injected by index.js to resolve circular imports
|
|
1082
|
+
static _WasmWebClient = null;
|
|
1083
|
+
static _MockWasmWebClient = null;
|
|
1084
|
+
static _getWasmOrThrow = null;
|
|
1085
|
+
|
|
1086
|
+
#inner;
|
|
1087
|
+
#getWasm;
|
|
1088
|
+
#terminated = false;
|
|
1089
|
+
#defaultProver = null;
|
|
1090
|
+
#isMock = false;
|
|
1091
|
+
|
|
1092
|
+
constructor(inner, getWasm, defaultProver) {
|
|
1093
|
+
this.#inner = inner;
|
|
1094
|
+
this.#getWasm = getWasm;
|
|
1095
|
+
this.#defaultProver = defaultProver ?? null;
|
|
1096
|
+
|
|
1097
|
+
this.accounts = new AccountsResource(inner, getWasm, this);
|
|
1098
|
+
this.transactions = new TransactionsResource(inner, getWasm, this);
|
|
1099
|
+
this.notes = new NotesResource(inner, getWasm, this);
|
|
1100
|
+
this.tags = new TagsResource(inner, getWasm, this);
|
|
1101
|
+
this.settings = new SettingsResource(inner, getWasm, this);
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Creates and initializes a new MidenClient.
|
|
1106
|
+
*
|
|
1107
|
+
* @param {ClientOptions} [options] - Client configuration options.
|
|
1108
|
+
* @returns {Promise<MidenClient>} A fully initialized client.
|
|
1109
|
+
*/
|
|
1110
|
+
static async create(options) {
|
|
1111
|
+
const getWasm = MidenClient._getWasmOrThrow;
|
|
1112
|
+
const WebClientClass = MidenClient._WasmWebClient;
|
|
1113
|
+
|
|
1114
|
+
if (!WebClientClass || !getWasm) {
|
|
1115
|
+
throw new Error(
|
|
1116
|
+
"MidenClient not initialized. Import from the SDK package entry point."
|
|
1117
|
+
);
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
const seed = options?.seed ? await hashSeed(options.seed) : undefined;
|
|
1121
|
+
|
|
1122
|
+
let inner;
|
|
1123
|
+
if (options?.keystore) {
|
|
1124
|
+
inner = await WebClientClass.createClientWithExternalKeystore(
|
|
1125
|
+
options?.rpcUrl,
|
|
1126
|
+
options?.noteTransportUrl,
|
|
1127
|
+
seed,
|
|
1128
|
+
options?.storeName,
|
|
1129
|
+
options.keystore.getKey,
|
|
1130
|
+
options.keystore.insertKey,
|
|
1131
|
+
options.keystore.sign
|
|
1132
|
+
);
|
|
1133
|
+
} else {
|
|
1134
|
+
inner = await WebClientClass.createClient(
|
|
1135
|
+
options?.rpcUrl,
|
|
1136
|
+
options?.noteTransportUrl,
|
|
1137
|
+
seed,
|
|
1138
|
+
options?.storeName
|
|
1139
|
+
);
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
let defaultProver = null;
|
|
1143
|
+
if (options?.proverUrl) {
|
|
1144
|
+
const wasm = await getWasm();
|
|
1145
|
+
defaultProver = wasm.TransactionProver.newRemoteProver(
|
|
1146
|
+
options.proverUrl,
|
|
1147
|
+
undefined
|
|
1148
|
+
);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
const client = new MidenClient(inner, getWasm, defaultProver);
|
|
1152
|
+
|
|
1153
|
+
if (options?.autoSync) {
|
|
1154
|
+
await client.sync();
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
return client;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/**
|
|
1161
|
+
* Creates a client preconfigured for testnet use.
|
|
1162
|
+
* Defaults to autoSync: true.
|
|
1163
|
+
*
|
|
1164
|
+
* @param {object} [options] - Options (autoSync can be overridden).
|
|
1165
|
+
* @returns {Promise<MidenClient>} A fully initialized testnet client.
|
|
1166
|
+
*/
|
|
1167
|
+
static async createTestnet(options) {
|
|
1168
|
+
return MidenClient.create({
|
|
1169
|
+
...options,
|
|
1170
|
+
autoSync: options?.autoSync ?? true,
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* Creates a mock client for testing.
|
|
1176
|
+
*
|
|
1177
|
+
* @param {MockOptions} [options] - Mock client options.
|
|
1178
|
+
* @returns {Promise<MidenClient>} A mock client.
|
|
1179
|
+
*/
|
|
1180
|
+
static async createMock(options) {
|
|
1181
|
+
const getWasm = MidenClient._getWasmOrThrow;
|
|
1182
|
+
const MockWebClientClass = MidenClient._MockWasmWebClient;
|
|
1183
|
+
|
|
1184
|
+
if (!MockWebClientClass || !getWasm) {
|
|
1185
|
+
throw new Error(
|
|
1186
|
+
"MidenClient not initialized. Import from the SDK package entry point."
|
|
1187
|
+
);
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
const seed = options?.seed ? await hashSeed(options.seed) : undefined;
|
|
1191
|
+
|
|
1192
|
+
const inner = await MockWebClientClass.createClient(
|
|
1193
|
+
options?.serializedMockChain,
|
|
1194
|
+
options?.serializedNoteTransport,
|
|
1195
|
+
seed
|
|
1196
|
+
);
|
|
1197
|
+
|
|
1198
|
+
const client = new MidenClient(inner, getWasm, null);
|
|
1199
|
+
client.#isMock = true;
|
|
1200
|
+
return client;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
/** Returns the client-level default prover (set from ClientOptions.proverUrl). */
|
|
1204
|
+
get defaultProver() {
|
|
1205
|
+
return this.#defaultProver;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Syncs the client state with the Miden node.
|
|
1210
|
+
*
|
|
1211
|
+
* @param {object} [opts] - Sync options.
|
|
1212
|
+
* @param {number} [opts.timeout] - Timeout in milliseconds (0 = no timeout).
|
|
1213
|
+
* @returns {Promise<SyncSummary>} The sync summary.
|
|
1214
|
+
*/
|
|
1215
|
+
async sync(opts) {
|
|
1216
|
+
this.assertNotTerminated();
|
|
1217
|
+
return await this.#inner.syncStateWithTimeout(opts?.timeout ?? 0);
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
/**
|
|
1221
|
+
* Returns the current sync height.
|
|
1222
|
+
*
|
|
1223
|
+
* @returns {Promise<number>} The current sync height.
|
|
1224
|
+
*/
|
|
1225
|
+
async getSyncHeight() {
|
|
1226
|
+
this.assertNotTerminated();
|
|
1227
|
+
return await this.#inner.getSyncHeight();
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
/**
|
|
1231
|
+
* Terminates the underlying Web Worker. After this, all method calls will throw.
|
|
1232
|
+
*/
|
|
1233
|
+
terminate() {
|
|
1234
|
+
this.#terminated = true;
|
|
1235
|
+
this.#inner.terminate?.();
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
[Symbol.dispose]() {
|
|
1239
|
+
this.terminate();
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
async [Symbol.asyncDispose]() {
|
|
1243
|
+
this.terminate();
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
/**
|
|
1247
|
+
* Exports the client store as a versioned snapshot.
|
|
1248
|
+
*
|
|
1249
|
+
* @returns {Promise<StoreSnapshot>} The store snapshot.
|
|
1250
|
+
*/
|
|
1251
|
+
async exportStore() {
|
|
1252
|
+
this.assertNotTerminated();
|
|
1253
|
+
const data = await this.#inner.exportStore();
|
|
1254
|
+
return { version: 1, data };
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
/**
|
|
1258
|
+
* Imports a previously exported store snapshot.
|
|
1259
|
+
*
|
|
1260
|
+
* @param {StoreSnapshot} snapshot - The store snapshot to import.
|
|
1261
|
+
*/
|
|
1262
|
+
async importStore(snapshot) {
|
|
1263
|
+
this.assertNotTerminated();
|
|
1264
|
+
if (!snapshot || snapshot.version !== 1) {
|
|
1265
|
+
throw new Error(
|
|
1266
|
+
`Unsupported store snapshot version: ${snapshot?.version}. Expected version 1.`
|
|
1267
|
+
);
|
|
1268
|
+
}
|
|
1269
|
+
// Second arg is the store password (empty string = no encryption)
|
|
1270
|
+
await this.#inner.forceImportStore(snapshot.data, "");
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
// ── Mock-only methods ──
|
|
1274
|
+
|
|
1275
|
+
/** Advances the mock chain by one block. Only available on mock clients. */
|
|
1276
|
+
proveBlock() {
|
|
1277
|
+
this.assertNotTerminated();
|
|
1278
|
+
this.#assertMock("proveBlock");
|
|
1279
|
+
return this.#inner.proveBlock();
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
/** Returns true if this client uses a mock chain. */
|
|
1283
|
+
usesMockChain() {
|
|
1284
|
+
return this.#isMock;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
/** Serializes the mock chain state for snapshot/restore in tests. */
|
|
1288
|
+
serializeMockChain() {
|
|
1289
|
+
this.assertNotTerminated();
|
|
1290
|
+
this.#assertMock("serializeMockChain");
|
|
1291
|
+
return this.#inner.serializeMockChain();
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
/** Serializes the mock note transport node state. */
|
|
1295
|
+
serializeMockNoteTransportNode() {
|
|
1296
|
+
this.assertNotTerminated();
|
|
1297
|
+
this.#assertMock("serializeMockNoteTransportNode");
|
|
1298
|
+
return this.#inner.serializeMockNoteTransportNode();
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// ── Internal ──
|
|
1302
|
+
|
|
1303
|
+
/** @internal Throws if the client has been terminated. */
|
|
1304
|
+
assertNotTerminated() {
|
|
1305
|
+
if (this.#terminated) {
|
|
1306
|
+
throw new Error("Client terminated");
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
#assertMock(method) {
|
|
1311
|
+
if (!this.#isMock) {
|
|
1312
|
+
throw new Error(`${method}() is only available on mock clients`);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
// Module-level WASM reference, set by index.js after initialization
|
|
1318
|
+
let _wasm = null;
|
|
1319
|
+
let _WebClient = null;
|
|
1320
|
+
|
|
1321
|
+
function _setWasm(wasm) {
|
|
1322
|
+
_wasm = wasm;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
function _setWebClient(WebClientClass) {
|
|
1326
|
+
_WebClient = WebClientClass;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
function getWasm() {
|
|
1330
|
+
if (!_wasm) {
|
|
1331
|
+
throw new Error(
|
|
1332
|
+
"WASM not initialized. Ensure the SDK is loaded before calling standalone utilities."
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
return _wasm;
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
/**
|
|
1339
|
+
* Creates a P2ID (Pay-to-ID) note.
|
|
1340
|
+
*
|
|
1341
|
+
* @param {NoteOptions} opts - Note creation options.
|
|
1342
|
+
* @returns {OutputNote} The created output note.
|
|
1343
|
+
*/
|
|
1344
|
+
function createP2IDNote(opts) {
|
|
1345
|
+
const wasm = getWasm();
|
|
1346
|
+
const sender = resolveAccountRef(opts.from, wasm);
|
|
1347
|
+
const target = resolveAccountRef(opts.to, wasm);
|
|
1348
|
+
const noteAssets = buildNoteAssets(opts.assets, wasm);
|
|
1349
|
+
const noteType = resolveNoteType(opts.type, wasm);
|
|
1350
|
+
const attachment = opts.attachment
|
|
1351
|
+
? new wasm.NoteAttachment(opts.attachment)
|
|
1352
|
+
: new wasm.NoteAttachment([]);
|
|
1353
|
+
|
|
1354
|
+
const note = wasm.Note.createP2IDNote(
|
|
1355
|
+
sender,
|
|
1356
|
+
target,
|
|
1357
|
+
noteAssets,
|
|
1358
|
+
noteType,
|
|
1359
|
+
attachment
|
|
1360
|
+
);
|
|
1361
|
+
return wasm.OutputNote.full(note);
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
/**
|
|
1365
|
+
* Creates a P2IDE (Pay-to-ID with Expiration) note.
|
|
1366
|
+
*
|
|
1367
|
+
* @param {P2IDEOptions} opts - Note creation options with timelock/reclaim.
|
|
1368
|
+
* @returns {OutputNote} The created output note.
|
|
1369
|
+
*/
|
|
1370
|
+
function createP2IDENote(opts) {
|
|
1371
|
+
const wasm = getWasm();
|
|
1372
|
+
const sender = resolveAccountRef(opts.from, wasm);
|
|
1373
|
+
const target = resolveAccountRef(opts.to, wasm);
|
|
1374
|
+
const noteAssets = buildNoteAssets(opts.assets, wasm);
|
|
1375
|
+
const noteType = resolveNoteType(opts.type, wasm);
|
|
1376
|
+
const attachment = opts.attachment
|
|
1377
|
+
? new wasm.NoteAttachment(opts.attachment)
|
|
1378
|
+
: new wasm.NoteAttachment([]);
|
|
1379
|
+
|
|
1380
|
+
const note = wasm.Note.createP2IDENote(
|
|
1381
|
+
sender,
|
|
1382
|
+
target,
|
|
1383
|
+
noteAssets,
|
|
1384
|
+
opts.reclaimAfter,
|
|
1385
|
+
opts.timelockUntil,
|
|
1386
|
+
noteType,
|
|
1387
|
+
attachment
|
|
1388
|
+
);
|
|
1389
|
+
return wasm.OutputNote.full(note);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
/**
|
|
1393
|
+
* Builds a swap tag for note matching.
|
|
1394
|
+
*
|
|
1395
|
+
* @param {BuildSwapTagOptions} opts - Swap tag options.
|
|
1396
|
+
* @returns {NoteTag} The computed swap tag.
|
|
1397
|
+
*/
|
|
1398
|
+
function buildSwapTag(opts) {
|
|
1399
|
+
const wasm = getWasm();
|
|
1400
|
+
if (!_WebClient || typeof _WebClient.buildSwapTag !== "function") {
|
|
1401
|
+
throw new Error(
|
|
1402
|
+
"WebClient.buildSwapTag is not available. Ensure the SDK is fully loaded."
|
|
1403
|
+
);
|
|
1404
|
+
}
|
|
1405
|
+
const noteType = resolveNoteType(opts.type, wasm);
|
|
1406
|
+
const offeredFaucetId = resolveAccountRef(opts.offer.token, wasm);
|
|
1407
|
+
const requestedFaucetId = resolveAccountRef(opts.request.token, wasm);
|
|
1408
|
+
|
|
1409
|
+
return _WebClient.buildSwapTag(
|
|
1410
|
+
noteType,
|
|
1411
|
+
offeredFaucetId,
|
|
1412
|
+
BigInt(opts.offer.amount),
|
|
1413
|
+
requestedFaucetId,
|
|
1414
|
+
BigInt(opts.request.amount)
|
|
1415
|
+
);
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
function buildNoteAssets(assets, wasm) {
|
|
1419
|
+
const assetArray = Array.isArray(assets) ? assets : [assets];
|
|
1420
|
+
const fungibleAssets = assetArray.map((asset) => {
|
|
1421
|
+
const faucetId = resolveAccountRef(asset.token, wasm);
|
|
1422
|
+
return new wasm.FungibleAsset(faucetId, BigInt(asset.amount));
|
|
1423
|
+
});
|
|
1424
|
+
return new wasm.NoteAssets(fungibleAssets);
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
const AccountType = Object.freeze({
|
|
1428
|
+
MutableWallet: "MutableWallet",
|
|
1429
|
+
ImmutableWallet: "ImmutableWallet",
|
|
1430
|
+
FungibleFaucet: "FungibleFaucet",
|
|
1431
|
+
});
|
|
1432
|
+
|
|
1433
|
+
const AuthScheme = Object.freeze({
|
|
1434
|
+
Falcon: "falcon",
|
|
1435
|
+
ECDSA: "ecdsa",
|
|
1436
|
+
});
|
|
1437
|
+
|
|
242
1438
|
const buildTypedArraysExport = (exportObject) => {
|
|
243
1439
|
return Object.entries(exportObject).reduce(
|
|
244
|
-
(exports, [exportName, _export]) => {
|
|
1440
|
+
(exports$1, [exportName, _export]) => {
|
|
245
1441
|
if (exportName.endsWith("Array")) {
|
|
246
|
-
exports[exportName] = _export;
|
|
1442
|
+
exports$1[exportName] = _export;
|
|
247
1443
|
}
|
|
248
|
-
return exports;
|
|
1444
|
+
return exports$1;
|
|
249
1445
|
},
|
|
250
1446
|
{}
|
|
251
1447
|
);
|
|
@@ -291,6 +1487,8 @@ const ensureWasm = async () => {
|
|
|
291
1487
|
copyWebClientStatics(module.WebClient);
|
|
292
1488
|
webClientStaticsCopied = true;
|
|
293
1489
|
}
|
|
1490
|
+
// Set WASM module for standalone utilities
|
|
1491
|
+
_setWasm(module);
|
|
294
1492
|
}
|
|
295
1493
|
return module;
|
|
296
1494
|
});
|
|
@@ -332,6 +1530,28 @@ const getWasmOrThrow = async () => {
|
|
|
332
1530
|
* Because of this implementation, the only breaking change for end users is in the way the
|
|
333
1531
|
* web client is instantiated. Users should now use the WebClient.createClient static call.
|
|
334
1532
|
*/
|
|
1533
|
+
/**
|
|
1534
|
+
* Create a Proxy that forwards missing properties to the underlying WASM
|
|
1535
|
+
* WebClient.
|
|
1536
|
+
*/
|
|
1537
|
+
function createClientProxy(instance) {
|
|
1538
|
+
return new Proxy(instance, {
|
|
1539
|
+
get(target, prop, receiver) {
|
|
1540
|
+
if (prop in target) {
|
|
1541
|
+
return Reflect.get(target, prop, receiver);
|
|
1542
|
+
}
|
|
1543
|
+
if (target.wasmWebClient && prop in target.wasmWebClient) {
|
|
1544
|
+
const value = target.wasmWebClient[prop];
|
|
1545
|
+
if (typeof value === "function") {
|
|
1546
|
+
return value.bind(target.wasmWebClient);
|
|
1547
|
+
}
|
|
1548
|
+
return value;
|
|
1549
|
+
}
|
|
1550
|
+
return undefined;
|
|
1551
|
+
},
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1554
|
+
|
|
335
1555
|
class WebClient {
|
|
336
1556
|
/**
|
|
337
1557
|
* Create a WebClient wrapper.
|
|
@@ -477,6 +1697,25 @@ class WebClient {
|
|
|
477
1697
|
// Lazy initialize the underlying WASM WebClient when first requested.
|
|
478
1698
|
this.wasmWebClient = null;
|
|
479
1699
|
this.wasmWebClientPromise = null;
|
|
1700
|
+
|
|
1701
|
+
// Promise chain to serialize direct WASM calls that require exclusive
|
|
1702
|
+
// (&mut self) access. Without this, concurrent calls on the same client
|
|
1703
|
+
// would panic with "recursive use of an object detected" due to
|
|
1704
|
+
// wasm-bindgen's internal RefCell.
|
|
1705
|
+
this._wasmCallChain = Promise.resolve();
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
/**
|
|
1709
|
+
* Serialize a WASM call that requires exclusive (&mut self) access.
|
|
1710
|
+
* Concurrent calls are queued and executed one at a time.
|
|
1711
|
+
*
|
|
1712
|
+
* @param {() => Promise<any>} fn - The async function to execute.
|
|
1713
|
+
* @returns {Promise<any>} The result of fn.
|
|
1714
|
+
*/
|
|
1715
|
+
_serializeWasmCall(fn) {
|
|
1716
|
+
const result = this._wasmCallChain.catch(() => {}).then(fn);
|
|
1717
|
+
this._wasmCallChain = result.catch(() => {});
|
|
1718
|
+
return result;
|
|
480
1719
|
}
|
|
481
1720
|
|
|
482
1721
|
// TODO: This will soon conflict with some changes in main.
|
|
@@ -550,24 +1789,7 @@ class WebClient {
|
|
|
550
1789
|
// Wait for the worker to be ready
|
|
551
1790
|
await instance.ready;
|
|
552
1791
|
|
|
553
|
-
|
|
554
|
-
return new Proxy(instance, {
|
|
555
|
-
get(target, prop, receiver) {
|
|
556
|
-
// If the property exists on the wrapper, return it.
|
|
557
|
-
if (prop in target) {
|
|
558
|
-
return Reflect.get(target, prop, receiver);
|
|
559
|
-
}
|
|
560
|
-
// Otherwise, if the wasmWebClient has it, return that.
|
|
561
|
-
if (target.wasmWebClient && prop in target.wasmWebClient) {
|
|
562
|
-
const value = target.wasmWebClient[prop];
|
|
563
|
-
if (typeof value === "function") {
|
|
564
|
-
return value.bind(target.wasmWebClient);
|
|
565
|
-
}
|
|
566
|
-
return value;
|
|
567
|
-
}
|
|
568
|
-
return undefined;
|
|
569
|
-
},
|
|
570
|
-
});
|
|
1792
|
+
return createClientProxy(instance);
|
|
571
1793
|
}
|
|
572
1794
|
|
|
573
1795
|
/**
|
|
@@ -625,24 +1847,7 @@ class WebClient {
|
|
|
625
1847
|
);
|
|
626
1848
|
|
|
627
1849
|
await instance.ready;
|
|
628
|
-
|
|
629
|
-
return new Proxy(instance, {
|
|
630
|
-
get(target, prop, receiver) {
|
|
631
|
-
// If the property exists on the wrapper, return it.
|
|
632
|
-
if (prop in target) {
|
|
633
|
-
return Reflect.get(target, prop, receiver);
|
|
634
|
-
}
|
|
635
|
-
// Otherwise, if the wasmWebClient has it, return that.
|
|
636
|
-
if (target.wasmWebClient && prop in target.wasmWebClient) {
|
|
637
|
-
const value = target.wasmWebClient[prop];
|
|
638
|
-
if (typeof value === "function") {
|
|
639
|
-
return value.bind(target.wasmWebClient);
|
|
640
|
-
}
|
|
641
|
-
return value;
|
|
642
|
-
}
|
|
643
|
-
return undefined;
|
|
644
|
-
},
|
|
645
|
-
});
|
|
1850
|
+
return createClientProxy(instance);
|
|
646
1851
|
}
|
|
647
1852
|
|
|
648
1853
|
/**
|
|
@@ -671,30 +1876,15 @@ class WebClient {
|
|
|
671
1876
|
// ----- Explicitly Wrapped Methods (Worker-Forwarded) -----
|
|
672
1877
|
|
|
673
1878
|
async newWallet(storageMode, mutable, authSchemeId, seed) {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
storageMode,
|
|
679
|
-
mutable,
|
|
680
|
-
authSchemeId,
|
|
681
|
-
seed
|
|
682
|
-
);
|
|
683
|
-
}
|
|
684
|
-
const wasm = await getWasmOrThrow();
|
|
685
|
-
const serializedStorageMode = storageMode.asStr();
|
|
686
|
-
const serializedAccountBytes = await this.callMethodWithWorker(
|
|
687
|
-
MethodName.NEW_WALLET,
|
|
688
|
-
serializedStorageMode,
|
|
1879
|
+
return this._serializeWasmCall(async () => {
|
|
1880
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
1881
|
+
return await wasmWebClient.newWallet(
|
|
1882
|
+
storageMode,
|
|
689
1883
|
mutable,
|
|
690
1884
|
authSchemeId,
|
|
691
1885
|
seed
|
|
692
1886
|
);
|
|
693
|
-
|
|
694
|
-
} catch (error) {
|
|
695
|
-
console.error("INDEX.JS: Error in newWallet:", error);
|
|
696
|
-
throw error;
|
|
697
|
-
}
|
|
1887
|
+
});
|
|
698
1888
|
}
|
|
699
1889
|
|
|
700
1890
|
async newFaucet(
|
|
@@ -705,36 +1895,17 @@ class WebClient {
|
|
|
705
1895
|
maxSupply,
|
|
706
1896
|
authSchemeId
|
|
707
1897
|
) {
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
storageMode,
|
|
713
|
-
nonFungible,
|
|
714
|
-
tokenSymbol,
|
|
715
|
-
decimals,
|
|
716
|
-
maxSupply,
|
|
717
|
-
authSchemeId
|
|
718
|
-
);
|
|
719
|
-
}
|
|
720
|
-
const wasm = await getWasmOrThrow();
|
|
721
|
-
const serializedStorageMode = storageMode.asStr();
|
|
722
|
-
const serializedMaxSupply = maxSupply.toString();
|
|
723
|
-
const serializedAccountBytes = await this.callMethodWithWorker(
|
|
724
|
-
MethodName.NEW_FAUCET,
|
|
725
|
-
serializedStorageMode,
|
|
1898
|
+
return this._serializeWasmCall(async () => {
|
|
1899
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
1900
|
+
return await wasmWebClient.newFaucet(
|
|
1901
|
+
storageMode,
|
|
726
1902
|
nonFungible,
|
|
727
1903
|
tokenSymbol,
|
|
728
1904
|
decimals,
|
|
729
|
-
|
|
1905
|
+
maxSupply,
|
|
730
1906
|
authSchemeId
|
|
731
1907
|
);
|
|
732
|
-
|
|
733
|
-
return wasm.Account.deserialize(new Uint8Array(serializedAccountBytes));
|
|
734
|
-
} catch (error) {
|
|
735
|
-
console.error("INDEX.JS: Error in newFaucet:", error);
|
|
736
|
-
throw error;
|
|
737
|
-
}
|
|
1908
|
+
});
|
|
738
1909
|
}
|
|
739
1910
|
|
|
740
1911
|
async submitNewTransaction(accountId, transactionRequest) {
|
|
@@ -854,6 +2025,33 @@ class WebClient {
|
|
|
854
2025
|
}
|
|
855
2026
|
}
|
|
856
2027
|
|
|
2028
|
+
async applyTransaction(transactionResult, submissionHeight) {
|
|
2029
|
+
try {
|
|
2030
|
+
if (!this.worker) {
|
|
2031
|
+
const wasmWebClient = await this.getWasmWebClient();
|
|
2032
|
+
return await wasmWebClient.applyTransaction(
|
|
2033
|
+
transactionResult,
|
|
2034
|
+
submissionHeight
|
|
2035
|
+
);
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
const wasm = await getWasmOrThrow();
|
|
2039
|
+
const serializedTransactionResult = transactionResult.serialize();
|
|
2040
|
+
const serializedUpdateBytes = await this.callMethodWithWorker(
|
|
2041
|
+
MethodName.APPLY_TRANSACTION,
|
|
2042
|
+
serializedTransactionResult,
|
|
2043
|
+
submissionHeight
|
|
2044
|
+
);
|
|
2045
|
+
|
|
2046
|
+
return wasm.TransactionStoreUpdate.deserialize(
|
|
2047
|
+
new Uint8Array(serializedUpdateBytes)
|
|
2048
|
+
);
|
|
2049
|
+
} catch (error) {
|
|
2050
|
+
console.error("INDEX.JS: Error in applyTransaction:", error);
|
|
2051
|
+
throw error;
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
|
|
857
2055
|
/**
|
|
858
2056
|
* Syncs the client state with the node.
|
|
859
2057
|
*
|
|
@@ -920,6 +2118,15 @@ class WebClient {
|
|
|
920
2118
|
}
|
|
921
2119
|
}
|
|
922
2120
|
|
|
2121
|
+
/**
|
|
2122
|
+
* Terminates the underlying Web Worker used by this WebClient instance.
|
|
2123
|
+
*
|
|
2124
|
+
* Call this method when you're done using a WebClient to free up browser
|
|
2125
|
+
* resources. Each WebClient instance uses a dedicated Web Worker for
|
|
2126
|
+
* computationally intensive operations. Terminating releases that thread.
|
|
2127
|
+
*
|
|
2128
|
+
* After calling terminate(), the WebClient should not be used.
|
|
2129
|
+
*/
|
|
923
2130
|
terminate() {
|
|
924
2131
|
if (this.worker) {
|
|
925
2132
|
this.worker.terminate();
|
|
@@ -973,24 +2180,7 @@ class MockWebClient extends WebClient {
|
|
|
973
2180
|
// Wait for the worker to be ready
|
|
974
2181
|
await instance.ready;
|
|
975
2182
|
|
|
976
|
-
|
|
977
|
-
return new Proxy(instance, {
|
|
978
|
-
get(target, prop, receiver) {
|
|
979
|
-
// If the property exists on the wrapper, return it.
|
|
980
|
-
if (prop in target) {
|
|
981
|
-
return Reflect.get(target, prop, receiver);
|
|
982
|
-
}
|
|
983
|
-
// Otherwise, if the wasmWebClient has it, return that.
|
|
984
|
-
if (target.wasmWebClient && prop in target.wasmWebClient) {
|
|
985
|
-
const value = target.wasmWebClient[prop];
|
|
986
|
-
if (typeof value === "function") {
|
|
987
|
-
return value.bind(target.wasmWebClient);
|
|
988
|
-
}
|
|
989
|
-
return value;
|
|
990
|
-
}
|
|
991
|
-
return undefined;
|
|
992
|
-
},
|
|
993
|
-
});
|
|
2183
|
+
return createClientProxy(instance);
|
|
994
2184
|
}
|
|
995
2185
|
|
|
996
2186
|
/**
|
|
@@ -1181,5 +2371,11 @@ function copyWebClientStatics(WasmWebClient) {
|
|
|
1181
2371
|
});
|
|
1182
2372
|
}
|
|
1183
2373
|
|
|
1184
|
-
|
|
2374
|
+
// Wire MidenClient dependencies (resolves circular import)
|
|
2375
|
+
MidenClient._WasmWebClient = WebClient;
|
|
2376
|
+
MidenClient._MockWasmWebClient = MockWebClient;
|
|
2377
|
+
MidenClient._getWasmOrThrow = getWasmOrThrow;
|
|
2378
|
+
_setWebClient(WebClient);
|
|
2379
|
+
|
|
2380
|
+
export { AccountType, AuthScheme, MidenArrays, MidenClient, MockWebClient as MockWasmWebClient, WebClient as WasmWebClient, buildSwapTag, createP2IDENote, createP2IDNote, getWasmOrThrow };
|
|
1185
2381
|
//# sourceMappingURL=index.js.map
|