@miden-sdk/miden-sdk 0.14.11 → 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.
Files changed (59) hide show
  1. package/dist/mt/{Cargo-CZopJ--X.js → Cargo-smJQCGjz.js} +1111 -768
  2. package/dist/mt/Cargo-smJQCGjz.js.map +1 -0
  3. package/dist/mt/api-types.d.ts +122 -33
  4. package/dist/mt/assets/miden_client_web.wasm +0 -0
  5. package/dist/mt/crates/miden_client_web.d.ts +376 -303
  6. package/dist/mt/docs-entry.d.ts +3 -0
  7. package/dist/mt/eager.js +7 -4
  8. package/dist/mt/eager.js.map +1 -1
  9. package/dist/mt/index.d.ts +103 -10
  10. package/dist/mt/index.js +669 -312
  11. package/dist/mt/index.js.map +1 -1
  12. package/dist/mt/wasm.js +1 -1
  13. package/dist/mt/workerHelpers.js +1 -1
  14. package/dist/mt/workers/{Cargo-CZopJ--X-SsyOTzpb.js → Cargo-smJQCGjz-q4GYXDiD.js} +1111 -768
  15. package/dist/mt/workers/Cargo-smJQCGjz-q4GYXDiD.js.map +1 -0
  16. package/dist/mt/workers/assets/miden_client_web.wasm +0 -0
  17. package/dist/mt/workers/web-client-methods-worker.js +1140 -792
  18. package/dist/mt/workers/web-client-methods-worker.js.map +1 -1
  19. package/dist/mt/workers/web-client-methods-worker.module.js +23 -19
  20. package/dist/mt/workers/web-client-methods-worker.module.js.map +1 -1
  21. package/dist/mt/workers/workerHelpers.js +1 -1
  22. package/dist/st/{Cargo-DC6jSekr.js → Cargo-CG4XszZo.js} +1105 -763
  23. package/dist/st/Cargo-CG4XszZo.js.map +1 -0
  24. package/dist/st/api-types.d.ts +122 -33
  25. package/dist/st/assets/miden_client_web.wasm +0 -0
  26. package/dist/st/crates/miden_client_web.d.ts +376 -303
  27. package/dist/st/docs-entry.d.ts +3 -0
  28. package/dist/st/eager.js +7 -4
  29. package/dist/st/eager.js.map +1 -1
  30. package/dist/st/index.d.ts +103 -10
  31. package/dist/st/index.js +669 -312
  32. package/dist/st/index.js.map +1 -1
  33. package/dist/st/wasm.js +1 -1
  34. package/dist/st/workers/{Cargo-DC6jSekr-BG7C7m56.js → Cargo-CG4XszZo-S7EHAZSa.js} +1105 -763
  35. package/dist/st/workers/Cargo-CG4XszZo-S7EHAZSa.js.map +1 -0
  36. package/dist/st/workers/assets/miden_client_web.wasm +0 -0
  37. package/dist/st/workers/web-client-methods-worker.js +1134 -787
  38. package/dist/st/workers/web-client-methods-worker.js.map +1 -1
  39. package/dist/st/workers/web-client-methods-worker.module.js +23 -19
  40. package/dist/st/workers/web-client-methods-worker.module.js.map +1 -1
  41. package/js/client.js +491 -0
  42. package/js/node/client-factory.js +117 -0
  43. package/js/node/loader.js +138 -0
  44. package/js/node/napi-compat.js +253 -0
  45. package/js/node-index.js +194 -0
  46. package/js/resources/accounts.js +222 -0
  47. package/js/resources/compiler.js +74 -0
  48. package/js/resources/keystore.js +54 -0
  49. package/js/resources/notes.js +124 -0
  50. package/js/resources/settings.js +30 -0
  51. package/js/resources/tags.js +31 -0
  52. package/js/resources/transactions.js +667 -0
  53. package/js/standalone.js +109 -0
  54. package/js/utils.js +232 -0
  55. package/package.json +17 -2
  56. package/dist/mt/Cargo-CZopJ--X.js.map +0 -1
  57. package/dist/mt/workers/Cargo-CZopJ--X-SsyOTzpb.js.map +0 -1
  58. package/dist/st/Cargo-DC6jSekr.js.map +0 -1
  59. package/dist/st/workers/Cargo-DC6jSekr-BG7C7m56.js.map +0 -1
@@ -0,0 +1,667 @@
1
+ import {
2
+ resolveAccountRef,
3
+ resolveNoteType,
4
+ resolveTransactionIdHex,
5
+ } from "../utils.js";
6
+
7
+ export class TransactionsResource {
8
+ #inner;
9
+ #getWasm;
10
+ #client;
11
+
12
+ constructor(inner, getWasm, client) {
13
+ this.#inner = inner;
14
+ this.#getWasm = getWasm;
15
+ this.#client = client;
16
+ }
17
+
18
+ async send(opts) {
19
+ this.#client.assertNotTerminated();
20
+ const wasm = await this.#getWasm();
21
+
22
+ if (opts.returnNote === true) {
23
+ // returnNote path — build the P2ID note in JS so we can return the Note
24
+ // object to the caller (e.g. for out-of-band delivery to the recipient).
25
+ if (opts.reclaimAfter != null || opts.timelockUntil != null) {
26
+ throw new Error(
27
+ "reclaimAfter and timelockUntil are not supported when returnNote is true"
28
+ );
29
+ }
30
+
31
+ const senderId = resolveAccountRef(opts.account, wasm);
32
+ const receiverId = resolveAccountRef(opts.to, wasm);
33
+ const faucetId = resolveAccountRef(opts.token, wasm);
34
+ const noteType = resolveNoteType(opts.type, wasm);
35
+
36
+ const note = wasm.Note.createP2IDNote(
37
+ senderId,
38
+ receiverId,
39
+ new wasm.NoteAssets([
40
+ new wasm.FungibleAsset(faucetId, BigInt(opts.amount)),
41
+ ]),
42
+ noteType,
43
+ new wasm.NoteAttachment()
44
+ );
45
+
46
+ // NoteArray constructor consumes its elements; use push(&note) to keep
47
+ // `note` valid so we can return it to the caller below.
48
+ const ownOutputs = new wasm.NoteArray();
49
+ ownOutputs.push(note);
50
+ const request = new wasm.TransactionRequestBuilder()
51
+ .withOwnOutputNotes(ownOutputs)
52
+ .build();
53
+
54
+ const { txId, result } = await this.#submitOrSubmitWithProver(
55
+ senderId,
56
+ request,
57
+ opts.prover
58
+ );
59
+
60
+ if (opts.waitForConfirmation) {
61
+ await this.waitFor(txId.toHex(), { timeout: opts.timeout });
62
+ }
63
+
64
+ return { txId, note, result };
65
+ }
66
+
67
+ // Default path — note built in WASM with optional reclaim/timelock
68
+ const { accountId, request } = await this.#buildSendRequest(opts, wasm);
69
+ const { txId, result } = await this.#submitOrSubmitWithProver(
70
+ accountId,
71
+ request,
72
+ opts.prover
73
+ );
74
+
75
+ if (opts.waitForConfirmation) {
76
+ await this.waitFor(txId.toHex(), { timeout: opts.timeout });
77
+ }
78
+
79
+ return { txId, note: null, result };
80
+ }
81
+
82
+ async mint(opts) {
83
+ this.#client.assertNotTerminated();
84
+ const wasm = await this.#getWasm();
85
+ const { accountId, request } = await this.#buildMintRequest(opts, wasm);
86
+
87
+ const { txId, result } = await this.#submitOrSubmitWithProver(
88
+ accountId,
89
+ request,
90
+ opts.prover
91
+ );
92
+
93
+ if (opts.waitForConfirmation) {
94
+ await this.waitFor(txId.toHex(), { timeout: opts.timeout });
95
+ }
96
+
97
+ return { txId, result };
98
+ }
99
+
100
+ async consume(opts) {
101
+ this.#client.assertNotTerminated();
102
+ const wasm = await this.#getWasm();
103
+ const { accountId, request } = await this.#buildConsumeRequest(opts, wasm);
104
+
105
+ const { txId, result } = await this.#submitOrSubmitWithProver(
106
+ accountId,
107
+ request,
108
+ opts.prover
109
+ );
110
+
111
+ if (opts.waitForConfirmation) {
112
+ await this.waitFor(txId.toHex(), { timeout: opts.timeout });
113
+ }
114
+
115
+ return { txId, result };
116
+ }
117
+
118
+ async consumeAll(opts) {
119
+ this.#client.assertNotTerminated();
120
+ const wasm = await this.#getWasm();
121
+
122
+ // getConsumableNotes takes AccountId by value (consumed by WASM).
123
+ // Save hex so we can reconstruct for submitNewTransaction.
124
+ const accountId = resolveAccountRef(opts.account, wasm);
125
+ const accountIdHex = accountId.toString();
126
+ const consumable = await this.#inner.getConsumableNotes(accountId);
127
+
128
+ if (!consumable || consumable.length === 0) {
129
+ return { txId: null, consumed: 0, remaining: 0 };
130
+ }
131
+
132
+ const total = consumable.length;
133
+ const toConsume =
134
+ opts.maxNotes != null ? consumable.slice(0, opts.maxNotes) : consumable;
135
+
136
+ if (toConsume.length === 0) {
137
+ return { txId: null, consumed: 0, remaining: total };
138
+ }
139
+
140
+ const notes = toConsume.map((c) => c.inputNoteRecord().toNote());
141
+
142
+ const request = await this.#inner.newConsumeTransactionRequest(notes);
143
+
144
+ const { txId, result } = await this.#submitOrSubmitWithProver(
145
+ wasm.AccountId.fromHex(accountIdHex),
146
+ request,
147
+ opts.prover
148
+ );
149
+
150
+ if (opts.waitForConfirmation) {
151
+ await this.waitFor(txId.toHex(), { timeout: opts.timeout });
152
+ }
153
+
154
+ return {
155
+ txId,
156
+ consumed: toConsume.length,
157
+ remaining: total - toConsume.length,
158
+ result,
159
+ };
160
+ }
161
+
162
+ async swap(opts) {
163
+ this.#client.assertNotTerminated();
164
+ const wasm = await this.#getWasm();
165
+ const { accountId, request } = await this.#buildSwapRequest(opts, wasm);
166
+
167
+ const { txId, result } = await this.#submitOrSubmitWithProver(
168
+ accountId,
169
+ request,
170
+ opts.prover
171
+ );
172
+
173
+ if (opts.waitForConfirmation) {
174
+ await this.waitFor(txId.toHex(), { timeout: opts.timeout });
175
+ }
176
+
177
+ return { txId, result };
178
+ }
179
+
180
+ /** Create a partial-swap (PSWAP) note. See {@link PswapCreateOptions}. */
181
+ async pswapCreate(opts) {
182
+ this.#client.assertNotTerminated();
183
+ const wasm = await this.#getWasm();
184
+ const { accountId, request } = await this.#buildPswapCreateRequest(
185
+ opts,
186
+ wasm
187
+ );
188
+
189
+ const { txId, result } = await this.#submitOrSubmitWithProver(
190
+ accountId,
191
+ request,
192
+ opts.prover
193
+ );
194
+
195
+ if (opts.waitForConfirmation) {
196
+ await this.waitFor(txId.toHex(), { timeout: opts.timeout });
197
+ }
198
+
199
+ return { txId, result };
200
+ }
201
+
202
+ /** Consume (fully or partially fill) a PSWAP note. See {@link PswapConsumeOptions}. */
203
+ async pswapConsume(opts) {
204
+ this.#client.assertNotTerminated();
205
+ const wasm = await this.#getWasm();
206
+ const { accountId, request } = await this.#buildPswapConsumeRequest(
207
+ opts,
208
+ wasm
209
+ );
210
+
211
+ const { txId, result } = await this.#submitOrSubmitWithProver(
212
+ accountId,
213
+ request,
214
+ opts.prover
215
+ );
216
+
217
+ if (opts.waitForConfirmation) {
218
+ await this.waitFor(txId.toHex(), { timeout: opts.timeout });
219
+ }
220
+
221
+ return { txId, result };
222
+ }
223
+
224
+ /** Cancel a PSWAP note as its creator and reclaim the offered asset. See {@link PswapCancelOptions}. */
225
+ async pswapCancel(opts) {
226
+ this.#client.assertNotTerminated();
227
+ const wasm = await this.#getWasm();
228
+ const { accountId, request } = await this.#buildPswapCancelRequest(
229
+ opts,
230
+ wasm
231
+ );
232
+
233
+ const { txId, result } = await this.#submitOrSubmitWithProver(
234
+ accountId,
235
+ request,
236
+ opts.prover
237
+ );
238
+
239
+ if (opts.waitForConfirmation) {
240
+ await this.waitFor(txId.toHex(), { timeout: opts.timeout });
241
+ }
242
+
243
+ return { txId, result };
244
+ }
245
+
246
+ async preview(opts) {
247
+ this.#client.assertNotTerminated();
248
+ const wasm = await this.#getWasm();
249
+
250
+ let accountId;
251
+ let request;
252
+
253
+ switch (opts.operation) {
254
+ case "send": {
255
+ ({ accountId, request } = await this.#buildSendRequest(opts, wasm));
256
+ break;
257
+ }
258
+ case "mint": {
259
+ ({ accountId, request } = await this.#buildMintRequest(opts, wasm));
260
+ break;
261
+ }
262
+ case "consume": {
263
+ ({ accountId, request } = await this.#buildConsumeRequest(opts, wasm));
264
+ break;
265
+ }
266
+ case "swap": {
267
+ ({ accountId, request } = await this.#buildSwapRequest(opts, wasm));
268
+ break;
269
+ }
270
+ case "pswapCreate": {
271
+ ({ accountId, request } = await this.#buildPswapCreateRequest(
272
+ opts,
273
+ wasm
274
+ ));
275
+ break;
276
+ }
277
+ case "pswapConsume": {
278
+ ({ accountId, request } = await this.#buildPswapConsumeRequest(
279
+ opts,
280
+ wasm
281
+ ));
282
+ break;
283
+ }
284
+ case "pswapCancel": {
285
+ ({ accountId, request } = await this.#buildPswapCancelRequest(
286
+ opts,
287
+ wasm
288
+ ));
289
+ break;
290
+ }
291
+ case "custom": {
292
+ accountId = resolveAccountRef(opts.account, wasm);
293
+ request = opts.request;
294
+ break;
295
+ }
296
+ default:
297
+ throw new Error(`Unknown preview operation: ${opts.operation}`);
298
+ }
299
+
300
+ return await this.#inner.executeForSummary(accountId, request);
301
+ }
302
+
303
+ async execute(opts) {
304
+ this.#client.assertNotTerminated();
305
+ const wasm = await this.#getWasm();
306
+ const accountId = resolveAccountRef(opts.account, wasm);
307
+
308
+ let builder = new wasm.TransactionRequestBuilder().withCustomScript(
309
+ opts.script
310
+ );
311
+
312
+ if (opts.foreignAccounts?.length) {
313
+ const accounts = opts.foreignAccounts.map((fa) => {
314
+ // Distinguish { id: AccountRef, storage? } wrapper objects from WASM types
315
+ // (Account/AccountHeader expose .id() as a method, wrappers have .id as a property)
316
+ const isWrapper =
317
+ fa !== null &&
318
+ typeof fa === "object" &&
319
+ "id" in fa &&
320
+ typeof fa.id !== "function";
321
+ const id = resolveAccountRef(isWrapper ? fa.id : fa, wasm);
322
+ const storage =
323
+ isWrapper && fa.storage
324
+ ? fa.storage
325
+ : new wasm.AccountStorageRequirements();
326
+ return wasm.ForeignAccount.public(id, storage);
327
+ });
328
+ builder = builder.withForeignAccounts(
329
+ new wasm.ForeignAccountArray(accounts)
330
+ );
331
+ }
332
+
333
+ const request = builder.build();
334
+ const { txId, result } = await this.#submitOrSubmitWithProver(
335
+ accountId,
336
+ request,
337
+ opts.prover
338
+ );
339
+
340
+ if (opts.waitForConfirmation) {
341
+ await this.waitFor(txId.toHex(), { timeout: opts.timeout });
342
+ }
343
+
344
+ return { txId, result };
345
+ }
346
+
347
+ async executeProgram(opts) {
348
+ this.#client.assertNotTerminated();
349
+ const wasm = await this.#getWasm();
350
+ const accountId = resolveAccountRef(opts.account, wasm);
351
+
352
+ let foreignAccountsArray = new wasm.ForeignAccountArray();
353
+ if (opts.foreignAccounts?.length) {
354
+ const accounts = opts.foreignAccounts.map((fa) => {
355
+ const isWrapper =
356
+ fa !== null &&
357
+ typeof fa === "object" &&
358
+ "id" in fa &&
359
+ typeof fa.id !== "function";
360
+ const id = resolveAccountRef(isWrapper ? fa.id : fa, wasm);
361
+ const storage =
362
+ isWrapper && fa.storage
363
+ ? fa.storage
364
+ : new wasm.AccountStorageRequirements();
365
+ return wasm.ForeignAccount.public(id, storage);
366
+ });
367
+ foreignAccountsArray = new wasm.ForeignAccountArray(accounts);
368
+ }
369
+
370
+ return await this.#inner.executeProgram(
371
+ accountId,
372
+ opts.script,
373
+ opts.adviceInputs ?? new wasm.AdviceInputs(),
374
+ foreignAccountsArray
375
+ );
376
+ }
377
+
378
+ async submit(account, request, opts) {
379
+ this.#client.assertNotTerminated();
380
+ const wasm = await this.#getWasm();
381
+ const accountId = resolveAccountRef(account, wasm);
382
+ return await this.#submitOrSubmitWithProver(
383
+ accountId,
384
+ request,
385
+ opts?.prover
386
+ );
387
+ }
388
+
389
+ async list(query) {
390
+ this.#client.assertNotTerminated();
391
+ const wasm = await this.#getWasm();
392
+
393
+ let filter;
394
+ if (!query) {
395
+ filter = wasm.TransactionFilter.all();
396
+ } else if (query.status === "uncommitted") {
397
+ filter = wasm.TransactionFilter.uncommitted();
398
+ } else if (query.ids) {
399
+ const txIds = query.ids.map((id) =>
400
+ wasm.TransactionId.fromHex(resolveTransactionIdHex(id))
401
+ );
402
+ filter = wasm.TransactionFilter.ids(txIds);
403
+ } else if (query.expiredBefore !== undefined) {
404
+ filter = wasm.TransactionFilter.expiredBefore(query.expiredBefore);
405
+ } else {
406
+ filter = wasm.TransactionFilter.all();
407
+ }
408
+
409
+ return await this.#inner.getTransactions(filter);
410
+ }
411
+
412
+ /**
413
+ * Polls for transaction confirmation.
414
+ *
415
+ * @param {string | TransactionId} txId - Transaction ID hex string or TransactionId object.
416
+ * @param {WaitOptions} [opts] - Polling options.
417
+ * @param {number} [opts.timeout=60000] - Wall-clock polling timeout in
418
+ * milliseconds. This is NOT a block height — it controls how long the
419
+ * client waits before giving up. Set to 0 to disable the timeout and poll
420
+ * indefinitely until the transaction is committed or discarded.
421
+ * @param {number} [opts.interval=5000] - Polling interval in ms.
422
+ * @param {function} [opts.onProgress] - Called with the current status on
423
+ * each poll iteration ("pending", "submitted", or "committed").
424
+ */
425
+ async waitFor(txId, opts) {
426
+ this.#client.assertNotTerminated();
427
+ const hex = resolveTransactionIdHex(txId);
428
+ const timeout = opts?.timeout ?? 60_000;
429
+ const interval = opts?.interval ?? 5_000;
430
+ const start = Date.now();
431
+
432
+ const wasm = await this.#getWasm();
433
+
434
+ while (true) {
435
+ const elapsed = Date.now() - start;
436
+ if (timeout > 0 && elapsed >= timeout) {
437
+ throw new Error(
438
+ `Transaction confirmation timed out after ${timeout}ms`
439
+ );
440
+ }
441
+
442
+ try {
443
+ await this.#inner.syncStateWithTimeout(0);
444
+ } catch {
445
+ // Sync may fail transiently; continue polling
446
+ }
447
+
448
+ // Recreate filter each iteration — WASM consumes it by value
449
+ const filter = wasm.TransactionFilter.ids([
450
+ wasm.TransactionId.fromHex(hex),
451
+ ]);
452
+ const txs = await this.#inner.getTransactions(filter);
453
+
454
+ if (txs && txs.length > 0) {
455
+ const tx = txs[0];
456
+ const status = tx.transactionStatus?.();
457
+
458
+ if (status) {
459
+ if (status.isCommitted()) {
460
+ opts?.onProgress?.("committed");
461
+ return;
462
+ }
463
+ if (status.isDiscarded()) {
464
+ throw new Error(`Transaction rejected: ${hex}`);
465
+ }
466
+ }
467
+
468
+ opts?.onProgress?.("submitted");
469
+ } else {
470
+ opts?.onProgress?.("pending");
471
+ }
472
+
473
+ await new Promise((resolve) => setTimeout(resolve, interval));
474
+ }
475
+ }
476
+
477
+ // ── Shared request builders ──
478
+
479
+ async #buildSendRequest(opts, wasm) {
480
+ const accountId = resolveAccountRef(opts.account, wasm);
481
+ const targetId = resolveAccountRef(opts.to, wasm);
482
+ const faucetId = resolveAccountRef(opts.token, wasm);
483
+ const noteType = resolveNoteType(opts.type, wasm);
484
+ const amount = BigInt(opts.amount);
485
+
486
+ const request = await this.#inner.newSendTransactionRequest(
487
+ accountId,
488
+ targetId,
489
+ faucetId,
490
+ noteType,
491
+ amount,
492
+ opts.reclaimAfter,
493
+ opts.timelockUntil
494
+ );
495
+ return { accountId, request };
496
+ }
497
+
498
+ async #buildMintRequest(opts, wasm) {
499
+ const accountId = resolveAccountRef(opts.account, wasm);
500
+ const targetId = resolveAccountRef(opts.to, wasm);
501
+ const noteType = resolveNoteType(opts.type, wasm);
502
+ const amount = BigInt(opts.amount);
503
+
504
+ // WASM signature: newMintTransactionRequest(target, faucet, noteType, amount)
505
+ const request = await this.#inner.newMintTransactionRequest(
506
+ targetId,
507
+ accountId,
508
+ noteType,
509
+ amount
510
+ );
511
+ return { accountId, request };
512
+ }
513
+
514
+ async #buildConsumeRequest(opts, wasm) {
515
+ const accountId = resolveAccountRef(opts.account, wasm);
516
+ const noteInputs = Array.isArray(opts.notes) ? opts.notes : [opts.notes];
517
+
518
+ const isDirectNote = (input) =>
519
+ input !== null &&
520
+ typeof input === "object" &&
521
+ typeof input.id === "function" &&
522
+ typeof input.toNote !== "function";
523
+
524
+ const hasDirectNotes = noteInputs.some(isDirectNote);
525
+
526
+ if (hasDirectNotes) {
527
+ // At least one raw Note object — use NoteAndArgs builder path
528
+ // (the only WASM path that accepts unauthenticated notes not in the store).
529
+ const resolvedNotes = await Promise.all(
530
+ noteInputs.map(async (input) => {
531
+ if (isDirectNote(input)) return input;
532
+ if (input && typeof input.toNote === "function")
533
+ return input.toNote();
534
+ return await this.#resolveNoteInput(input);
535
+ })
536
+ );
537
+
538
+ const noteAndArgsArr = resolvedNotes.map(
539
+ (note) => new wasm.NoteAndArgs(note, null)
540
+ );
541
+ const request = new wasm.TransactionRequestBuilder()
542
+ .withInputNotes(new wasm.NoteAndArgsArray(noteAndArgsArr))
543
+ .build();
544
+ return { accountId, request };
545
+ }
546
+
547
+ // Standard path: all inputs are IDs or records — look up from store.
548
+ const notes = await Promise.all(
549
+ noteInputs.map((input) => this.#resolveNoteInput(input))
550
+ );
551
+ const request = await this.#inner.newConsumeTransactionRequest(notes);
552
+ return { accountId, request };
553
+ }
554
+
555
+ async #buildSwapRequest(opts, wasm) {
556
+ const accountId = resolveAccountRef(opts.account, wasm);
557
+ const offeredFaucetId = resolveAccountRef(opts.offer.token, wasm);
558
+ const requestedFaucetId = resolveAccountRef(opts.request.token, wasm);
559
+ const noteType = resolveNoteType(opts.type, wasm);
560
+ const paybackNoteType = resolveNoteType(
561
+ opts.paybackType ?? opts.type,
562
+ wasm
563
+ );
564
+
565
+ const request = await this.#inner.newSwapTransactionRequest(
566
+ accountId,
567
+ offeredFaucetId,
568
+ BigInt(opts.offer.amount),
569
+ requestedFaucetId,
570
+ BigInt(opts.request.amount),
571
+ noteType,
572
+ paybackNoteType
573
+ );
574
+ return { accountId, request };
575
+ }
576
+
577
+ async #buildPswapCreateRequest(opts, wasm) {
578
+ const accountId = resolveAccountRef(opts.account, wasm);
579
+ const offeredFaucetId = resolveAccountRef(opts.offer.token, wasm);
580
+ const requestedFaucetId = resolveAccountRef(opts.request.token, wasm);
581
+ const noteType = resolveNoteType(opts.type, wasm);
582
+ const paybackNoteType = resolveNoteType(
583
+ opts.paybackType ?? opts.type,
584
+ wasm
585
+ );
586
+
587
+ const request = await this.#inner.newPswapCreateTransactionRequest(
588
+ accountId,
589
+ offeredFaucetId,
590
+ BigInt(opts.offer.amount),
591
+ requestedFaucetId,
592
+ BigInt(opts.request.amount),
593
+ noteType,
594
+ paybackNoteType
595
+ );
596
+ return { accountId, request };
597
+ }
598
+
599
+ async #buildPswapConsumeRequest(opts, wasm) {
600
+ const accountId = resolveAccountRef(opts.account, wasm);
601
+ const note = await this.#resolveNoteInput(opts.note);
602
+ const noteFillAmount = opts.noteFillAmount ?? 0n;
603
+
604
+ const request = await this.#inner.newPswapConsumeTransactionRequest(
605
+ note,
606
+ accountId,
607
+ BigInt(opts.fillAmount),
608
+ BigInt(noteFillAmount)
609
+ );
610
+ return { accountId, request };
611
+ }
612
+
613
+ async #buildPswapCancelRequest(opts, wasm) {
614
+ const accountId = resolveAccountRef(opts.account, wasm);
615
+ const note = await this.#resolveNoteInput(opts.note);
616
+
617
+ const request = await this.#inner.newPswapCancelTransactionRequest(
618
+ note,
619
+ accountId
620
+ );
621
+ return { accountId, request };
622
+ }
623
+
624
+ async #resolveNoteInput(input) {
625
+ if (typeof input === "string") {
626
+ const record = await this.#inner.getInputNote(input);
627
+ if (!record) {
628
+ throw new Error(`Note not found: ${input}`);
629
+ }
630
+ return record.toNote();
631
+ }
632
+ // InputNoteRecord — unwrap to Note
633
+ if (input && typeof input.toNote === "function") {
634
+ return input.toNote();
635
+ }
636
+ // NoteId — has toString() but not toNote() or id() (unlike InputNoteRecord/Note).
637
+ // Check for constructor.fromHex to distinguish from plain objects.
638
+ if (
639
+ input &&
640
+ typeof input.toString === "function" &&
641
+ typeof input.toNote !== "function" &&
642
+ typeof input.id !== "function" &&
643
+ input.constructor?.fromHex !== undefined
644
+ ) {
645
+ const hex = input.toString();
646
+ const record = await this.#inner.getInputNote(hex);
647
+ if (!record) {
648
+ throw new Error(`Note not found: ${hex}`);
649
+ }
650
+ return record.toNote();
651
+ }
652
+ // Assume it's already a Note object
653
+ return input;
654
+ }
655
+
656
+ async #submitOrSubmitWithProver(accountId, request, perCallProver) {
657
+ const result = await this.#inner.executeTransaction(accountId, request);
658
+ const prover = perCallProver ?? this.#client.defaultProver;
659
+ const proven = prover
660
+ ? await this.#inner.proveTransaction(result, prover)
661
+ : await this.#inner.proveTransaction(result);
662
+ const txId = result.id();
663
+ const height = await this.#inner.submitProvenTransaction(proven, result);
664
+ await this.#inner.applyTransaction(result, height);
665
+ return { txId, result };
666
+ }
667
+ }