@provablehq/sdk 0.8.8 → 0.9.1
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/mainnet/browser.d.ts +2 -1
- package/dist/mainnet/browser.js +2 -2
- package/dist/mainnet/browser.js.map +1 -1
- package/dist/mainnet/models/imports.d.ts +7 -0
- package/dist/mainnet/network-client.d.ts +44 -2
- package/dist/mainnet/node.js +1 -1
- package/dist/mainnet/{program-manager-OK_mdi-y.js → program-manager-DMDKstZ8.js} +419 -61
- package/dist/mainnet/program-manager-DMDKstZ8.js.map +1 -0
- package/dist/mainnet/program-manager.d.ts +63 -5
- package/dist/mainnet/utils.d.ts +10 -0
- package/dist/mainnet/worker.js +1 -1
- package/dist/testnet/browser.d.ts +2 -1
- package/dist/testnet/browser.js +2 -2
- package/dist/testnet/browser.js.map +1 -1
- package/dist/testnet/models/imports.d.ts +7 -0
- package/dist/testnet/network-client.d.ts +44 -2
- package/dist/testnet/node.js +1 -1
- package/dist/testnet/{program-manager-BuK9g9xJ.js → program-manager-BTHjM8b7.js} +419 -61
- package/dist/testnet/program-manager-BTHjM8b7.js.map +1 -0
- package/dist/testnet/program-manager.d.ts +63 -5
- package/dist/testnet/utils.d.ts +10 -0
- package/dist/testnet/worker.js +1 -1
- package/package.json +2 -2
- package/dist/mainnet/program-manager-OK_mdi-y.js.map +0 -1
- package/dist/testnet/program-manager-BuK9g9xJ.js.map +0 -1
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
import { PrivateKey, RecordCiphertext, Program, Plaintext, Address, Transaction, Metadata, VerifyingKey, ProvingKey, ProgramManager as ProgramManager$1, RecordPlaintext, verifyFunctionExecution } from '@provablehq/wasm/testnet.js';
|
|
2
2
|
|
|
3
|
+
function detectBrowser() {
|
|
4
|
+
const userAgent = navigator.userAgent;
|
|
5
|
+
if (/chrome|crios|crmo/i.test(userAgent) && !/edge|edg|opr/i.test(userAgent)) {
|
|
6
|
+
return "chrome";
|
|
7
|
+
}
|
|
8
|
+
else if (/firefox|fxios/i.test(userAgent)) {
|
|
9
|
+
return "firefox";
|
|
10
|
+
}
|
|
11
|
+
else if (/safari/i.test(userAgent) && !/chrome|crios|crmo|android/i.test(userAgent)) {
|
|
12
|
+
return "safari";
|
|
13
|
+
}
|
|
14
|
+
else if (/edg/i.test(userAgent)) {
|
|
15
|
+
return "edge";
|
|
16
|
+
}
|
|
17
|
+
else if (/opr\//i.test(userAgent)) {
|
|
18
|
+
return "opera";
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
return "browser";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function environment() {
|
|
25
|
+
if ((typeof process !== 'undefined') &&
|
|
26
|
+
(process.release?.name === 'node')) {
|
|
27
|
+
return 'node';
|
|
28
|
+
}
|
|
29
|
+
else if (typeof window !== 'undefined') {
|
|
30
|
+
return detectBrowser();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
return 'unknown';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
3
36
|
function logAndThrow(message) {
|
|
4
37
|
console.error(message);
|
|
5
38
|
throw new Error(message);
|
|
@@ -30,6 +63,37 @@ async function post(url, options) {
|
|
|
30
63
|
}
|
|
31
64
|
return response;
|
|
32
65
|
}
|
|
66
|
+
async function retryWithBackoff(fn, { maxAttempts = 5, baseDelay = 100, jitter, retryOnStatus = [], shouldRetry, } = {}) {
|
|
67
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
68
|
+
try {
|
|
69
|
+
return await fn();
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
const isLast = attempt === maxAttempts;
|
|
73
|
+
const error = err;
|
|
74
|
+
let retryable = false;
|
|
75
|
+
if (typeof error.status === "number") {
|
|
76
|
+
if (error.status >= 500) {
|
|
77
|
+
retryable = true;
|
|
78
|
+
}
|
|
79
|
+
else if (error.status >= 400 && shouldRetry) {
|
|
80
|
+
retryable = shouldRetry(error);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if (shouldRetry) {
|
|
84
|
+
retryable = shouldRetry(error);
|
|
85
|
+
}
|
|
86
|
+
if (!retryable || isLast)
|
|
87
|
+
throw error;
|
|
88
|
+
const jitterAmount = jitter ?? baseDelay;
|
|
89
|
+
const actualJitter = Math.floor(Math.random() * jitterAmount);
|
|
90
|
+
const delay = baseDelay * 2 ** (attempt - 1) + actualJitter;
|
|
91
|
+
console.warn(`Retry ${attempt}/${maxAttempts} failed. Retrying in ${delay}ms...`);
|
|
92
|
+
await new Promise((res) => setTimeout(res, delay));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
throw new Error("retryWithBackoff: unreachable");
|
|
96
|
+
}
|
|
33
97
|
|
|
34
98
|
/**
|
|
35
99
|
* Client library that encapsulates REST calls to publicly exposed endpoints of Aleo nodes. The methods provided in this
|
|
@@ -48,15 +112,20 @@ class AleoNetworkClient {
|
|
|
48
112
|
host;
|
|
49
113
|
headers;
|
|
50
114
|
account;
|
|
115
|
+
ctx;
|
|
116
|
+
network;
|
|
51
117
|
constructor(host, options) {
|
|
52
118
|
this.host = host + "/testnet";
|
|
119
|
+
this.network = "testnet";
|
|
120
|
+
this.ctx = {};
|
|
53
121
|
if (options && options.headers) {
|
|
54
122
|
this.headers = options.headers;
|
|
55
123
|
}
|
|
56
124
|
else {
|
|
57
125
|
this.headers = {
|
|
58
126
|
// This is replaced by the actual version by a Rollup plugin
|
|
59
|
-
"X-Aleo-SDK-Version": "0.
|
|
127
|
+
"X-Aleo-SDK-Version": "0.9.1",
|
|
128
|
+
"X-Aleo-environment": environment(),
|
|
60
129
|
};
|
|
61
130
|
}
|
|
62
131
|
}
|
|
@@ -101,6 +170,41 @@ class AleoNetworkClient {
|
|
|
101
170
|
setHost(host) {
|
|
102
171
|
this.host = host + "/testnet";
|
|
103
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Set a header in the `AleoNetworkClient`s header map
|
|
175
|
+
*
|
|
176
|
+
* @param {string} headerName The name of the header to set
|
|
177
|
+
* @param {string} value The header value
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* import { AleoNetworkClient } from "@provablehq/sdk/mainnet.js";
|
|
181
|
+
*
|
|
182
|
+
* // Create a networkClient
|
|
183
|
+
* const networkClient = new AleoNetworkClient();
|
|
184
|
+
*
|
|
185
|
+
* // Set the value of the `Accept-Language` header to `en-US`
|
|
186
|
+
* networkClient.setHeader('Accept-Language', 'en-US');
|
|
187
|
+
*/
|
|
188
|
+
setHeader(headerName, value) {
|
|
189
|
+
this.headers[headerName] = value;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Remove a header from the `AleoNetworkClient`s header map
|
|
193
|
+
*
|
|
194
|
+
* @param {string} headerName The name of the header to be removed
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* import { AleoNetworkClient } from "@provablehq/sdk/mainnet.js";
|
|
198
|
+
*
|
|
199
|
+
* // Create a networkClient
|
|
200
|
+
* const networkClient = new AleoNetworkClient();
|
|
201
|
+
*
|
|
202
|
+
* // Remove the default `X-Aleo-SDK-Version` header
|
|
203
|
+
* networkClient.removeHeader('X-Aleo-SDK-Version');
|
|
204
|
+
*/
|
|
205
|
+
removeHeader(headerName) {
|
|
206
|
+
delete this.headers[headerName];
|
|
207
|
+
}
|
|
104
208
|
/**
|
|
105
209
|
* Fetches data from the Aleo network and returns it as a JSON object.
|
|
106
210
|
*
|
|
@@ -108,7 +212,8 @@ class AleoNetworkClient {
|
|
|
108
212
|
*/
|
|
109
213
|
async fetchData(url = "/") {
|
|
110
214
|
try {
|
|
111
|
-
|
|
215
|
+
const raw = await this.fetchRaw(url);
|
|
216
|
+
return parseJSON(raw);
|
|
112
217
|
}
|
|
113
218
|
catch (error) {
|
|
114
219
|
throw new Error(`Error fetching data: ${error}`);
|
|
@@ -124,15 +229,31 @@ class AleoNetworkClient {
|
|
|
124
229
|
*/
|
|
125
230
|
async fetchRaw(url = "/") {
|
|
126
231
|
try {
|
|
127
|
-
const
|
|
128
|
-
|
|
232
|
+
const ctx = { ...this.ctx };
|
|
233
|
+
return await retryWithBackoff(async () => {
|
|
234
|
+
const response = await get(this.host + url, {
|
|
235
|
+
headers: {
|
|
236
|
+
...this.headers,
|
|
237
|
+
...ctx,
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
return await response.text();
|
|
129
241
|
});
|
|
130
|
-
return await response.text();
|
|
131
242
|
}
|
|
132
243
|
catch (error) {
|
|
133
244
|
throw new Error(`Error fetching data: ${error}`);
|
|
134
245
|
}
|
|
135
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Wrapper around the POST helper to allow mocking in tests. Not meant for use in production.
|
|
249
|
+
*
|
|
250
|
+
* @param url The URL to POST to.
|
|
251
|
+
* @param options The RequestInit options for the POST request.
|
|
252
|
+
* @returns The Response object from the POST request.
|
|
253
|
+
*/
|
|
254
|
+
async _sendPost(url, options) {
|
|
255
|
+
return post(url, options);
|
|
256
|
+
}
|
|
136
257
|
/**
|
|
137
258
|
* Attempt to find records in the Aleo blockchain.
|
|
138
259
|
*
|
|
@@ -190,7 +311,10 @@ class AleoNetworkClient {
|
|
|
190
311
|
}
|
|
191
312
|
else {
|
|
192
313
|
try {
|
|
193
|
-
resolvedPrivateKey =
|
|
314
|
+
resolvedPrivateKey =
|
|
315
|
+
privateKey instanceof PrivateKey
|
|
316
|
+
? privateKey
|
|
317
|
+
: PrivateKey.from_string(privateKey);
|
|
194
318
|
}
|
|
195
319
|
catch (error) {
|
|
196
320
|
throw new Error("Error parsing private key provided.");
|
|
@@ -241,8 +365,12 @@ class AleoNetworkClient {
|
|
|
241
365
|
// Search for unspent records in execute transactions of credits.aleo
|
|
242
366
|
if (confirmedTransaction.type == "execute") {
|
|
243
367
|
const transaction = confirmedTransaction.transaction;
|
|
244
|
-
if (transaction.execution &&
|
|
245
|
-
|
|
368
|
+
if (transaction.execution &&
|
|
369
|
+
!(typeof transaction.execution
|
|
370
|
+
.transitions == "undefined")) {
|
|
371
|
+
for (let k = 0; k <
|
|
372
|
+
transaction.execution.transitions
|
|
373
|
+
.length; k++) {
|
|
246
374
|
const transition = transaction.execution.transitions[k];
|
|
247
375
|
// Only search for unspent records in the specified programs.
|
|
248
376
|
if (!(typeof programs === "undefined")) {
|
|
@@ -250,7 +378,8 @@ class AleoNetworkClient {
|
|
|
250
378
|
continue;
|
|
251
379
|
}
|
|
252
380
|
}
|
|
253
|
-
if (!(typeof transition.outputs ==
|
|
381
|
+
if (!(typeof transition.outputs ==
|
|
382
|
+
"undefined")) {
|
|
254
383
|
for (let l = 0; l < transition.outputs.length; l++) {
|
|
255
384
|
const output = transition.outputs[l];
|
|
256
385
|
if (output.type === "record") {
|
|
@@ -271,7 +400,7 @@ class AleoNetworkClient {
|
|
|
271
400
|
const serialNumber = recordPlaintext.serialNumberString(resolvedPrivateKey, "credits.aleo", "credits");
|
|
272
401
|
// Attempt to see if the serial number is spent
|
|
273
402
|
try {
|
|
274
|
-
await this.getTransitionId(serialNumber);
|
|
403
|
+
await retryWithBackoff(() => this.getTransitionId(serialNumber));
|
|
275
404
|
continue;
|
|
276
405
|
}
|
|
277
406
|
catch (error) {
|
|
@@ -282,37 +411,47 @@ class AleoNetworkClient {
|
|
|
282
411
|
if (!amounts) {
|
|
283
412
|
records.push(recordPlaintext);
|
|
284
413
|
// If the user specified a maximum number of microcredits, check if the search has found enough
|
|
285
|
-
if (typeof maxMicrocredits ===
|
|
286
|
-
|
|
414
|
+
if (typeof maxMicrocredits ===
|
|
415
|
+
"number") {
|
|
416
|
+
totalRecordValue +=
|
|
417
|
+
recordPlaintext.microcredits();
|
|
287
418
|
// Exit if the search has found the amount specified
|
|
288
|
-
if (totalRecordValue >=
|
|
419
|
+
if (totalRecordValue >=
|
|
420
|
+
BigInt(maxMicrocredits)) {
|
|
289
421
|
return records;
|
|
290
422
|
}
|
|
291
423
|
}
|
|
292
424
|
}
|
|
293
425
|
// If the user specified a list of amounts, check if the search has found them
|
|
294
|
-
if (!(typeof amounts ===
|
|
426
|
+
if (!(typeof amounts ===
|
|
427
|
+
"undefined") &&
|
|
428
|
+
amounts.length >
|
|
429
|
+
0) {
|
|
295
430
|
let amounts_found = 0;
|
|
296
|
-
if (recordPlaintext.microcredits() >
|
|
431
|
+
if (recordPlaintext.microcredits() >
|
|
432
|
+
amounts[amounts_found]) {
|
|
297
433
|
amounts_found += 1;
|
|
298
434
|
records.push(recordPlaintext);
|
|
299
435
|
// If the user specified a maximum number of microcredits, check if the search has found enough
|
|
300
|
-
if (typeof maxMicrocredits ===
|
|
301
|
-
|
|
436
|
+
if (typeof maxMicrocredits ===
|
|
437
|
+
"number") {
|
|
438
|
+
totalRecordValue +=
|
|
439
|
+
recordPlaintext.microcredits();
|
|
302
440
|
// Exit if the search has found the amount specified
|
|
303
|
-
if (totalRecordValue >=
|
|
441
|
+
if (totalRecordValue >=
|
|
442
|
+
BigInt(maxMicrocredits)) {
|
|
304
443
|
return records;
|
|
305
444
|
}
|
|
306
445
|
}
|
|
307
|
-
if (records.length >=
|
|
446
|
+
if (records.length >=
|
|
447
|
+
amounts.length) {
|
|
308
448
|
return records;
|
|
309
449
|
}
|
|
310
450
|
}
|
|
311
451
|
}
|
|
312
452
|
}
|
|
313
453
|
}
|
|
314
|
-
catch (error) {
|
|
315
|
-
}
|
|
454
|
+
catch (error) { }
|
|
316
455
|
}
|
|
317
456
|
}
|
|
318
457
|
}
|
|
@@ -325,7 +464,10 @@ class AleoNetworkClient {
|
|
|
325
464
|
}
|
|
326
465
|
catch (error) {
|
|
327
466
|
// If there is an error fetching blocks, log it and keep searching
|
|
328
|
-
console.warn("Error fetching blocks in range: " +
|
|
467
|
+
console.warn("Error fetching blocks in range: " +
|
|
468
|
+
start.toString() +
|
|
469
|
+
"-" +
|
|
470
|
+
end.toString());
|
|
329
471
|
console.warn("Error: ", error);
|
|
330
472
|
failures += 1;
|
|
331
473
|
if (failures > 10) {
|
|
@@ -368,7 +510,16 @@ class AleoNetworkClient {
|
|
|
368
510
|
* const records = networkClient.findUnspentRecords(startHeight, undefined, ["credits.aleo"], undefined, maxMicrocredits);
|
|
369
511
|
*/
|
|
370
512
|
async findUnspentRecords(startHeight, endHeight, programs, amounts, maxMicrocredits, nonces, privateKey) {
|
|
371
|
-
|
|
513
|
+
try {
|
|
514
|
+
this.ctx = { "X-ALEO-METHOD": "findUnspentRecords" };
|
|
515
|
+
return await this.findRecords(startHeight, endHeight, true, programs, amounts, maxMicrocredits, nonces, privateKey);
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
throw new Error("Error finding unspent records: " + error);
|
|
519
|
+
}
|
|
520
|
+
finally {
|
|
521
|
+
this.ctx = {};
|
|
522
|
+
}
|
|
372
523
|
}
|
|
373
524
|
/**
|
|
374
525
|
* Returns the contents of the block at the specified block height.
|
|
@@ -381,12 +532,16 @@ class AleoNetworkClient {
|
|
|
381
532
|
*/
|
|
382
533
|
async getBlock(blockHeight) {
|
|
383
534
|
try {
|
|
535
|
+
this.ctx = { "X-ALEO-METHOD": "getBlock" };
|
|
384
536
|
const block = await this.fetchData("/block/" + blockHeight);
|
|
385
537
|
return block;
|
|
386
538
|
}
|
|
387
539
|
catch (error) {
|
|
388
540
|
throw new Error(`Error fetching block ${blockHeight}: ${error}`);
|
|
389
541
|
}
|
|
542
|
+
finally {
|
|
543
|
+
this.ctx = {};
|
|
544
|
+
}
|
|
390
545
|
}
|
|
391
546
|
/**
|
|
392
547
|
* Returns the contents of the block with the specified hash.
|
|
@@ -402,12 +557,16 @@ class AleoNetworkClient {
|
|
|
402
557
|
*/
|
|
403
558
|
async getBlockByHash(blockHash) {
|
|
404
559
|
try {
|
|
560
|
+
this.ctx = { "X-ALEO-METHOD": "getBlockByHash" };
|
|
405
561
|
const block = await this.fetchData(`/block/${blockHash}`);
|
|
406
562
|
return block;
|
|
407
563
|
}
|
|
408
564
|
catch (error) {
|
|
409
565
|
throw new Error(`Error fetching block ${blockHash}: ${error}`);
|
|
410
566
|
}
|
|
567
|
+
finally {
|
|
568
|
+
this.ctx = {};
|
|
569
|
+
}
|
|
411
570
|
}
|
|
412
571
|
/**
|
|
413
572
|
* Returns a range of blocks between the specified block heights. A maximum of 50 blocks can be fetched at a time.
|
|
@@ -431,11 +590,15 @@ class AleoNetworkClient {
|
|
|
431
590
|
*/
|
|
432
591
|
async getBlockRange(start, end) {
|
|
433
592
|
try {
|
|
593
|
+
this.ctx = { "X-ALEO-METHOD": "getBlockRange" };
|
|
434
594
|
return await this.fetchData("/blocks?start=" + start + "&end=" + end);
|
|
435
595
|
}
|
|
436
596
|
catch (error) {
|
|
437
597
|
throw new Error(`Error fetching blocks between ${start} and ${end}: ${error}`);
|
|
438
598
|
}
|
|
599
|
+
finally {
|
|
600
|
+
this.ctx = {};
|
|
601
|
+
}
|
|
439
602
|
}
|
|
440
603
|
/**
|
|
441
604
|
* Returns the deployment transaction id associated with the specified program.
|
|
@@ -457,16 +620,20 @@ class AleoNetworkClient {
|
|
|
457
620
|
* const verifyingKeys = transaction.verifyingKeys();
|
|
458
621
|
*/
|
|
459
622
|
async getDeploymentTransactionIDForProgram(program) {
|
|
623
|
+
this.ctx = { "X-ALEO-METHOD": "getDeploymentTransactionIDForProgram" };
|
|
460
624
|
if (program instanceof Program) {
|
|
461
625
|
program = program.id();
|
|
462
626
|
}
|
|
463
627
|
try {
|
|
464
628
|
const id = await this.fetchData("/find/transactionID/deployment/" + program);
|
|
465
|
-
return id.replace("
|
|
629
|
+
return id.replace('"', "");
|
|
466
630
|
}
|
|
467
631
|
catch (error) {
|
|
468
632
|
throw new Error(`Error fetching deployment transaction for program ${program}: ${error}`);
|
|
469
633
|
}
|
|
634
|
+
finally {
|
|
635
|
+
this.ctx = {};
|
|
636
|
+
}
|
|
470
637
|
}
|
|
471
638
|
/**
|
|
472
639
|
* Returns the deployment transaction associated with a specified program as a JSON object.
|
|
@@ -490,12 +657,16 @@ class AleoNetworkClient {
|
|
|
490
657
|
program = program.id();
|
|
491
658
|
}
|
|
492
659
|
try {
|
|
493
|
-
|
|
660
|
+
this.ctx = { "X-ALEO-METHOD": "getDeploymentTransactionForProgram" };
|
|
661
|
+
const transaction_id = (await this.getDeploymentTransactionIDForProgram(program));
|
|
494
662
|
return await this.getTransaction(transaction_id);
|
|
495
663
|
}
|
|
496
664
|
catch (error) {
|
|
497
665
|
throw new Error(`Error fetching deployment transaction for program ${program}: ${error}`);
|
|
498
666
|
}
|
|
667
|
+
finally {
|
|
668
|
+
this.ctx = {};
|
|
669
|
+
}
|
|
499
670
|
}
|
|
500
671
|
/**
|
|
501
672
|
* Returns the deployment transaction associated with a specified program as a wasm object.
|
|
@@ -518,12 +689,16 @@ class AleoNetworkClient {
|
|
|
518
689
|
*/
|
|
519
690
|
async getDeploymentTransactionObjectForProgram(program) {
|
|
520
691
|
try {
|
|
521
|
-
|
|
692
|
+
this.ctx = { "X-ALEO-METHOD": "getDeploymentTransactionObjectForProgram" };
|
|
693
|
+
const transaction_id = (await this.getDeploymentTransactionIDForProgram(program));
|
|
522
694
|
return await this.getTransactionObject(transaction_id);
|
|
523
695
|
}
|
|
524
696
|
catch (error) {
|
|
525
697
|
throw new Error(`Error fetching deployment transaction for program ${program}: ${error}`);
|
|
526
698
|
}
|
|
699
|
+
finally {
|
|
700
|
+
this.ctx = {};
|
|
701
|
+
}
|
|
527
702
|
}
|
|
528
703
|
/**
|
|
529
704
|
* Returns the contents of the latest block as JSON.
|
|
@@ -540,11 +715,15 @@ class AleoNetworkClient {
|
|
|
540
715
|
*/
|
|
541
716
|
async getLatestBlock() {
|
|
542
717
|
try {
|
|
543
|
-
|
|
718
|
+
this.ctx = { "X-ALEO-METHOD": "getLatestBlock" };
|
|
719
|
+
return (await this.fetchData("/block/latest"));
|
|
544
720
|
}
|
|
545
721
|
catch (error) {
|
|
546
722
|
throw new Error(`Error fetching latest block: ${error}`);
|
|
547
723
|
}
|
|
724
|
+
finally {
|
|
725
|
+
this.ctx = {};
|
|
726
|
+
}
|
|
548
727
|
}
|
|
549
728
|
/**
|
|
550
729
|
* Returns the latest committee.
|
|
@@ -563,11 +742,15 @@ class AleoNetworkClient {
|
|
|
563
742
|
*/
|
|
564
743
|
async getLatestCommittee() {
|
|
565
744
|
try {
|
|
745
|
+
this.ctx = { "X-ALEO-METHOD": "getLatestCommittee" };
|
|
566
746
|
return await this.fetchData("/committee/latest");
|
|
567
747
|
}
|
|
568
748
|
catch (error) {
|
|
569
749
|
throw new Error(`Error fetching latest committee: ${error}`);
|
|
570
750
|
}
|
|
751
|
+
finally {
|
|
752
|
+
this.ctx = {};
|
|
753
|
+
}
|
|
571
754
|
}
|
|
572
755
|
/**
|
|
573
756
|
* Returns the committee at the specified block height.
|
|
@@ -587,11 +770,15 @@ class AleoNetworkClient {
|
|
|
587
770
|
*/
|
|
588
771
|
async getCommitteeByBlockHeight(blockHeight) {
|
|
589
772
|
try {
|
|
773
|
+
this.ctx = { "X-ALEO-METHOD": "getCommitteeByBlockHeight" };
|
|
590
774
|
return await this.fetchData(`/committee/${blockHeight}`);
|
|
591
775
|
}
|
|
592
776
|
catch (error) {
|
|
593
777
|
throw new Error(`Error fetching committee at height ${blockHeight}: ${error}`);
|
|
594
778
|
}
|
|
779
|
+
finally {
|
|
780
|
+
this.ctx = {};
|
|
781
|
+
}
|
|
595
782
|
}
|
|
596
783
|
/**
|
|
597
784
|
* Returns the latest block height.
|
|
@@ -608,11 +795,15 @@ class AleoNetworkClient {
|
|
|
608
795
|
*/
|
|
609
796
|
async getLatestHeight() {
|
|
610
797
|
try {
|
|
798
|
+
this.ctx = { "X-ALEO-METHOD": "getLatestHeight" };
|
|
611
799
|
return Number(await this.fetchData("/block/height/latest"));
|
|
612
800
|
}
|
|
613
801
|
catch (error) {
|
|
614
802
|
throw new Error(`Error fetching latest height: ${error}`);
|
|
615
803
|
}
|
|
804
|
+
finally {
|
|
805
|
+
this.ctx = {};
|
|
806
|
+
}
|
|
616
807
|
}
|
|
617
808
|
/**
|
|
618
809
|
* Returns the latest block hash.
|
|
@@ -630,11 +821,15 @@ class AleoNetworkClient {
|
|
|
630
821
|
*/
|
|
631
822
|
async getLatestBlockHash() {
|
|
632
823
|
try {
|
|
824
|
+
this.ctx = { "X-ALEO-METHOD": "getLatestBlockHash" };
|
|
633
825
|
return String(await this.fetchData("/block/hash/latest"));
|
|
634
826
|
}
|
|
635
827
|
catch (error) {
|
|
636
828
|
throw new Error(`Error fetching latest hash: ${error}`);
|
|
637
829
|
}
|
|
830
|
+
finally {
|
|
831
|
+
this.ctx = {};
|
|
832
|
+
}
|
|
638
833
|
}
|
|
639
834
|
/**
|
|
640
835
|
* Returns the source code of a program given a program ID.
|
|
@@ -654,11 +849,15 @@ class AleoNetworkClient {
|
|
|
654
849
|
*/
|
|
655
850
|
async getProgram(programId) {
|
|
656
851
|
try {
|
|
852
|
+
this.ctx = { "X-ALEO-METHOD": "getProgram" };
|
|
657
853
|
return await this.fetchData("/program/" + programId);
|
|
658
854
|
}
|
|
659
855
|
catch (error) {
|
|
660
856
|
throw new Error(`Error fetching program ${programId}: ${error}`);
|
|
661
857
|
}
|
|
858
|
+
finally {
|
|
859
|
+
this.ctx = {};
|
|
860
|
+
}
|
|
662
861
|
}
|
|
663
862
|
/**
|
|
664
863
|
* Returns a program object from a program ID or program source code.
|
|
@@ -684,16 +883,20 @@ class AleoNetworkClient {
|
|
|
684
883
|
*/
|
|
685
884
|
async getProgramObject(inputProgram) {
|
|
686
885
|
try {
|
|
886
|
+
this.ctx = { "X-ALEO-METHOD": "getProgramObject" };
|
|
687
887
|
return Program.fromString(inputProgram);
|
|
688
888
|
}
|
|
689
889
|
catch (error) {
|
|
690
890
|
try {
|
|
691
|
-
return Program.fromString(
|
|
891
|
+
return Program.fromString(await this.getProgram(inputProgram));
|
|
692
892
|
}
|
|
693
893
|
catch (error) {
|
|
694
894
|
throw new Error(`${inputProgram} is neither a program name or a valid program: ${error}`);
|
|
695
895
|
}
|
|
696
896
|
}
|
|
897
|
+
finally {
|
|
898
|
+
this.ctx = {};
|
|
899
|
+
}
|
|
697
900
|
}
|
|
698
901
|
/**
|
|
699
902
|
* Returns an object containing the source code of a program and the source code of all programs it imports
|
|
@@ -727,17 +930,20 @@ class AleoNetworkClient {
|
|
|
727
930
|
*/
|
|
728
931
|
async getProgramImports(inputProgram) {
|
|
729
932
|
try {
|
|
933
|
+
this.ctx = { "X-ALEO-METHOD": "getProgramImports" };
|
|
730
934
|
const imports = {};
|
|
731
935
|
// Get the program object or fail if the program is not valid or does not exist
|
|
732
|
-
const program = inputProgram instanceof Program
|
|
936
|
+
const program = inputProgram instanceof Program
|
|
937
|
+
? inputProgram
|
|
938
|
+
: await this.getProgramObject(inputProgram);
|
|
733
939
|
// Get the list of programs that the program imports
|
|
734
940
|
const importList = program.getImports();
|
|
735
941
|
// Recursively get any imports that the imported programs have in a depth first search order
|
|
736
942
|
for (let i = 0; i < importList.length; i++) {
|
|
737
943
|
const import_id = importList[i];
|
|
738
944
|
if (!imports.hasOwnProperty(import_id)) {
|
|
739
|
-
const programSource = await this.getProgram(import_id);
|
|
740
|
-
const nestedImports = await this.getProgramImports(import_id);
|
|
945
|
+
const programSource = (await this.getProgram(import_id));
|
|
946
|
+
const nestedImports = (await this.getProgramImports(import_id));
|
|
741
947
|
for (const key in nestedImports) {
|
|
742
948
|
if (!imports.hasOwnProperty(key)) {
|
|
743
949
|
imports[key] = nestedImports[key];
|
|
@@ -751,6 +957,9 @@ class AleoNetworkClient {
|
|
|
751
957
|
catch (error) {
|
|
752
958
|
logAndThrow("Error fetching program imports: " + error.message);
|
|
753
959
|
}
|
|
960
|
+
finally {
|
|
961
|
+
this.ctx = {};
|
|
962
|
+
}
|
|
754
963
|
}
|
|
755
964
|
/**
|
|
756
965
|
* Get a list of the program names that a program imports.
|
|
@@ -770,12 +979,18 @@ class AleoNetworkClient {
|
|
|
770
979
|
*/
|
|
771
980
|
async getProgramImportNames(inputProgram) {
|
|
772
981
|
try {
|
|
773
|
-
|
|
982
|
+
this.ctx = { "X-ALEO-METHOD": "getProgramImportNames" };
|
|
983
|
+
const program = inputProgram instanceof Program
|
|
984
|
+
? inputProgram
|
|
985
|
+
: await this.getProgramObject(inputProgram);
|
|
774
986
|
return program.getImports();
|
|
775
987
|
}
|
|
776
988
|
catch (error) {
|
|
777
989
|
throw new Error(`Error fetching imports for program ${inputProgram instanceof Program ? inputProgram.id() : inputProgram}: ${error.message}`);
|
|
778
990
|
}
|
|
991
|
+
finally {
|
|
992
|
+
this.ctx = {};
|
|
993
|
+
}
|
|
779
994
|
}
|
|
780
995
|
/**
|
|
781
996
|
* Returns the names of the mappings of a program.
|
|
@@ -803,11 +1018,15 @@ class AleoNetworkClient {
|
|
|
803
1018
|
*/
|
|
804
1019
|
async getProgramMappingNames(programId) {
|
|
805
1020
|
try {
|
|
1021
|
+
this.ctx = { "X-ALEO-METHOD": "getProgramMappingNames" };
|
|
806
1022
|
return await this.fetchData(`/program/${programId}/mappings`);
|
|
807
1023
|
}
|
|
808
1024
|
catch (error) {
|
|
809
1025
|
throw new Error(`Error fetching mappings for program ${programId} - ensure the program exists on chain before trying again`);
|
|
810
1026
|
}
|
|
1027
|
+
finally {
|
|
1028
|
+
this.ctx = {};
|
|
1029
|
+
}
|
|
811
1030
|
}
|
|
812
1031
|
/**
|
|
813
1032
|
* Returns the value of a program's mapping for a specific key.
|
|
@@ -830,12 +1049,16 @@ class AleoNetworkClient {
|
|
|
830
1049
|
*/
|
|
831
1050
|
async getProgramMappingValue(programId, mappingName, key) {
|
|
832
1051
|
try {
|
|
1052
|
+
this.ctx = { "X-ALEO-METHOD": "getProgramMappingValue" };
|
|
833
1053
|
const keyString = key instanceof Plaintext ? key.toString() : key;
|
|
834
1054
|
return await this.fetchData(`/program/${programId}/mapping/${mappingName}/${keyString}`);
|
|
835
1055
|
}
|
|
836
1056
|
catch (error) {
|
|
837
1057
|
throw new Error(`Error fetching value for key '${key}' in mapping '${mappingName}' in program '${programId}' - ensure the mapping exists and the key is correct`);
|
|
838
1058
|
}
|
|
1059
|
+
finally {
|
|
1060
|
+
this.ctx = {};
|
|
1061
|
+
}
|
|
839
1062
|
}
|
|
840
1063
|
/**
|
|
841
1064
|
* Returns the value of a mapping as a wasm Plaintext object. Returning an object in this format allows it to be converted to a Js type and for its internal members to be inspected if it's a struct or array.
|
|
@@ -873,6 +1096,7 @@ class AleoNetworkClient {
|
|
|
873
1096
|
*/
|
|
874
1097
|
async getProgramMappingPlaintext(programId, mappingName, key) {
|
|
875
1098
|
try {
|
|
1099
|
+
this.ctx = { "X-ALEO-METHOD": "getProgramMappingPlaintext" };
|
|
876
1100
|
const keyString = key instanceof Plaintext ? key.toString() : key;
|
|
877
1101
|
const value = await this.fetchRaw(`/program/${programId}/mapping/${mappingName}/${keyString}`);
|
|
878
1102
|
return Plaintext.fromString(JSON.parse(value));
|
|
@@ -880,6 +1104,9 @@ class AleoNetworkClient {
|
|
|
880
1104
|
catch (error) {
|
|
881
1105
|
throw new Error("Failed to fetch mapping value." + error);
|
|
882
1106
|
}
|
|
1107
|
+
finally {
|
|
1108
|
+
this.ctx = {};
|
|
1109
|
+
}
|
|
883
1110
|
}
|
|
884
1111
|
/**
|
|
885
1112
|
* Returns the public balance of an address from the account mapping in credits.aleo
|
|
@@ -901,13 +1128,17 @@ class AleoNetworkClient {
|
|
|
901
1128
|
*/
|
|
902
1129
|
async getPublicBalance(address) {
|
|
903
1130
|
try {
|
|
1131
|
+
this.ctx = { "X-ALEO-METHOD": "getPublicBalance" };
|
|
904
1132
|
const addressString = address instanceof Address ? address.to_string() : address;
|
|
905
|
-
const balanceStr = await this.getProgramMappingValue(
|
|
1133
|
+
const balanceStr = await this.getProgramMappingValue("credits.aleo", "account", addressString);
|
|
906
1134
|
return balanceStr ? parseInt(balanceStr) : 0;
|
|
907
1135
|
}
|
|
908
1136
|
catch (error) {
|
|
909
1137
|
throw new Error(`Error fetching public balance for ${address}: ${error}`);
|
|
910
1138
|
}
|
|
1139
|
+
finally {
|
|
1140
|
+
this.ctx = {};
|
|
1141
|
+
}
|
|
911
1142
|
}
|
|
912
1143
|
/**
|
|
913
1144
|
* Returns the latest state/merkle root of the Aleo blockchain.
|
|
@@ -925,11 +1156,15 @@ class AleoNetworkClient {
|
|
|
925
1156
|
*/
|
|
926
1157
|
async getStateRoot() {
|
|
927
1158
|
try {
|
|
928
|
-
|
|
1159
|
+
this.ctx = { "X-ALEO-METHOD": "getStateRoot" };
|
|
1160
|
+
return await this.fetchData("/stateRoot/latest");
|
|
929
1161
|
}
|
|
930
1162
|
catch (error) {
|
|
931
1163
|
throw new Error(`Error fetching latest state root: ${error}`);
|
|
932
1164
|
}
|
|
1165
|
+
finally {
|
|
1166
|
+
this.ctx = {};
|
|
1167
|
+
}
|
|
933
1168
|
}
|
|
934
1169
|
/**
|
|
935
1170
|
* Returns a transaction by its unique identifier.
|
|
@@ -947,11 +1182,15 @@ class AleoNetworkClient {
|
|
|
947
1182
|
*/
|
|
948
1183
|
async getTransaction(transactionId) {
|
|
949
1184
|
try {
|
|
1185
|
+
this.ctx = { "X-ALEO-METHOD": "getTransaction" };
|
|
950
1186
|
return await this.fetchData("/transaction/" + transactionId);
|
|
951
1187
|
}
|
|
952
1188
|
catch (error) {
|
|
953
1189
|
throw new Error(`Error fetching transaction ${transactionId}: ${error}`);
|
|
954
1190
|
}
|
|
1191
|
+
finally {
|
|
1192
|
+
this.ctx = {};
|
|
1193
|
+
}
|
|
955
1194
|
}
|
|
956
1195
|
/**
|
|
957
1196
|
* Returns a confirmed transaction by its unique identifier.
|
|
@@ -970,11 +1209,15 @@ class AleoNetworkClient {
|
|
|
970
1209
|
*/
|
|
971
1210
|
async getConfirmedTransaction(transactionId) {
|
|
972
1211
|
try {
|
|
1212
|
+
this.ctx = { "X-ALEO-METHOD": "getConfirmedTransaction" };
|
|
973
1213
|
return await this.fetchData(`/transaction/confirmed/${transactionId}`);
|
|
974
1214
|
}
|
|
975
1215
|
catch (error) {
|
|
976
1216
|
throw new Error(`Error fetching confirmed transaction ${transactionId}: ${error}`);
|
|
977
1217
|
}
|
|
1218
|
+
finally {
|
|
1219
|
+
this.ctx = {};
|
|
1220
|
+
}
|
|
978
1221
|
}
|
|
979
1222
|
/**
|
|
980
1223
|
* Returns a transaction as a wasm object. Getting a transaction of this type will allow the ability for the inputs,
|
|
@@ -1003,12 +1246,16 @@ class AleoNetworkClient {
|
|
|
1003
1246
|
*/
|
|
1004
1247
|
async getTransactionObject(transactionId) {
|
|
1005
1248
|
try {
|
|
1249
|
+
this.ctx = { "X-ALEO-METHOD": "getTransactionObject" };
|
|
1006
1250
|
const transaction = await this.fetchRaw("/transaction/" + transactionId);
|
|
1007
1251
|
return Transaction.fromString(transaction);
|
|
1008
1252
|
}
|
|
1009
1253
|
catch (error) {
|
|
1010
1254
|
throw new Error(`Error fetching transaction object ${transactionId}: ${error}`);
|
|
1011
1255
|
}
|
|
1256
|
+
finally {
|
|
1257
|
+
this.ctx = {};
|
|
1258
|
+
}
|
|
1012
1259
|
}
|
|
1013
1260
|
/**
|
|
1014
1261
|
* Returns the transactions present at the specified block height.
|
|
@@ -1026,11 +1273,15 @@ class AleoNetworkClient {
|
|
|
1026
1273
|
*/
|
|
1027
1274
|
async getTransactions(blockHeight) {
|
|
1028
1275
|
try {
|
|
1276
|
+
this.ctx = { "X-ALEO-METHOD": "getTransactions" };
|
|
1029
1277
|
return await this.fetchData("/block/" + blockHeight.toString() + "/transactions");
|
|
1030
1278
|
}
|
|
1031
1279
|
catch (error) {
|
|
1032
1280
|
throw new Error(`Error fetching transactions: ${error}`);
|
|
1033
1281
|
}
|
|
1282
|
+
finally {
|
|
1283
|
+
this.ctx = {};
|
|
1284
|
+
}
|
|
1034
1285
|
}
|
|
1035
1286
|
/**
|
|
1036
1287
|
* Returns the confirmed transactions present in the block with the specified block hash.
|
|
@@ -1048,6 +1299,7 @@ class AleoNetworkClient {
|
|
|
1048
1299
|
*/
|
|
1049
1300
|
async getTransactionsByBlockHash(blockHash) {
|
|
1050
1301
|
try {
|
|
1302
|
+
this.ctx = { "X-ALEO-METHOD": "getTransactionsByBlockHash" };
|
|
1051
1303
|
const block = await this.fetchData(`/block/${blockHash}`);
|
|
1052
1304
|
const height = block.header.metadata.height;
|
|
1053
1305
|
return await this.getTransactions(Number(height));
|
|
@@ -1055,6 +1307,9 @@ class AleoNetworkClient {
|
|
|
1055
1307
|
catch (error) {
|
|
1056
1308
|
throw new Error(`Error fetching transactions for block ${blockHash}: ${error}`);
|
|
1057
1309
|
}
|
|
1310
|
+
finally {
|
|
1311
|
+
this.ctx = {};
|
|
1312
|
+
}
|
|
1058
1313
|
}
|
|
1059
1314
|
/**
|
|
1060
1315
|
* Returns the transactions in the memory pool. This method requires access to a validator's REST API.
|
|
@@ -1072,11 +1327,15 @@ class AleoNetworkClient {
|
|
|
1072
1327
|
*/
|
|
1073
1328
|
async getTransactionsInMempool() {
|
|
1074
1329
|
try {
|
|
1330
|
+
this.ctx = { "X-ALEO-METHOD": "getTransactionsInMempool" };
|
|
1075
1331
|
return await this.fetchData("/memoryPool/transactions");
|
|
1076
1332
|
}
|
|
1077
1333
|
catch (error) {
|
|
1078
1334
|
throw new Error(`Error fetching transactions from mempool: ${error}`);
|
|
1079
1335
|
}
|
|
1336
|
+
finally {
|
|
1337
|
+
this.ctx = {};
|
|
1338
|
+
}
|
|
1080
1339
|
}
|
|
1081
1340
|
/**
|
|
1082
1341
|
* Returns the transition ID of the transition corresponding to the ID of the input or output.
|
|
@@ -1088,11 +1347,15 @@ class AleoNetworkClient {
|
|
|
1088
1347
|
*/
|
|
1089
1348
|
async getTransitionId(inputOrOutputID) {
|
|
1090
1349
|
try {
|
|
1350
|
+
this.ctx = { "X-ALEO-METHOD": "getTransitionId" };
|
|
1091
1351
|
return await this.fetchData("/find/transitionID/" + inputOrOutputID);
|
|
1092
1352
|
}
|
|
1093
1353
|
catch (error) {
|
|
1094
1354
|
throw new Error(`Error fetching transition ID for input/output ${inputOrOutputID}: ${error}`);
|
|
1095
1355
|
}
|
|
1356
|
+
finally {
|
|
1357
|
+
this.ctx = {};
|
|
1358
|
+
}
|
|
1096
1359
|
}
|
|
1097
1360
|
/**
|
|
1098
1361
|
* Submit an execute or deployment transaction to the Aleo network.
|
|
@@ -1101,14 +1364,16 @@ class AleoNetworkClient {
|
|
|
1101
1364
|
* @returns {Promise<string>} - The transaction id of the submitted transaction or the resulting error
|
|
1102
1365
|
*/
|
|
1103
1366
|
async submitTransaction(transaction) {
|
|
1104
|
-
const
|
|
1367
|
+
const transactionString = transaction instanceof Transaction
|
|
1368
|
+
? transaction.toString()
|
|
1369
|
+
: transaction;
|
|
1105
1370
|
try {
|
|
1106
|
-
const response = await
|
|
1107
|
-
body:
|
|
1108
|
-
headers: Object.assign({}, this.headers, {
|
|
1371
|
+
const response = await retryWithBackoff(() => this._sendPost(this.host + "/transaction/broadcast", {
|
|
1372
|
+
body: transactionString,
|
|
1373
|
+
headers: Object.assign({}, { ...this.headers, "X-ALEO-METHOD": "submitTransaction" }, {
|
|
1109
1374
|
"Content-Type": "application/json",
|
|
1110
1375
|
}),
|
|
1111
|
-
});
|
|
1376
|
+
}));
|
|
1112
1377
|
try {
|
|
1113
1378
|
const text = await response.text();
|
|
1114
1379
|
return parseJSON(text);
|
|
@@ -1129,22 +1394,22 @@ class AleoNetworkClient {
|
|
|
1129
1394
|
*/
|
|
1130
1395
|
async submitSolution(solution) {
|
|
1131
1396
|
try {
|
|
1132
|
-
const response = await post(this.host + "/solution/broadcast", {
|
|
1397
|
+
const response = await retryWithBackoff(() => post(this.host + "/solution/broadcast", {
|
|
1133
1398
|
body: solution,
|
|
1134
|
-
headers: Object.assign({}, this.headers, {
|
|
1399
|
+
headers: Object.assign({}, { ...this.headers, "X-ALEO-METHOD": "submitSolution" }, {
|
|
1135
1400
|
"Content-Type": "application/json",
|
|
1136
1401
|
}),
|
|
1137
|
-
});
|
|
1402
|
+
}));
|
|
1138
1403
|
try {
|
|
1139
1404
|
const text = await response.text();
|
|
1140
1405
|
return parseJSON(text);
|
|
1141
1406
|
}
|
|
1142
1407
|
catch (error) {
|
|
1143
|
-
throw new Error(`Error posting
|
|
1408
|
+
throw new Error(`Error posting solution. Aleo network response: ${error.message}`);
|
|
1144
1409
|
}
|
|
1145
1410
|
}
|
|
1146
1411
|
catch (error) {
|
|
1147
|
-
throw new Error(`Error posting
|
|
1412
|
+
throw new Error(`Error posting solution: No response received: ${error.message}`);
|
|
1148
1413
|
}
|
|
1149
1414
|
}
|
|
1150
1415
|
/**
|
|
@@ -1174,23 +1439,55 @@ class AleoNetworkClient {
|
|
|
1174
1439
|
* // Wait for the transaction to be confirmed.
|
|
1175
1440
|
* const transaction = await networkClient.waitForTransactionConfirmation(transactionId);
|
|
1176
1441
|
*/
|
|
1177
|
-
async waitForTransactionConfirmation(transactionId, checkInterval = 2000,
|
|
1178
|
-
timeout = 45000 // Timeout after 45 seconds
|
|
1179
|
-
) {
|
|
1442
|
+
async waitForTransactionConfirmation(transactionId, checkInterval = 2000, timeout = 45000) {
|
|
1180
1443
|
const startTime = Date.now();
|
|
1181
1444
|
return new Promise((resolve, reject) => {
|
|
1182
1445
|
const interval = setInterval(async () => {
|
|
1446
|
+
const elapsed = Date.now() - startTime;
|
|
1447
|
+
if (elapsed > timeout) {
|
|
1448
|
+
clearInterval(interval);
|
|
1449
|
+
return reject(new Error(`Transaction ${transactionId} did not appear after the timeout period of ${interval}ms - consider resubmitting the transaction`));
|
|
1450
|
+
}
|
|
1183
1451
|
try {
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1452
|
+
const res = await fetch(`${this.host}/transaction/confirmed/${transactionId}`, {
|
|
1453
|
+
headers: {
|
|
1454
|
+
...this.headers,
|
|
1455
|
+
"X-ALEO-METHOD": "waitForTransactionConfirmation",
|
|
1456
|
+
},
|
|
1457
|
+
});
|
|
1458
|
+
if (!res.ok) {
|
|
1459
|
+
let text = "";
|
|
1460
|
+
try {
|
|
1461
|
+
text = await res.text();
|
|
1462
|
+
console.warn("Response text from server:", text);
|
|
1463
|
+
}
|
|
1464
|
+
catch (err) {
|
|
1465
|
+
console.warn("Failed to read response text:", err);
|
|
1466
|
+
}
|
|
1467
|
+
// If the transaction ID is malformed (e.g. invalid checksum, wrong length),
|
|
1468
|
+
// the API returns a 4XX with "Invalid URL" — we treat this as a fatal error and stop polling.
|
|
1469
|
+
if (res.status >= 400 &&
|
|
1470
|
+
res.status < 500 &&
|
|
1471
|
+
text.includes("Invalid URL")) {
|
|
1472
|
+
clearInterval(interval);
|
|
1473
|
+
return reject(new Error(`Malformed transaction ID: ${text}`));
|
|
1474
|
+
}
|
|
1475
|
+
// Log and continue polling for 404s or 5XX errors in case a tx doesn't exist yet
|
|
1476
|
+
console.warn("Non-OK response (retrying):", res.status, text);
|
|
1477
|
+
return;
|
|
1478
|
+
}
|
|
1479
|
+
const data = parseJSON(await res.text());
|
|
1480
|
+
if (data?.status === "accepted") {
|
|
1188
1481
|
clearInterval(interval);
|
|
1189
|
-
|
|
1482
|
+
return resolve(data);
|
|
1483
|
+
}
|
|
1484
|
+
if (data?.status === "rejected") {
|
|
1485
|
+
clearInterval(interval);
|
|
1486
|
+
return reject(new Error(`Transaction ${transactionId} was rejected by the network. Ensure that the account paying the fee has enough credits and that the inputs to the on-chain function are valid.`));
|
|
1190
1487
|
}
|
|
1191
1488
|
}
|
|
1192
|
-
catch (
|
|
1193
|
-
console.error("
|
|
1489
|
+
catch (err) {
|
|
1490
|
+
console.error("Polling error:", err);
|
|
1194
1491
|
}
|
|
1195
1492
|
}, checkInterval);
|
|
1196
1493
|
});
|
|
@@ -1709,9 +2006,9 @@ class ProgramManager {
|
|
|
1709
2006
|
* @param { FunctionKeyProvider | undefined } keyProvider A key provider that implements {@link FunctionKeyProvider} interface
|
|
1710
2007
|
* @param { RecordProvider | undefined } recordProvider A record provider that implements {@link RecordProvider} interface
|
|
1711
2008
|
*/
|
|
1712
|
-
constructor(host, keyProvider, recordProvider) {
|
|
2009
|
+
constructor(host, keyProvider, recordProvider, networkClientOptions) {
|
|
1713
2010
|
this.host = host ? host : "https://api.explorer.provable.com/v1";
|
|
1714
|
-
this.networkClient = new AleoNetworkClient(this.host);
|
|
2011
|
+
this.networkClient = new AleoNetworkClient(this.host, networkClientOptions);
|
|
1715
2012
|
this.keyProvider = keyProvider ? keyProvider : new AleoKeyProvider();
|
|
1716
2013
|
this.recordProvider = recordProvider;
|
|
1717
2014
|
}
|
|
@@ -1757,6 +2054,41 @@ class ProgramManager {
|
|
|
1757
2054
|
setRecordProvider(recordProvider) {
|
|
1758
2055
|
this.recordProvider = recordProvider;
|
|
1759
2056
|
}
|
|
2057
|
+
/**
|
|
2058
|
+
* Set a header in the `AleoNetworkClient`s header map
|
|
2059
|
+
*
|
|
2060
|
+
* @param {string} headerName The name of the header to set
|
|
2061
|
+
* @param {string} value The header value
|
|
2062
|
+
*
|
|
2063
|
+
* @example
|
|
2064
|
+
* import { ProgramManager } from "@provablehq/sdk/mainnet.js";
|
|
2065
|
+
*
|
|
2066
|
+
* // Create a ProgramManager
|
|
2067
|
+
* const programManager = new ProgramManager("https://api.explorer.provable.com/v1");
|
|
2068
|
+
*
|
|
2069
|
+
* // Set the value of the `Accept-Language` header to `en-US`
|
|
2070
|
+
* programManager.setHeader('Accept-Language', 'en-US');
|
|
2071
|
+
*/
|
|
2072
|
+
setHeader(headerName, value) {
|
|
2073
|
+
this.networkClient.headers[headerName] = value;
|
|
2074
|
+
}
|
|
2075
|
+
/**
|
|
2076
|
+
* Remove a header from the `AleoNetworkClient`s header map
|
|
2077
|
+
*
|
|
2078
|
+
* @param {string} headerName The name of the header to be removed
|
|
2079
|
+
*
|
|
2080
|
+
* @example
|
|
2081
|
+
* import { ProgramManager } from "@provablehq/sdk/mainnet.js";
|
|
2082
|
+
*
|
|
2083
|
+
* // Create a ProgramManager
|
|
2084
|
+
* const programManager = new ProgramManager("https://api.explorer.provable.com/v1");
|
|
2085
|
+
*
|
|
2086
|
+
* // Remove the default `X-Aleo-SDK-Version` header
|
|
2087
|
+
* programManager.removeHeader('X-Aleo-SDK-Version');
|
|
2088
|
+
*/
|
|
2089
|
+
removeHeader(headerName) {
|
|
2090
|
+
delete this.networkClient.headers[headerName];
|
|
2091
|
+
}
|
|
1760
2092
|
/**
|
|
1761
2093
|
* Builds a deployment transaction for submission to the Aleo network.
|
|
1762
2094
|
*
|
|
@@ -3018,18 +3350,44 @@ class ProgramManager {
|
|
|
3018
3350
|
return this.networkClient.submitTransaction(tx);
|
|
3019
3351
|
}
|
|
3020
3352
|
/**
|
|
3021
|
-
* Verify a proof
|
|
3353
|
+
* Verify a proof from an offline execution. This is useful when it is desired to do offchain proving and verification.
|
|
3022
3354
|
*
|
|
3023
|
-
* @param {executionResponse} executionResponse
|
|
3355
|
+
* @param {executionResponse} executionResponse The response from an offline function execution (via the `programManager.run` method)
|
|
3356
|
+
* @param {ImportedPrograms} imports The imported programs used in the execution. Specified as { "programName": "programSourceCode", ... }
|
|
3357
|
+
* @param {ImportedVerifyingKeys} importedVerifyingKeys The verifying keys in the execution. Specified as { "programName": [["functionName", "verifyingKey"], ...], ... }
|
|
3024
3358
|
* @returns {boolean} True if the proof is valid, false otherwise
|
|
3359
|
+
*
|
|
3360
|
+
* @example
|
|
3361
|
+
* /// Import the mainnet version of the sdk used to build executions.
|
|
3362
|
+
* import { Account, ProgramManager } from "@provablehq/sdk/mainnet.js";
|
|
3363
|
+
*
|
|
3364
|
+
* /// Create the source for two programs.
|
|
3365
|
+
* const program = "import add_it_up.aleo; \n\n program mul_add.aleo;\n\nfunction mul_and_add:\n input r0 as u32.public;\n input r1 as u32.private;\n mul r0 r1 into r2;\n call add_it_up.aleo/add_it r1 r2 into r3; output r3 as u32.private;\n";
|
|
3366
|
+
* const program_import = "program add_it_up.aleo;\n\nfunction add_it:\n input r0 as u32.public;\n input r1 as u32.private;\n add r0 r1 into r2;\n output r2 as u32.private;\n";
|
|
3367
|
+
* const programManager = new ProgramManager(undefined, undefined, undefined);
|
|
3368
|
+
*
|
|
3369
|
+
* /// Create a temporary account for the execution of the program
|
|
3370
|
+
* const account = Account.fromCipherText(process.env.ciphertext, process.env.password);
|
|
3371
|
+
* programManager.setAccount(account);
|
|
3372
|
+
*
|
|
3373
|
+
* /// Get the response and ensure that the program executed correctly
|
|
3374
|
+
* const executionResponse = await programManager.run(program, "mul_and_add", ["5u32", "5u32"], true);
|
|
3375
|
+
*
|
|
3376
|
+
* /// Construct the imports and verifying keys
|
|
3377
|
+
* const imports = { "add_it_up.aleo": program_import };
|
|
3378
|
+
* const importedVerifyingKeys = { "add_it_up.aleo": [["add_it", "verifyingKey1..."]] };
|
|
3379
|
+
*
|
|
3380
|
+
* /// Verify the execution.
|
|
3381
|
+
* const isValid = programManager.verifyExecution(executionResponse, imports, importedVerifyingKeys);
|
|
3382
|
+
* assert(isValid);
|
|
3025
3383
|
*/
|
|
3026
|
-
verifyExecution(executionResponse) {
|
|
3384
|
+
verifyExecution(executionResponse, imports, importedVerifyingKeys) {
|
|
3027
3385
|
try {
|
|
3028
3386
|
const execution = (executionResponse.getExecution());
|
|
3029
3387
|
const function_id = executionResponse.getFunctionId();
|
|
3030
3388
|
const program = executionResponse.getProgram();
|
|
3031
3389
|
const verifyingKey = executionResponse.getVerifyingKey();
|
|
3032
|
-
return verifyFunctionExecution(execution, verifyingKey, program, function_id);
|
|
3390
|
+
return verifyFunctionExecution(execution, verifyingKey, program, function_id, imports, importedVerifyingKeys);
|
|
3033
3391
|
}
|
|
3034
3392
|
catch (e) {
|
|
3035
3393
|
console.warn("The execution was not found in the response, cannot verify the execution");
|
|
@@ -3097,4 +3455,4 @@ function validateTransferType(transferType) {
|
|
|
3097
3455
|
}
|
|
3098
3456
|
|
|
3099
3457
|
export { AleoKeyProvider as A, CREDITS_PROGRAM_KEYS as C, KEY_STORE as K, ProgramManager as P, VALID_TRANSFER_TYPES as V, AleoKeyProviderParams as a, AleoNetworkClient as b, PRIVATE_TRANSFER as c, PRIVATE_TO_PUBLIC_TRANSFER as d, PRIVATE_TRANSFER_TYPES as e, PUBLIC_TRANSFER as f, PUBLIC_TRANSFER_AS_SIGNER as g, PUBLIC_TO_PRIVATE_TRANSFER as h, logAndThrow as l };
|
|
3100
|
-
//# sourceMappingURL=program-manager-
|
|
3458
|
+
//# sourceMappingURL=program-manager-BTHjM8b7.js.map
|