@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.
- package/dist/mt/{Cargo-CZopJ--X.js → Cargo-smJQCGjz.js} +1111 -768
- package/dist/mt/Cargo-smJQCGjz.js.map +1 -0
- package/dist/mt/api-types.d.ts +122 -33
- package/dist/mt/assets/miden_client_web.wasm +0 -0
- package/dist/mt/crates/miden_client_web.d.ts +376 -303
- package/dist/mt/docs-entry.d.ts +3 -0
- package/dist/mt/eager.js +7 -4
- package/dist/mt/eager.js.map +1 -1
- package/dist/mt/index.d.ts +103 -10
- package/dist/mt/index.js +669 -312
- package/dist/mt/index.js.map +1 -1
- package/dist/mt/wasm.js +1 -1
- package/dist/mt/workerHelpers.js +1 -1
- package/dist/mt/workers/{Cargo-CZopJ--X-SsyOTzpb.js → Cargo-smJQCGjz-q4GYXDiD.js} +1111 -768
- 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 +1140 -792
- package/dist/mt/workers/web-client-methods-worker.js.map +1 -1
- package/dist/mt/workers/web-client-methods-worker.module.js +23 -19
- package/dist/mt/workers/web-client-methods-worker.module.js.map +1 -1
- package/dist/mt/workers/workerHelpers.js +1 -1
- package/dist/st/{Cargo-DC6jSekr.js → Cargo-CG4XszZo.js} +1105 -763
- package/dist/st/Cargo-CG4XszZo.js.map +1 -0
- package/dist/st/api-types.d.ts +122 -33
- package/dist/st/assets/miden_client_web.wasm +0 -0
- package/dist/st/crates/miden_client_web.d.ts +376 -303
- package/dist/st/docs-entry.d.ts +3 -0
- package/dist/st/eager.js +7 -4
- package/dist/st/eager.js.map +1 -1
- package/dist/st/index.d.ts +103 -10
- package/dist/st/index.js +669 -312
- package/dist/st/index.js.map +1 -1
- package/dist/st/wasm.js +1 -1
- package/dist/st/workers/{Cargo-DC6jSekr-BG7C7m56.js → Cargo-CG4XszZo-S7EHAZSa.js} +1105 -763
- package/dist/st/workers/Cargo-CG4XszZo-S7EHAZSa.js.map +1 -0
- package/dist/st/workers/assets/miden_client_web.wasm +0 -0
- package/dist/st/workers/web-client-methods-worker.js +1134 -787
- package/dist/st/workers/web-client-methods-worker.js.map +1 -1
- package/dist/st/workers/web-client-methods-worker.module.js +23 -19
- package/dist/st/workers/web-client-methods-worker.module.js.map +1 -1
- package/js/client.js +491 -0
- package/js/node/client-factory.js +117 -0
- package/js/node/loader.js +138 -0
- package/js/node/napi-compat.js +253 -0
- package/js/node-index.js +194 -0
- package/js/resources/accounts.js +222 -0
- package/js/resources/compiler.js +74 -0
- package/js/resources/keystore.js +54 -0
- package/js/resources/notes.js +124 -0
- package/js/resources/settings.js +30 -0
- package/js/resources/tags.js +31 -0
- package/js/resources/transactions.js +667 -0
- package/js/standalone.js +109 -0
- package/js/utils.js +232 -0
- package/package.json +17 -2
- package/dist/mt/Cargo-CZopJ--X.js.map +0 -1
- package/dist/mt/workers/Cargo-CZopJ--X-SsyOTzpb.js.map +0 -1
- package/dist/st/Cargo-DC6jSekr.js.map +0 -1
- 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(¬e) 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
|
+
}
|