@provablehq/sdk 0.9.13 → 0.9.15-enc
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/account.d.ts +15 -0
- package/dist/mainnet/browser.d.ts +5 -2
- package/dist/mainnet/browser.js +669 -160
- package/dist/mainnet/browser.js.map +1 -1
- package/dist/mainnet/constants.d.ts +1 -0
- package/dist/mainnet/integrations/sealance/merkle-tree.d.ts +63 -17
- package/dist/mainnet/models/cryptoBoxPubkey.d.ts +4 -0
- package/dist/mainnet/models/encryptedProvingRequest.d.ts +4 -0
- package/dist/mainnet/models/provingResponse.d.ts +48 -2
- package/dist/mainnet/models/record-scanner/encryptedRegistrationRequest.d.ts +8 -0
- package/dist/mainnet/models/record-scanner/registrationResult.d.ts +26 -0
- package/dist/mainnet/network-client.d.ts +77 -4
- package/dist/mainnet/node-polyfill.js +2 -49
- package/dist/mainnet/node-polyfill.js.map +1 -1
- package/dist/mainnet/node.js +2 -2
- package/dist/mainnet/record-scanner.d.ts +53 -5
- package/dist/mainnet/security.d.ts +38 -0
- package/dist/testnet/account.d.ts +15 -0
- package/dist/testnet/browser.d.ts +5 -2
- package/dist/testnet/browser.js +669 -160
- package/dist/testnet/browser.js.map +1 -1
- package/dist/testnet/constants.d.ts +1 -0
- package/dist/testnet/integrations/sealance/merkle-tree.d.ts +63 -17
- package/dist/testnet/models/cryptoBoxPubkey.d.ts +4 -0
- package/dist/testnet/models/encryptedProvingRequest.d.ts +4 -0
- package/dist/testnet/models/provingResponse.d.ts +48 -2
- package/dist/testnet/models/record-scanner/encryptedRegistrationRequest.d.ts +8 -0
- package/dist/testnet/models/record-scanner/registrationResult.d.ts +26 -0
- package/dist/testnet/network-client.d.ts +77 -4
- package/dist/testnet/node-polyfill.js +2 -49
- package/dist/testnet/node-polyfill.js.map +1 -1
- package/dist/testnet/node.js +2 -2
- package/dist/testnet/record-scanner.d.ts +53 -5
- package/dist/testnet/security.d.ts +38 -0
- package/package.json +4 -4
package/dist/mainnet/browser.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import 'core-js/proposals/json-parse-with-source.js';
|
|
2
|
-
import { ViewKey, ComputeKey, Address, PrivateKeyCiphertext, PrivateKey, RecordCiphertext, EncryptionToolkit, Group, Program, Plaintext, Transaction, ProvingRequest,
|
|
2
|
+
import { ViewKey, ComputeKey, Address, PrivateKeyCiphertext, PrivateKey, RecordCiphertext, EncryptionToolkit, Group, Metadata, VerifyingKey, Program, Plaintext, Transaction, ProvingRequest, ProvingKey, RecordPlaintext, Field, Poseidon4, ProgramManager as ProgramManager$1, verifyFunctionExecution } from '@provablehq/wasm/mainnet.js';
|
|
3
3
|
export { Address, Authorization, BHP1024, BHP256, BHP512, BHP768, Boolean, Ciphertext, ComputeKey, EncryptionToolkit, ExecutionRequest, ExecutionResponse, Field, Execution as FunctionExecution, GraphKey, Group, I128, I16, I32, I64, I8, OfflineQuery, Pedersen128, Pedersen64, Plaintext, Poseidon2, Poseidon4, Poseidon8, PrivateKey, PrivateKeyCiphertext, Program, ProgramManager as ProgramManagerBase, ProvingKey, ProvingRequest, RecordCiphertext, RecordPlaintext, Scalar, Signature, Transaction, Transition, U128, U16, U32, U64, U8, VerifyingKey, ViewKey, getOrInitConsensusVersionTestHeights, initThreadPool, verifyFunctionExecution } from '@provablehq/wasm/mainnet.js';
|
|
4
|
+
import sodium from 'libsodium-wrappers';
|
|
4
5
|
import { bech32m } from '@scure/base';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -72,6 +73,23 @@ class Account {
|
|
|
72
73
|
throw new Error("Wrong password or invalid ciphertext");
|
|
73
74
|
}
|
|
74
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Validates whether the given input is a valid Aleo address.
|
|
78
|
+
* @param {string | Uint8Array} address The address to validate, either as a string or bytes
|
|
79
|
+
* @returns {boolean} True if the address is valid, false otherwise
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* import { Account } from "@provablehq/sdk/testnet.js";
|
|
83
|
+
*
|
|
84
|
+
* const isValid = Account.isValidAddress("aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px");
|
|
85
|
+
* console.log(isValid); // true
|
|
86
|
+
*
|
|
87
|
+
* const isInvalid = Account.isValidAddress("invalid_address");
|
|
88
|
+
* console.log(isInvalid); // false
|
|
89
|
+
*/
|
|
90
|
+
static isValidAddress(address) {
|
|
91
|
+
return Address.isValid(address);
|
|
92
|
+
}
|
|
75
93
|
/**
|
|
76
94
|
* Creates a PrivateKey from the provided parameters.
|
|
77
95
|
* @param {AccountParam} params The parameters containing either a private key string or a seed
|
|
@@ -466,6 +484,191 @@ async function retryWithBackoff(fn, { maxAttempts = 5, baseDelay = 100, jitter,
|
|
|
466
484
|
throw new Error("retryWithBackoff: unreachable");
|
|
467
485
|
}
|
|
468
486
|
|
|
487
|
+
/** Type guard: value is a ProvingResponse. */
|
|
488
|
+
function isProvingResponse(value) {
|
|
489
|
+
return (typeof value === "object" &&
|
|
490
|
+
value !== null &&
|
|
491
|
+
"transaction" in value &&
|
|
492
|
+
"broadcast_result" in value &&
|
|
493
|
+
typeof value.broadcast_result === "object");
|
|
494
|
+
}
|
|
495
|
+
/** Type guard: value is a ProveApiErrorBody. */
|
|
496
|
+
function isProveApiErrorBody(value) {
|
|
497
|
+
return (typeof value === "object" &&
|
|
498
|
+
value !== null &&
|
|
499
|
+
"message" in value);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
await sodium.ready;
|
|
503
|
+
/**
|
|
504
|
+
* Encrypt an authorization with a libsodium cryptobox public key.
|
|
505
|
+
*
|
|
506
|
+
* @param {string} publicKey The cryptobox X25519 public key to encrypt with (encoded in RFC 4648 standard Base64).
|
|
507
|
+
* @param {Authorization} authorization the authorization to encrypt.
|
|
508
|
+
*
|
|
509
|
+
* @returns {string} the encrypted authorization in RFC 4648 standard Base64.
|
|
510
|
+
*/
|
|
511
|
+
function encryptAuthorization(publicKey, authorization) {
|
|
512
|
+
// Ready the cryptobox lib.
|
|
513
|
+
return encryptMessage(publicKey, authorization.toBytesLe());
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Encrypt a ProvingRequest with a libsodium cryptobox public key.
|
|
517
|
+
*
|
|
518
|
+
* @param {string} publicKey The cryptobox X25519 public key to encrypt with (encoded in RFC 4648 standard Base64).
|
|
519
|
+
* @param {Authorization} provingRequest the ProvingRequest to encrypt.
|
|
520
|
+
*
|
|
521
|
+
* @returns {string} the encrypted ProvingRequest in RFC 4648 standard Base64.
|
|
522
|
+
*/
|
|
523
|
+
function encryptProvingRequest(publicKey, provingRequest) {
|
|
524
|
+
return encryptMessage(publicKey, provingRequest.toBytesLe());
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Encrypt a view key with a libsodium cryptobox public key.
|
|
528
|
+
*
|
|
529
|
+
* @param {string} publicKey The cryptobox X25519 public key to encrypt with (encoded in RFC 4648 standard Base64).
|
|
530
|
+
* @param {ViewKey} viewKey the view key to encrypt.
|
|
531
|
+
*
|
|
532
|
+
* @returns {string} the encrypted view key in RFC 4648 standard Base64.
|
|
533
|
+
*/
|
|
534
|
+
function encryptViewKey(publicKey, viewKey) {
|
|
535
|
+
return encryptMessage(publicKey, viewKey.toBytesLe());
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Encrypt a record scanner registration request.
|
|
539
|
+
*
|
|
540
|
+
* @param {string} publicKey The cryptobox X25519 public key to encrypt with (encoded in RFC 4648 standard Base64).
|
|
541
|
+
* @param {ViewKey} viewKey the view key to encrypt.
|
|
542
|
+
* @param {number} start the start height of the registration request.
|
|
543
|
+
*
|
|
544
|
+
* @returns {string} the encrypted view key in RFC 4648 standard Base64.
|
|
545
|
+
*/
|
|
546
|
+
function encryptRegistrationRequest(publicKey, viewKey, start) {
|
|
547
|
+
// Turn the view key into a Uint8Array.
|
|
548
|
+
const vk_bytes = viewKey.toBytesLe();
|
|
549
|
+
// Create a new array to hold the original bytes and the 4-byte start height.
|
|
550
|
+
const bytes = new Uint8Array(vk_bytes.length + 4);
|
|
551
|
+
// Copy existing bytes.
|
|
552
|
+
bytes.set(vk_bytes, 0);
|
|
553
|
+
// Write the 4-byte number in LE format at the end of the array.
|
|
554
|
+
const view = new DataView(bytes.buffer);
|
|
555
|
+
view.setUint32(vk_bytes.length, start, true);
|
|
556
|
+
// Encrypt the encoded bytes.
|
|
557
|
+
return encryptMessage(publicKey, bytes);
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Encrypt arbitrary bytes with a libsodium cryptobox public key.
|
|
561
|
+
*
|
|
562
|
+
* @param {string} publicKey The cryptobox X25519 public key to encrypt with (encoded in RFC 4648 standard Base64).
|
|
563
|
+
* @param {Uint8Array} message the bytes to encrypt.
|
|
564
|
+
*
|
|
565
|
+
* @returns {string} the encrypted bytes in RFC 4648 standard Base64.
|
|
566
|
+
*/
|
|
567
|
+
function encryptMessage(publicKey, message) {
|
|
568
|
+
const publicKeyBytes = sodium.from_base64(publicKey, sodium.base64_variants.ORIGINAL);
|
|
569
|
+
return sodium.to_base64(sodium.crypto_box_seal(message, publicKeyBytes), sodium.base64_variants.ORIGINAL);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const KEY_STORE = Metadata.baseUrl();
|
|
573
|
+
function convert(metadata) {
|
|
574
|
+
// This looks up the method name in VerifyingKey
|
|
575
|
+
const verifyingKey = VerifyingKey[metadata.verifyingKey];
|
|
576
|
+
if (!verifyingKey) {
|
|
577
|
+
throw new Error("Invalid method name: " + metadata.verifyingKey);
|
|
578
|
+
}
|
|
579
|
+
return {
|
|
580
|
+
name: metadata.name,
|
|
581
|
+
locator: metadata.locator,
|
|
582
|
+
prover: metadata.prover,
|
|
583
|
+
verifier: metadata.verifier,
|
|
584
|
+
verifyingKey,
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
const CREDITS_PROGRAM_KEYS = {
|
|
588
|
+
bond_public: convert(Metadata.bond_public()),
|
|
589
|
+
bond_validator: convert(Metadata.bond_validator()),
|
|
590
|
+
claim_unbond_public: convert(Metadata.claim_unbond_public()),
|
|
591
|
+
fee_private: convert(Metadata.fee_private()),
|
|
592
|
+
fee_public: convert(Metadata.fee_public()),
|
|
593
|
+
inclusion: convert(Metadata.inclusion()),
|
|
594
|
+
join: convert(Metadata.join()),
|
|
595
|
+
set_validator_state: convert(Metadata.set_validator_state()),
|
|
596
|
+
split: convert(Metadata.split()),
|
|
597
|
+
transfer_private: convert(Metadata.transfer_private()),
|
|
598
|
+
transfer_private_to_public: convert(Metadata.transfer_private_to_public()),
|
|
599
|
+
transfer_public: convert(Metadata.transfer_public()),
|
|
600
|
+
transfer_public_as_signer: convert(Metadata.transfer_public_as_signer()),
|
|
601
|
+
transfer_public_to_private: convert(Metadata.transfer_public_to_private()),
|
|
602
|
+
unbond_public: convert(Metadata.unbond_public()),
|
|
603
|
+
getKey: function (key) {
|
|
604
|
+
if (this.hasOwnProperty(key)) {
|
|
605
|
+
return this[key];
|
|
606
|
+
}
|
|
607
|
+
else {
|
|
608
|
+
throw new Error(`Key "${key}" not found.`);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
const PRIVATE_TRANSFER_TYPES = new Set([
|
|
613
|
+
"transfer_private",
|
|
614
|
+
"private",
|
|
615
|
+
"transferPrivate",
|
|
616
|
+
"transfer_private_to_public",
|
|
617
|
+
"privateToPublic",
|
|
618
|
+
"transferPrivateToPublic",
|
|
619
|
+
]);
|
|
620
|
+
const VALID_TRANSFER_TYPES = new Set([
|
|
621
|
+
"transfer_private",
|
|
622
|
+
"private",
|
|
623
|
+
"transferPrivate",
|
|
624
|
+
"transfer_private_to_public",
|
|
625
|
+
"privateToPublic",
|
|
626
|
+
"transferPrivateToPublic",
|
|
627
|
+
"transfer_public",
|
|
628
|
+
"transfer_public_as_signer",
|
|
629
|
+
"public",
|
|
630
|
+
"public_as_signer",
|
|
631
|
+
"transferPublic",
|
|
632
|
+
"transferPublicAsSigner",
|
|
633
|
+
"transfer_public_to_private",
|
|
634
|
+
"publicToPrivate",
|
|
635
|
+
"publicAsSigner",
|
|
636
|
+
"transferPublicToPrivate",
|
|
637
|
+
]);
|
|
638
|
+
const PRIVATE_TRANSFER = new Set([
|
|
639
|
+
"private",
|
|
640
|
+
"transfer_private",
|
|
641
|
+
"transferPrivate",
|
|
642
|
+
]);
|
|
643
|
+
const PRIVATE_TO_PUBLIC_TRANSFER = new Set([
|
|
644
|
+
"private_to_public",
|
|
645
|
+
"privateToPublic",
|
|
646
|
+
"transfer_private_to_public",
|
|
647
|
+
"transferPrivateToPublic",
|
|
648
|
+
]);
|
|
649
|
+
const PUBLIC_TRANSFER = new Set([
|
|
650
|
+
"public",
|
|
651
|
+
"transfer_public",
|
|
652
|
+
"transferPublic",
|
|
653
|
+
]);
|
|
654
|
+
const PUBLIC_TRANSFER_AS_SIGNER = new Set([
|
|
655
|
+
"public_as_signer",
|
|
656
|
+
"transfer_public_as_signer",
|
|
657
|
+
"transferPublicAsSigner",
|
|
658
|
+
]);
|
|
659
|
+
const PUBLIC_TO_PRIVATE_TRANSFER = new Set([
|
|
660
|
+
"public_to_private",
|
|
661
|
+
"publicToPrivate",
|
|
662
|
+
"transfer_public_to_private",
|
|
663
|
+
"transferPublicToPrivate",
|
|
664
|
+
]);
|
|
665
|
+
const RECORD_DOMAIN = "RecordScannerV0";
|
|
666
|
+
/**
|
|
667
|
+
* Zero address on Aleo blockchain that corresponds to field element 0. Used as padding in Merkle trees and as a sentinel value.
|
|
668
|
+
*/
|
|
669
|
+
const ZERO_ADDRESS = "aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc";
|
|
670
|
+
const FIVE_MINUTES = 5 * 60 * 1000; // 5 minutes in milliseconds
|
|
671
|
+
|
|
469
672
|
/**
|
|
470
673
|
* Client library that encapsulates REST calls to publicly exposed endpoints of Aleo nodes. The methods provided in this
|
|
471
674
|
* allow users to query public information from the Aleo blockchain and submit transactions to the network.
|
|
@@ -477,6 +680,8 @@ async function retryWithBackoff(fn, { maxAttempts = 5, baseDelay = 100, jitter,
|
|
|
477
680
|
*
|
|
478
681
|
* // Connection to a public beacon node
|
|
479
682
|
* const account = Account.fromCiphertext(process.env.ciphertext, process.env.password);
|
|
683
|
+
* const apiKey = process.env.apiKey;
|
|
684
|
+
* const consumerId = process.env.consumerId;
|
|
480
685
|
* const publicNetworkClient = new AleoNetworkClient("http://api.explorer.provable.com/v1", undefined, account);
|
|
481
686
|
*/
|
|
482
687
|
class AleoNetworkClient {
|
|
@@ -486,18 +691,40 @@ class AleoNetworkClient {
|
|
|
486
691
|
ctx;
|
|
487
692
|
verboseErrors;
|
|
488
693
|
network;
|
|
694
|
+
apiKey;
|
|
695
|
+
consumerId;
|
|
696
|
+
jwtData;
|
|
697
|
+
proverUri;
|
|
698
|
+
recordScannerUri;
|
|
489
699
|
constructor(host, options) {
|
|
490
700
|
this.host = host + "/mainnet";
|
|
491
701
|
this.network = "mainnet";
|
|
492
702
|
this.ctx = {};
|
|
493
703
|
this.verboseErrors = true;
|
|
494
|
-
if (options
|
|
495
|
-
|
|
704
|
+
if (options) {
|
|
705
|
+
if (options.headers) {
|
|
706
|
+
this.headers = options.headers;
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
this.headers = {
|
|
710
|
+
// This is replaced by the actual version by a Rollup plugin
|
|
711
|
+
"X-Aleo-SDK-Version": "0.9.15-enc",
|
|
712
|
+
"X-Aleo-environment": environment(),
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
// If a prover uri was specified, set the prover uri.
|
|
716
|
+
if (options.proverUri) {
|
|
717
|
+
this.proverUri = options.proverUri + "/mainnet";
|
|
718
|
+
}
|
|
719
|
+
// If a record scanner uri was specified, set the record scanner uri.
|
|
720
|
+
if (options.recordScannerUri) {
|
|
721
|
+
this.recordScannerUri = options.recordScannerUri + "/mainnet";
|
|
722
|
+
}
|
|
496
723
|
}
|
|
497
724
|
else {
|
|
498
725
|
this.headers = {
|
|
499
726
|
// This is replaced by the actual version by a Rollup plugin
|
|
500
|
-
"X-Aleo-SDK-Version": "0.9.
|
|
727
|
+
"X-Aleo-SDK-Version": "0.9.15-enc",
|
|
501
728
|
"X-Aleo-environment": environment(),
|
|
502
729
|
};
|
|
503
730
|
}
|
|
@@ -542,6 +769,40 @@ class AleoNetworkClient {
|
|
|
542
769
|
setHost(host) {
|
|
543
770
|
this.host = host + "/mainnet";
|
|
544
771
|
}
|
|
772
|
+
/**
|
|
773
|
+
* Set a new uri for a remote prover.
|
|
774
|
+
*
|
|
775
|
+
* @param {string} proverUri The uri of the remote prover.
|
|
776
|
+
*
|
|
777
|
+
* @example
|
|
778
|
+
* import { AleoNetworkClient } from "@provablehq/sdk/mainnet.js";
|
|
779
|
+
*
|
|
780
|
+
* // Create a networkClient that connects to the provable explorer api.
|
|
781
|
+
* const networkClient = new AleoNetworkClient("http://api.explorer.provable.com/v1", undefined);
|
|
782
|
+
*
|
|
783
|
+
* // Set the prover uri.
|
|
784
|
+
* networkClient.setProverUri("https://prover.provable.prove");
|
|
785
|
+
*/
|
|
786
|
+
setProverUri(proverUri) {
|
|
787
|
+
this.proverUri = proverUri + "/mainnet";
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Set a new uri for a remote record scanner.
|
|
791
|
+
*
|
|
792
|
+
* @param {string} recordScannerUri The uri of the remote record scanner.
|
|
793
|
+
*
|
|
794
|
+
* @example
|
|
795
|
+
* import { AleoNetworkClient } from "@provablehq/sdk/mainnet.js";
|
|
796
|
+
*
|
|
797
|
+
* // Create a networkClient that connects to the provable explorer api.
|
|
798
|
+
* const networkClient = new AleoNetworkClient("http://api.explorer.provable.com/v1", undefined);
|
|
799
|
+
*
|
|
800
|
+
* // Set the record scanner uri.
|
|
801
|
+
* networkClient.setRecordScannerUri("https://scanner.provable.scan");
|
|
802
|
+
*/
|
|
803
|
+
setRecordScannerUri(recordScannerUri) {
|
|
804
|
+
this.recordScannerUri = recordScannerUri + "/mainnet";
|
|
805
|
+
}
|
|
545
806
|
/**
|
|
546
807
|
* Set verbose errors to true or false for the `AleoNetworkClient`. When set to true, if `submitTransaction` fails, the failure responses will report descriptive information as to why the transaction failed.
|
|
547
808
|
*
|
|
@@ -1342,10 +1603,9 @@ class AleoNetworkClient {
|
|
|
1342
1603
|
* programImports = await networkClient.getProgramImports(double_test);
|
|
1343
1604
|
* assert.deepStrictEqual(programImports, expectedImports);
|
|
1344
1605
|
*/
|
|
1345
|
-
async getProgramImports(inputProgram) {
|
|
1606
|
+
async getProgramImports(inputProgram, imports = {}) {
|
|
1346
1607
|
try {
|
|
1347
1608
|
this.ctx = { "X-ALEO-METHOD": "getProgramImports" };
|
|
1348
|
-
const imports = {};
|
|
1349
1609
|
// Normalize input to a Program object
|
|
1350
1610
|
let program;
|
|
1351
1611
|
if (inputProgram instanceof Program) {
|
|
@@ -1371,7 +1631,7 @@ class AleoNetworkClient {
|
|
|
1371
1631
|
const import_id = importList[i];
|
|
1372
1632
|
if (!imports.hasOwnProperty(import_id)) {
|
|
1373
1633
|
const programSource = await this.getProgram(import_id);
|
|
1374
|
-
const nestedImports = await this.getProgramImports(
|
|
1634
|
+
const nestedImports = await this.getProgramImports(programSource, imports);
|
|
1375
1635
|
for (const key in nestedImports) {
|
|
1376
1636
|
if (!imports.hasOwnProperty(key)) {
|
|
1377
1637
|
imports[key] = nestedImports[key];
|
|
@@ -1842,37 +2102,182 @@ class AleoNetworkClient {
|
|
|
1842
2102
|
}
|
|
1843
2103
|
}
|
|
1844
2104
|
/**
|
|
1845
|
-
*
|
|
2105
|
+
* Refreshes the JWT by making a POST request to /jwts/{consumer_id}
|
|
2106
|
+
*
|
|
2107
|
+
* @param {string} apiKey - The API key for authentication.
|
|
2108
|
+
* @param {string} consumerId - The consumer ID associated with the API key.
|
|
2109
|
+
* @returns {Promise<JwtData>} The JWT token and expiration time
|
|
2110
|
+
*/
|
|
2111
|
+
async refreshJwt(apiKey, consumerId) {
|
|
2112
|
+
if (!apiKey || !consumerId) {
|
|
2113
|
+
throw new Error('API key and consumer ID are required to refresh JWT');
|
|
2114
|
+
}
|
|
2115
|
+
const response = await post(`https://api.provable.com/jwts/${consumerId}`, {
|
|
2116
|
+
headers: {
|
|
2117
|
+
'X-Provable-API-Key': apiKey
|
|
2118
|
+
}
|
|
2119
|
+
});
|
|
2120
|
+
const authHeader = response.headers.get('authorization');
|
|
2121
|
+
if (!authHeader) {
|
|
2122
|
+
throw new Error('No authorization header in JWT refresh response');
|
|
2123
|
+
}
|
|
2124
|
+
const body = await response.json();
|
|
2125
|
+
return {
|
|
2126
|
+
jwt: authHeader,
|
|
2127
|
+
expiration: body.exp * 1000 // Convert to milliseconds
|
|
2128
|
+
};
|
|
2129
|
+
}
|
|
2130
|
+
/**
|
|
2131
|
+
* Parses a /prove or /prove/encrypted response. Returns a result object (never throws for 200/400/500/503).
|
|
2132
|
+
*/
|
|
2133
|
+
async handleProvingResponse(response) {
|
|
2134
|
+
// Get the proving response text.
|
|
2135
|
+
const text = await response.text();
|
|
2136
|
+
let body;
|
|
2137
|
+
// Parse the body.
|
|
2138
|
+
try {
|
|
2139
|
+
body = parseJSON(text);
|
|
2140
|
+
}
|
|
2141
|
+
catch {
|
|
2142
|
+
body = {};
|
|
2143
|
+
}
|
|
2144
|
+
// If the status is 200, attempt to parse the Proving Request along its expected structure.
|
|
2145
|
+
if (response.status === 200) {
|
|
2146
|
+
if (isProvingResponse(body)) {
|
|
2147
|
+
return { ok: true, data: body };
|
|
2148
|
+
}
|
|
2149
|
+
return {
|
|
2150
|
+
ok: false,
|
|
2151
|
+
status: response.status,
|
|
2152
|
+
error: { message: "Invalid response from proving service" },
|
|
2153
|
+
};
|
|
2154
|
+
}
|
|
2155
|
+
// If the response is non 200, return the information back to the caller so it can be handled.
|
|
2156
|
+
if (response.status === 400 || response.status === 500 || response.status === 503) {
|
|
2157
|
+
const error = isProveApiErrorBody(body)
|
|
2158
|
+
? body
|
|
2159
|
+
: { message: text || `${response.status} error` };
|
|
2160
|
+
return { ok: false, status: response.status, error };
|
|
2161
|
+
}
|
|
2162
|
+
return {
|
|
2163
|
+
ok: false,
|
|
2164
|
+
status: response.status,
|
|
2165
|
+
error: { message: text || `${response.status} error` },
|
|
2166
|
+
};
|
|
2167
|
+
}
|
|
2168
|
+
/**
|
|
2169
|
+
* Submit a `ProvingRequest` to a remote proving service for delegated proving. If the broadcast flag of the `ProvingRequest` is set to `true` the remote service will attempt to broadcast the result `Transaction` on behalf of the requestor. Throws on HTTP 400, 500, 503 (and retries on 500/503). Callers should {@link submitProvingRequestSafe} to handle proving request failures without throwing.
|
|
1846
2170
|
*
|
|
1847
2171
|
* @param {DelegatedProvingParams} options - The optional parameters required to submit a proving request.
|
|
1848
2172
|
* @returns {Promise<ProvingResponse>} The ProvingResponse containing the transaction result and the result of the broadcast if the `broadcast` flag was set to `true`.
|
|
1849
2173
|
*/
|
|
1850
2174
|
async submitProvingRequest(options) {
|
|
1851
|
-
const
|
|
2175
|
+
const result = await this.submitProvingRequestSafe(options);
|
|
2176
|
+
if (result.ok) {
|
|
2177
|
+
return result.data;
|
|
2178
|
+
}
|
|
2179
|
+
const err = new Error(result.error.message);
|
|
2180
|
+
err.status = result.status;
|
|
2181
|
+
throw err;
|
|
2182
|
+
}
|
|
2183
|
+
/**
|
|
2184
|
+
* Submit a proving request and return a result object instead of throwing. This method is usable when callers want to handle HTTP status (400, 500, 503) yourself. Retries on 500/503 and returns on 200 or 400.
|
|
2185
|
+
*
|
|
2186
|
+
* @param {DelegatedProvingParams} options - The optional parameters required to submit a proving request.
|
|
2187
|
+
* @returns {Promise<ProvingResult>} `{ ok: true, data }` on success (200), or `{ ok: false, status, error }` on 400/500/503. Check `result.ok` and then either `result.data` or `result.status` / `result.error.message`.
|
|
2188
|
+
*/
|
|
2189
|
+
async submitProvingRequestSafe(options) {
|
|
2190
|
+
// Attempt to get the Prover URI first from the options, then from any configured globally, or third try the main configured host.
|
|
2191
|
+
const proverUri = (options.url ?? this.proverUri) ?? this.host;
|
|
1852
2192
|
const provingRequestString = options.provingRequest instanceof ProvingRequest
|
|
1853
2193
|
? options.provingRequest.toString()
|
|
1854
2194
|
: options.provingRequest;
|
|
1855
|
-
//
|
|
2195
|
+
// Try to get JWT data to access the Provable API.
|
|
2196
|
+
const apiKey = options.apiKey ?? this.apiKey;
|
|
2197
|
+
const consumerId = options.consumerId ?? this.consumerId;
|
|
2198
|
+
let jwtData = options.jwtData ?? this.jwtData;
|
|
2199
|
+
// Check to see if the JWT needs refreshing.
|
|
2200
|
+
const isExpired = jwtData && Date.now() >= jwtData.expiration - FIVE_MINUTES;
|
|
2201
|
+
if (!jwtData || isExpired) {
|
|
2202
|
+
if (options.apiKey && options.consumerId) {
|
|
2203
|
+
jwtData = await this.refreshJwt(apiKey, consumerId);
|
|
2204
|
+
this.jwtData = jwtData;
|
|
2205
|
+
options.jwtData = jwtData;
|
|
2206
|
+
}
|
|
2207
|
+
else {
|
|
2208
|
+
console.warn('JWT or both apiKey and consumerId are required when using the Provable API');
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
// Create the necessary headers to hit the provable api.
|
|
1856
2212
|
const headers = {
|
|
1857
2213
|
...this.headers,
|
|
1858
2214
|
"X-ALEO-METHOD": "submitProvingRequest",
|
|
1859
|
-
"Content-Type": "application/json"
|
|
2215
|
+
"Content-Type": "application/json",
|
|
1860
2216
|
};
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
2217
|
+
if (jwtData?.jwt) {
|
|
2218
|
+
headers["Authorization"] = jwtData.jwt;
|
|
2219
|
+
}
|
|
2220
|
+
// Encapsulate the requests in a locally scoped function that can be run with a retry closure.
|
|
2221
|
+
const runRequest = async () => {
|
|
2222
|
+
// If DPS privacy is set, call invoke the encrypted flow.
|
|
2223
|
+
if (options.dpsPrivacy) {
|
|
2224
|
+
// Get an ephemeral public key from a DPS service.
|
|
2225
|
+
const pubKeyResponse = await get(proverUri + "/pubkey", {
|
|
2226
|
+
headers,
|
|
2227
|
+
});
|
|
2228
|
+
// Encrypt the provingRequest.
|
|
2229
|
+
const pubkey = parseJSON(await pubKeyResponse.text());
|
|
2230
|
+
const ciphertext = encryptProvingRequest(pubkey.public_key, ProvingRequest.fromString(provingRequestString));
|
|
2231
|
+
// Form the expected query a DPS service expects (including the key_id).
|
|
2232
|
+
const payload = {
|
|
2233
|
+
key_id: pubkey.key_id,
|
|
2234
|
+
ciphertext: ciphertext,
|
|
2235
|
+
};
|
|
2236
|
+
const res = await fetch(`${proverUri}/prove/encrypted`, {
|
|
2237
|
+
method: "POST",
|
|
2238
|
+
body: JSON.stringify(payload),
|
|
2239
|
+
headers,
|
|
2240
|
+
});
|
|
2241
|
+
// Properly handle the proving response.
|
|
2242
|
+
return this.handleProvingResponse(res);
|
|
2243
|
+
}
|
|
2244
|
+
// If encrypted usage is not specified use the unencrypted endpoint.
|
|
2245
|
+
const proveEndpoint = proverUri.endsWith("/prove")
|
|
2246
|
+
? proverUri
|
|
2247
|
+
: proverUri + "/prove";
|
|
2248
|
+
const res = await fetch(proveEndpoint, {
|
|
2249
|
+
method: "POST",
|
|
1867
2250
|
body: provingRequestString,
|
|
1868
|
-
headers
|
|
1869
|
-
})
|
|
1870
|
-
|
|
1871
|
-
return
|
|
2251
|
+
headers,
|
|
2252
|
+
});
|
|
2253
|
+
// Properly handle the proving response.
|
|
2254
|
+
return this.handleProvingResponse(res);
|
|
2255
|
+
};
|
|
2256
|
+
try {
|
|
2257
|
+
// Run the request with retries.
|
|
2258
|
+
return await retryWithBackoff(async () => {
|
|
2259
|
+
// Run the encrypted or non-encrypted flow as specified by the flags.
|
|
2260
|
+
const result = await runRequest();
|
|
2261
|
+
if (result.ok) {
|
|
2262
|
+
return result;
|
|
2263
|
+
}
|
|
2264
|
+
// If 500s are hit responses are returned, attempt retries.
|
|
2265
|
+
if (result.status === 500 || result.status === 503) {
|
|
2266
|
+
const err = new Error(result.error.message);
|
|
2267
|
+
err.status = result.status;
|
|
2268
|
+
throw err;
|
|
2269
|
+
}
|
|
2270
|
+
return result;
|
|
2271
|
+
});
|
|
1872
2272
|
}
|
|
1873
|
-
catch (
|
|
1874
|
-
|
|
1875
|
-
|
|
2273
|
+
catch (err) {
|
|
2274
|
+
// If an error is returned, provide usable information to the caller.
|
|
2275
|
+
const e = err;
|
|
2276
|
+
return {
|
|
2277
|
+
ok: false,
|
|
2278
|
+
status: e.status ?? 500,
|
|
2279
|
+
error: { message: e.message },
|
|
2280
|
+
};
|
|
1876
2281
|
}
|
|
1877
2282
|
}
|
|
1878
2283
|
/**
|
|
@@ -1957,105 +2362,6 @@ class AleoNetworkClient {
|
|
|
1957
2362
|
}
|
|
1958
2363
|
}
|
|
1959
2364
|
|
|
1960
|
-
const KEY_STORE = Metadata.baseUrl();
|
|
1961
|
-
function convert(metadata) {
|
|
1962
|
-
// This looks up the method name in VerifyingKey
|
|
1963
|
-
const verifyingKey = VerifyingKey[metadata.verifyingKey];
|
|
1964
|
-
if (!verifyingKey) {
|
|
1965
|
-
throw new Error("Invalid method name: " + metadata.verifyingKey);
|
|
1966
|
-
}
|
|
1967
|
-
return {
|
|
1968
|
-
name: metadata.name,
|
|
1969
|
-
locator: metadata.locator,
|
|
1970
|
-
prover: metadata.prover,
|
|
1971
|
-
verifier: metadata.verifier,
|
|
1972
|
-
verifyingKey,
|
|
1973
|
-
};
|
|
1974
|
-
}
|
|
1975
|
-
const CREDITS_PROGRAM_KEYS = {
|
|
1976
|
-
bond_public: convert(Metadata.bond_public()),
|
|
1977
|
-
bond_validator: convert(Metadata.bond_validator()),
|
|
1978
|
-
claim_unbond_public: convert(Metadata.claim_unbond_public()),
|
|
1979
|
-
fee_private: convert(Metadata.fee_private()),
|
|
1980
|
-
fee_public: convert(Metadata.fee_public()),
|
|
1981
|
-
inclusion: convert(Metadata.inclusion()),
|
|
1982
|
-
join: convert(Metadata.join()),
|
|
1983
|
-
set_validator_state: convert(Metadata.set_validator_state()),
|
|
1984
|
-
split: convert(Metadata.split()),
|
|
1985
|
-
transfer_private: convert(Metadata.transfer_private()),
|
|
1986
|
-
transfer_private_to_public: convert(Metadata.transfer_private_to_public()),
|
|
1987
|
-
transfer_public: convert(Metadata.transfer_public()),
|
|
1988
|
-
transfer_public_as_signer: convert(Metadata.transfer_public_as_signer()),
|
|
1989
|
-
transfer_public_to_private: convert(Metadata.transfer_public_to_private()),
|
|
1990
|
-
unbond_public: convert(Metadata.unbond_public()),
|
|
1991
|
-
getKey: function (key) {
|
|
1992
|
-
if (this.hasOwnProperty(key)) {
|
|
1993
|
-
return this[key];
|
|
1994
|
-
}
|
|
1995
|
-
else {
|
|
1996
|
-
throw new Error(`Key "${key}" not found.`);
|
|
1997
|
-
}
|
|
1998
|
-
}
|
|
1999
|
-
};
|
|
2000
|
-
const PRIVATE_TRANSFER_TYPES = new Set([
|
|
2001
|
-
"transfer_private",
|
|
2002
|
-
"private",
|
|
2003
|
-
"transferPrivate",
|
|
2004
|
-
"transfer_private_to_public",
|
|
2005
|
-
"privateToPublic",
|
|
2006
|
-
"transferPrivateToPublic",
|
|
2007
|
-
]);
|
|
2008
|
-
const VALID_TRANSFER_TYPES = new Set([
|
|
2009
|
-
"transfer_private",
|
|
2010
|
-
"private",
|
|
2011
|
-
"transferPrivate",
|
|
2012
|
-
"transfer_private_to_public",
|
|
2013
|
-
"privateToPublic",
|
|
2014
|
-
"transferPrivateToPublic",
|
|
2015
|
-
"transfer_public",
|
|
2016
|
-
"transfer_public_as_signer",
|
|
2017
|
-
"public",
|
|
2018
|
-
"public_as_signer",
|
|
2019
|
-
"transferPublic",
|
|
2020
|
-
"transferPublicAsSigner",
|
|
2021
|
-
"transfer_public_to_private",
|
|
2022
|
-
"publicToPrivate",
|
|
2023
|
-
"publicAsSigner",
|
|
2024
|
-
"transferPublicToPrivate",
|
|
2025
|
-
]);
|
|
2026
|
-
const PRIVATE_TRANSFER = new Set([
|
|
2027
|
-
"private",
|
|
2028
|
-
"transfer_private",
|
|
2029
|
-
"transferPrivate",
|
|
2030
|
-
]);
|
|
2031
|
-
const PRIVATE_TO_PUBLIC_TRANSFER = new Set([
|
|
2032
|
-
"private_to_public",
|
|
2033
|
-
"privateToPublic",
|
|
2034
|
-
"transfer_private_to_public",
|
|
2035
|
-
"transferPrivateToPublic",
|
|
2036
|
-
]);
|
|
2037
|
-
const PUBLIC_TRANSFER = new Set([
|
|
2038
|
-
"public",
|
|
2039
|
-
"transfer_public",
|
|
2040
|
-
"transferPublic",
|
|
2041
|
-
]);
|
|
2042
|
-
const PUBLIC_TRANSFER_AS_SIGNER = new Set([
|
|
2043
|
-
"public_as_signer",
|
|
2044
|
-
"transfer_public_as_signer",
|
|
2045
|
-
"transferPublicAsSigner",
|
|
2046
|
-
]);
|
|
2047
|
-
const PUBLIC_TO_PRIVATE_TRANSFER = new Set([
|
|
2048
|
-
"public_to_private",
|
|
2049
|
-
"publicToPrivate",
|
|
2050
|
-
"transfer_public_to_private",
|
|
2051
|
-
"transferPublicToPrivate",
|
|
2052
|
-
]);
|
|
2053
|
-
const RECORD_DOMAIN = "RecordScannerV0";
|
|
2054
|
-
/**
|
|
2055
|
-
* Zero address on Aleo blockchain that corresponds to field element 0. Used as padding in Merkle trees and as a sentinel value.
|
|
2056
|
-
*/
|
|
2057
|
-
const ZERO_ADDRESS = "aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc";
|
|
2058
|
-
|
|
2059
2365
|
/**
|
|
2060
2366
|
* AleoKeyProviderParams search parameter for the AleoKeyProvider. It allows for the specification of a proverUri and
|
|
2061
2367
|
* verifierUri to fetch keys via HTTP from a remote resource as well as a unique cacheKey to store the keys in memory.
|
|
@@ -3287,6 +3593,20 @@ class BlockHeightSearch {
|
|
|
3287
3593
|
}
|
|
3288
3594
|
}
|
|
3289
3595
|
|
|
3596
|
+
/**
|
|
3597
|
+
* Error thrown when a record scanner request fails (e.g. /register, /register/encrypted).
|
|
3598
|
+
* Includes HTTP status so callers can handle 422 vs 500 etc.
|
|
3599
|
+
*/
|
|
3600
|
+
class RecordScannerRequestError extends Error {
|
|
3601
|
+
status;
|
|
3602
|
+
constructor(message, status) {
|
|
3603
|
+
super(message);
|
|
3604
|
+
this.name = "RecordScannerRequestError";
|
|
3605
|
+
this.status = status;
|
|
3606
|
+
Object.setPrototypeOf(this, RecordScannerRequestError.prototype);
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3290
3610
|
/**
|
|
3291
3611
|
* RecordScanner is a RecordProvider implementation that uses the record scanner service to find records.
|
|
3292
3612
|
*
|
|
@@ -3296,7 +3616,8 @@ class BlockHeightSearch {
|
|
|
3296
3616
|
* const recordScanner = new RecordScanner({ url: "https://record-scanner.aleo.org" });
|
|
3297
3617
|
* recordScanner.setAccount(account);
|
|
3298
3618
|
* recordScanner.setApiKey("your-api-key");
|
|
3299
|
-
* const
|
|
3619
|
+
* const result = await recordScanner.register(viewKey, 0);
|
|
3620
|
+
* if (result.ok) { const uuid = result.data.uuid; }
|
|
3300
3621
|
*
|
|
3301
3622
|
* const filter = {
|
|
3302
3623
|
* uuid,
|
|
@@ -3332,9 +3653,21 @@ class RecordScanner {
|
|
|
3332
3653
|
url;
|
|
3333
3654
|
apiKey;
|
|
3334
3655
|
uuid;
|
|
3656
|
+
consumerId;
|
|
3657
|
+
jwtData;
|
|
3335
3658
|
constructor(options) {
|
|
3336
|
-
|
|
3659
|
+
// Set the network by detecting which version of the SDK is being used.
|
|
3660
|
+
const network = "/mainnet";
|
|
3661
|
+
// If the user has configured a network in their uri, throw
|
|
3662
|
+
if (options.url.endsWith("/mainnet") || options.url.endsWith("/testnet")) {
|
|
3663
|
+
throw new Error("The record scanning url should not include the specific network, this is automatically configured by the Provable SDK.");
|
|
3664
|
+
}
|
|
3665
|
+
// Configure the url to use the network the SDK is using.
|
|
3666
|
+
this.url = options.url + network;
|
|
3667
|
+
// Configure authentication options/
|
|
3337
3668
|
this.apiKey = typeof options.apiKey === "string" ? { header: "X-Provable-API-Key", value: options.apiKey } : options.apiKey;
|
|
3669
|
+
this.consumerId = options.consumerId;
|
|
3670
|
+
this.jwtData = options.jwtData;
|
|
3338
3671
|
}
|
|
3339
3672
|
/**
|
|
3340
3673
|
* Set the API key to use for the record scanner.
|
|
@@ -3344,6 +3677,59 @@ class RecordScanner {
|
|
|
3344
3677
|
async setApiKey(apiKey) {
|
|
3345
3678
|
this.apiKey = typeof apiKey === "string" ? { header: "X-Provable-API-Key", value: apiKey } : apiKey;
|
|
3346
3679
|
}
|
|
3680
|
+
/**
|
|
3681
|
+
* Set the consumer ID used for JWT refresh when using authenticated record scanner (e.g. Provable API).
|
|
3682
|
+
*/
|
|
3683
|
+
async setConsumerId(consumerId) {
|
|
3684
|
+
this.consumerId = consumerId;
|
|
3685
|
+
}
|
|
3686
|
+
/**
|
|
3687
|
+
* Set JWT data for authentication. Optional; when not set, JWT can be refreshed from apiKey + consumerId if provided.
|
|
3688
|
+
*/
|
|
3689
|
+
async setJwtData(jwtData) {
|
|
3690
|
+
this.jwtData = jwtData;
|
|
3691
|
+
}
|
|
3692
|
+
/**
|
|
3693
|
+
* Refreshes the JWT by making a POST request to /jwts/{consumer_id}. Used when authentication is required.
|
|
3694
|
+
*/
|
|
3695
|
+
async refreshJwt(apiKey, consumerId) {
|
|
3696
|
+
const response = await post(`https://api.provable.com/jwts/${consumerId}`, {
|
|
3697
|
+
headers: {
|
|
3698
|
+
"X-Provable-API-Key": apiKey,
|
|
3699
|
+
},
|
|
3700
|
+
});
|
|
3701
|
+
const authHeader = response.headers.get("authorization");
|
|
3702
|
+
if (!authHeader) {
|
|
3703
|
+
throw new Error("No authorization header in JWT refresh response");
|
|
3704
|
+
}
|
|
3705
|
+
const body = await response.json();
|
|
3706
|
+
return {
|
|
3707
|
+
jwt: authHeader,
|
|
3708
|
+
expiration: body.exp * 1000, // Convert to milliseconds
|
|
3709
|
+
};
|
|
3710
|
+
}
|
|
3711
|
+
/**
|
|
3712
|
+
* Returns auth headers (e.g. Authorization with JWT). Refreshes JWT if expired and apiKey + consumerId are set. Empty when auth is not configured.
|
|
3713
|
+
*/
|
|
3714
|
+
async getAuthHeaders() {
|
|
3715
|
+
let jwtData = this.jwtData;
|
|
3716
|
+
const isExpired = jwtData && Date.now() >= jwtData.expiration - FIVE_MINUTES;
|
|
3717
|
+
if (!jwtData || isExpired) {
|
|
3718
|
+
const apiKey = this.apiKey?.value;
|
|
3719
|
+
if (apiKey && this.consumerId) {
|
|
3720
|
+
jwtData = await this.refreshJwt(apiKey, this.consumerId);
|
|
3721
|
+
this.jwtData = jwtData;
|
|
3722
|
+
}
|
|
3723
|
+
else if (jwtData?.jwt) {
|
|
3724
|
+
// Use existing JWT even if expired when we can't refresh
|
|
3725
|
+
return { Authorization: jwtData.jwt };
|
|
3726
|
+
}
|
|
3727
|
+
else {
|
|
3728
|
+
return {};
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
return jwtData?.jwt ? { Authorization: jwtData.jwt } : {};
|
|
3732
|
+
}
|
|
3347
3733
|
/**
|
|
3348
3734
|
* Set the UUID to use for the record scanner.
|
|
3349
3735
|
*
|
|
@@ -3353,14 +3739,15 @@ class RecordScanner {
|
|
|
3353
3739
|
this.uuid = uuidOrViewKey instanceof ViewKey ? this.computeUUID(uuidOrViewKey) : uuidOrViewKey;
|
|
3354
3740
|
}
|
|
3355
3741
|
/**
|
|
3356
|
-
* Register the account with the record scanner service.
|
|
3742
|
+
* Register the account with the record scanner service (unencrypted POST /register). Does not throw if a valid error response from the record scanner is received; returns a result object instead.
|
|
3357
3743
|
*
|
|
3744
|
+
* @param {ViewKey} viewKey The view key to register.
|
|
3358
3745
|
* @param {number} startBlock The block height to start scanning from.
|
|
3359
|
-
* @returns {Promise<
|
|
3746
|
+
* @returns {Promise<RegisterResult>} `{ ok: true, data }` on success, or `{ ok: false, status, error }` on failure.
|
|
3360
3747
|
*/
|
|
3361
3748
|
async register(viewKey, startBlock) {
|
|
3362
3749
|
try {
|
|
3363
|
-
|
|
3750
|
+
const request = {
|
|
3364
3751
|
view_key: viewKey.to_string(),
|
|
3365
3752
|
start: startBlock,
|
|
3366
3753
|
};
|
|
@@ -3371,11 +3758,63 @@ class RecordScanner {
|
|
|
3371
3758
|
}));
|
|
3372
3759
|
const data = await response.json();
|
|
3373
3760
|
this.uuid = data.uuid;
|
|
3374
|
-
return data;
|
|
3761
|
+
return { ok: true, data };
|
|
3375
3762
|
}
|
|
3376
|
-
catch (
|
|
3377
|
-
|
|
3378
|
-
|
|
3763
|
+
catch (err) {
|
|
3764
|
+
if (err instanceof RecordScannerRequestError) {
|
|
3765
|
+
return {
|
|
3766
|
+
ok: false,
|
|
3767
|
+
status: err.status,
|
|
3768
|
+
error: { message: err.message },
|
|
3769
|
+
};
|
|
3770
|
+
}
|
|
3771
|
+
console.error(`Failed to register view key: ${err}`);
|
|
3772
|
+
throw err;
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3775
|
+
/**
|
|
3776
|
+
* Fetches an ephemeral public key from the record scanner service for use with registerEncrypted.
|
|
3777
|
+
* Follows the same pattern as the delegated proving service /pubkey endpoint.
|
|
3778
|
+
*
|
|
3779
|
+
* @returns {Promise<CryptoBoxPubKey>} The service's ephemeral public key and key_id.
|
|
3780
|
+
*/
|
|
3781
|
+
async getPubkey() {
|
|
3782
|
+
const response = await this.request(new Request(`${this.url}/pubkey`, { method: "GET" }));
|
|
3783
|
+
return parseJSON(await response.text());
|
|
3784
|
+
}
|
|
3785
|
+
/**
|
|
3786
|
+
* Registers the account with the record scanner service using the encrypted flow: 1. fetches an ephemeral public key from /pubkey - 2. encrypts the registration request (view key + start block) - 3. POSTs to /register/encrypted. Does not HTTP error on a proper error response from the record scanner; returns a result object instead.
|
|
3787
|
+
*
|
|
3788
|
+
* @param {ViewKey} viewKey The view key to register.
|
|
3789
|
+
* @param {number} startBlock The block height to start scanning from.
|
|
3790
|
+
* @returns {Promise<RegisterResult>} `{ ok: true, data }` on success, or `{ ok: false, status, error }` on failure.
|
|
3791
|
+
*/
|
|
3792
|
+
async registerEncrypted(viewKey, startBlock) {
|
|
3793
|
+
try {
|
|
3794
|
+
const pubkey = await this.getPubkey();
|
|
3795
|
+
const ciphertext = encryptRegistrationRequest(pubkey.public_key, viewKey, startBlock);
|
|
3796
|
+
const payload = {
|
|
3797
|
+
key_id: pubkey.key_id,
|
|
3798
|
+
ciphertext,
|
|
3799
|
+
};
|
|
3800
|
+
const response = await this.request(new Request(`${this.url}/register/encrypted`, {
|
|
3801
|
+
method: "POST",
|
|
3802
|
+
headers: { "Content-Type": "application/json" },
|
|
3803
|
+
body: JSON.stringify(payload),
|
|
3804
|
+
}));
|
|
3805
|
+
const data = await response.json();
|
|
3806
|
+
this.uuid = data.uuid;
|
|
3807
|
+
return { ok: true, data };
|
|
3808
|
+
}
|
|
3809
|
+
catch (err) {
|
|
3810
|
+
if (err instanceof RecordScannerRequestError) {
|
|
3811
|
+
return {
|
|
3812
|
+
ok: false,
|
|
3813
|
+
status: err.status,
|
|
3814
|
+
error: { message: err.message },
|
|
3815
|
+
};
|
|
3816
|
+
}
|
|
3817
|
+
throw err;
|
|
3379
3818
|
}
|
|
3380
3819
|
}
|
|
3381
3820
|
/**
|
|
@@ -3568,18 +4007,24 @@ class RecordScanner {
|
|
|
3568
4007
|
}
|
|
3569
4008
|
/**
|
|
3570
4009
|
* Wrapper function to make a request to the record scanner service and handle any errors.
|
|
4010
|
+
* Optionally adds JWT Authorization header when consumerId/jwtData (or apiKey+consumerId) are configured.
|
|
3571
4011
|
*
|
|
3572
4012
|
* @param {Request} req The request to make.
|
|
3573
4013
|
* @returns {Promise<Response>} The response.
|
|
3574
4014
|
*/
|
|
3575
4015
|
async request(req) {
|
|
3576
4016
|
try {
|
|
4017
|
+
const authHeaders = await this.getAuthHeaders();
|
|
4018
|
+
for (const [key, value] of Object.entries(authHeaders)) {
|
|
4019
|
+
req.headers.set(key, value);
|
|
4020
|
+
}
|
|
3577
4021
|
if (this.apiKey) {
|
|
3578
4022
|
req.headers.set(this.apiKey.header, this.apiKey.value);
|
|
3579
4023
|
}
|
|
3580
4024
|
const response = await fetch(req);
|
|
3581
4025
|
if (!response.ok) {
|
|
3582
|
-
|
|
4026
|
+
const text = await response.text();
|
|
4027
|
+
throw new RecordScannerRequestError(text || `Request to ${req.url} failed with status ${response.status}`, response.status);
|
|
3583
4028
|
}
|
|
3584
4029
|
return response;
|
|
3585
4030
|
}
|
|
@@ -3616,6 +4061,7 @@ class RecordScanner {
|
|
|
3616
4061
|
* const proof_left = sealance.getSiblingPath(tree, leftIdx, 15);
|
|
3617
4062
|
* const proof_right = sealance.getSiblingPath(tree, rightIdx, 15);
|
|
3618
4063
|
* const exclusion_proof = [proof_left, proof_right];
|
|
4064
|
+
* const formatted_proof = sealance.formatMerkleProof(exclusion_proof);
|
|
3619
4065
|
* ```
|
|
3620
4066
|
*/
|
|
3621
4067
|
class SealanceMerkleTree {
|
|
@@ -3633,8 +4079,9 @@ class SealanceMerkleTree {
|
|
|
3633
4079
|
*
|
|
3634
4080
|
* @example
|
|
3635
4081
|
* ```typescript
|
|
4082
|
+
* const sealance = new SealanceMerkleTree();
|
|
3636
4083
|
* const address = "aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px";
|
|
3637
|
-
* const fieldValue = convertAddressToField(address);
|
|
4084
|
+
* const fieldValue = sealance.convertAddressToField(address);
|
|
3638
4085
|
* console.log(fieldValue); // 123456789...n
|
|
3639
4086
|
* ```
|
|
3640
4087
|
*/
|
|
@@ -3673,8 +4120,9 @@ class SealanceMerkleTree {
|
|
|
3673
4120
|
*
|
|
3674
4121
|
* @example
|
|
3675
4122
|
* ```typescript
|
|
4123
|
+
* const sealance = new SealanceMerkleTree();
|
|
3676
4124
|
* const leaves = ["0field", "1field", "2field", "3field"];
|
|
3677
|
-
* const tree = buildTree(leaves);
|
|
4125
|
+
* const tree = sealance.buildTree(leaves);
|
|
3678
4126
|
* const root = tree[tree.length - 1]; // Get the Merkle root
|
|
3679
4127
|
* ```
|
|
3680
4128
|
*/
|
|
@@ -3703,10 +4151,23 @@ class SealanceMerkleTree {
|
|
|
3703
4151
|
}
|
|
3704
4152
|
return tree.map(element => BigInt(element.slice(0, element.length - "field".length)));
|
|
3705
4153
|
}
|
|
3706
|
-
/**
|
|
4154
|
+
/**
|
|
4155
|
+
* Converts an array of decimal string representations of U256 numbers to an array of BigInts.
|
|
3707
4156
|
*
|
|
3708
4157
|
* @param tree - Array of decimal string representations of U256 numbers.
|
|
3709
4158
|
* @returns Array of BigInts.
|
|
4159
|
+
*
|
|
4160
|
+
* @example
|
|
4161
|
+
* ```typescript
|
|
4162
|
+
* const treeStrings = ["0","4328470178059738374782465505490977516512210899136548187530607227309847251692","1741259420362056497457198439964202806733137875365061915996980524089960046336"];
|
|
4163
|
+
* const sealance = new SealanceMerkleTree();
|
|
4164
|
+
* const treeBigInts = sealance.convertTreeToBigInt(treeStrings);
|
|
4165
|
+
* console.log(treeBigInts); // [
|
|
4166
|
+
* 0,
|
|
4167
|
+
* 4328470178059738374782465505490977516512210899136548187530607227309847251692,
|
|
4168
|
+
* 1741259420362056497457198439964202806733137875365061915996980524089960046336
|
|
4169
|
+
* ]
|
|
4170
|
+
* ```
|
|
3710
4171
|
*/
|
|
3711
4172
|
convertTreeToBigInt(tree) {
|
|
3712
4173
|
return tree.map((element) => {
|
|
@@ -3730,11 +4191,18 @@ class SealanceMerkleTree {
|
|
|
3730
4191
|
* @example
|
|
3731
4192
|
* ```typescript
|
|
3732
4193
|
* const addresses = [
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
* const
|
|
4194
|
+
* "aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px",
|
|
4195
|
+
* "aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t",
|
|
4196
|
+
* "aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t",
|
|
4197
|
+
* ];
|
|
4198
|
+
* const sealance = new SealanceMerkleTree();
|
|
4199
|
+
* const leaves = sealance.generateLeaves(addresses, 15);
|
|
4200
|
+
* console.log(leaves); // [
|
|
4201
|
+
* "0field",
|
|
4202
|
+
* "1295133970529764960316948294624974168921228814652993007266766481909235735940field",
|
|
4203
|
+
* "1295133970529764960316948294624974168921228814652993007266766481909235735940field",
|
|
4204
|
+
* "3501665755452795161867664882580888971213780722176652848275908626939553697821field"
|
|
4205
|
+
* ]
|
|
3738
4206
|
* ```
|
|
3739
4207
|
*/
|
|
3740
4208
|
generateLeaves(addresses, maxTreeDepth = 15) {
|
|
@@ -3773,8 +4241,15 @@ class SealanceMerkleTree {
|
|
|
3773
4241
|
*
|
|
3774
4242
|
* @example
|
|
3775
4243
|
* ```typescript
|
|
3776
|
-
* const
|
|
3777
|
-
|
|
4244
|
+
* const addresses = [
|
|
4245
|
+
* "aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px",
|
|
4246
|
+
* "aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t",
|
|
4247
|
+
* "aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t",
|
|
4248
|
+
* ];
|
|
4249
|
+
* const sealance = new SealanceMerkleTree();
|
|
4250
|
+
* const leaves = sealance.generateLeaves(addresses);
|
|
4251
|
+
* const tree = sealance.buildTree(leaves);
|
|
4252
|
+
* const [leftIdx, rightIdx] = sealance.getLeafIndices(tree, "aleo1...");
|
|
3778
4253
|
* ```
|
|
3779
4254
|
*/
|
|
3780
4255
|
getLeafIndices(merkleTree, address) {
|
|
@@ -3802,9 +4277,17 @@ class SealanceMerkleTree {
|
|
|
3802
4277
|
*
|
|
3803
4278
|
* @example
|
|
3804
4279
|
* ```typescript
|
|
3805
|
-
* const
|
|
3806
|
-
*
|
|
3807
|
-
*
|
|
4280
|
+
* const addresses = [
|
|
4281
|
+
* "aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px",
|
|
4282
|
+
* "aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t",
|
|
4283
|
+
* "aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t",
|
|
4284
|
+
* ];
|
|
4285
|
+
* const sealance = new SealanceMerkleTree();
|
|
4286
|
+
* const leaves = sealance.generateLeaves(addresses);
|
|
4287
|
+
* const tree = sealance.buildTree(leaves);
|
|
4288
|
+
* const [leftIdx, rightIdx] = sealance.getLeafIndices(tree, "aleo1...");
|
|
4289
|
+
* const proof = sealance.getSiblingPath(tree, leftIdx, 15);
|
|
4290
|
+
* // proof = { siblings: [0n, 1n, ...], leaf_index: leftIdx }
|
|
3808
4291
|
* ```
|
|
3809
4292
|
*/
|
|
3810
4293
|
getSiblingPath(tree, leafIndex, depth) {
|
|
@@ -3835,10 +4318,18 @@ class SealanceMerkleTree {
|
|
|
3835
4318
|
*
|
|
3836
4319
|
* @example
|
|
3837
4320
|
* ```typescript
|
|
3838
|
-
* const
|
|
3839
|
-
*
|
|
3840
|
-
*
|
|
3841
|
-
*
|
|
4321
|
+
* const addresses = [
|
|
4322
|
+
* "aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px",
|
|
4323
|
+
* "aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t",
|
|
4324
|
+
* "aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t",
|
|
4325
|
+
* ];
|
|
4326
|
+
* const sealance = new SealanceMerkleTree();
|
|
4327
|
+
* const leaves = sealance.generateLeaves(addresses);
|
|
4328
|
+
* const tree = sealance.buildTree(leaves);
|
|
4329
|
+
* const [leftIdx, rightIdx] = sealance.getLeafIndices(tree, "aleo1...");
|
|
4330
|
+
* const proof1 = getSiblingPath(tree, leftIdx, 15);
|
|
4331
|
+
* const proof2 = getSiblingPath(tree, rightIdx, 15);
|
|
4332
|
+
* const formattedProof = formatMerkleProof([proof1, proof2]);
|
|
3842
4333
|
* // formattedProof = "[{ siblings: [0field, 1field, ...], leaf_index: 0u32 }, { siblings: [0field, 2field, ...], leaf_index: 1u32 }]"
|
|
3843
4334
|
* ```
|
|
3844
4335
|
*/
|
|
@@ -4267,7 +4758,9 @@ class ProgramManager {
|
|
|
4267
4758
|
throw Error("No private key provided and no private key set in the ProgramManager. Please set an account or provide a private key.");
|
|
4268
4759
|
}
|
|
4269
4760
|
// Check if the account has sufficient credits to pay for the transaction
|
|
4270
|
-
|
|
4761
|
+
if (!privateFee) {
|
|
4762
|
+
await this.checkFee(feeAddress.to_string(), tx.feeAmount());
|
|
4763
|
+
}
|
|
4271
4764
|
return await this.networkClient.submitTransaction(tx);
|
|
4272
4765
|
}
|
|
4273
4766
|
/**
|
|
@@ -4938,7 +5431,9 @@ class ProgramManager {
|
|
|
4938
5431
|
throw Error("No private key provided and no private key set in the ProgramManager. Please set an account or provide a private key.");
|
|
4939
5432
|
}
|
|
4940
5433
|
// Check if the account has sufficient credits to pay for the transaction
|
|
4941
|
-
|
|
5434
|
+
if (!options.privateFee) {
|
|
5435
|
+
await this.checkFee(feeAddress.to_string(), tx.feeAmount());
|
|
5436
|
+
}
|
|
4942
5437
|
return await this.networkClient.submitTransaction(tx);
|
|
4943
5438
|
}
|
|
4944
5439
|
/**
|
|
@@ -5110,7 +5605,9 @@ class ProgramManager {
|
|
|
5110
5605
|
// Build an execution transaction and submit it to the network
|
|
5111
5606
|
const tx = await ProgramManager$1.buildJoinTransaction(executionPrivateKey, recordOne, recordTwo, priorityFee, feeRecord, this.host, joinProvingKey, joinVerifyingKey, feeProvingKey, feeVerifyingKey, offlineQuery);
|
|
5112
5607
|
// Check if the account has sufficient credits to pay for the transaction
|
|
5113
|
-
|
|
5608
|
+
if (!privateFee) {
|
|
5609
|
+
await this.checkFee(feeAddress.to_string(), tx.feeAmount());
|
|
5610
|
+
}
|
|
5114
5611
|
return await this.networkClient.submitTransaction(tx);
|
|
5115
5612
|
}
|
|
5116
5613
|
/**
|
|
@@ -5437,7 +5934,9 @@ class ProgramManager {
|
|
|
5437
5934
|
throw Error("No private key provided and no private key set in the ProgramManager. Please set an account or provide a private key.");
|
|
5438
5935
|
}
|
|
5439
5936
|
// Check if the account has sufficient credits to pay for the transaction
|
|
5440
|
-
|
|
5937
|
+
if (!privateFee) {
|
|
5938
|
+
await this.checkFee(feeAddress.to_string(), tx.feeAmount());
|
|
5939
|
+
}
|
|
5441
5940
|
return await this.networkClient.submitTransaction(tx);
|
|
5442
5941
|
}
|
|
5443
5942
|
/**
|
|
@@ -5538,7 +6037,9 @@ class ProgramManager {
|
|
|
5538
6037
|
throw Error("No private key provided and no private key set in the ProgramManager. Please set an account or provide a private key.");
|
|
5539
6038
|
}
|
|
5540
6039
|
// Check if the account has sufficient credits to pay for the transaction
|
|
5541
|
-
|
|
6040
|
+
if (!options.privateFee) {
|
|
6041
|
+
await this.checkFee(feeAddress.to_string(), tx.feeAmount());
|
|
6042
|
+
}
|
|
5542
6043
|
return await this.networkClient.submitTransaction(tx);
|
|
5543
6044
|
}
|
|
5544
6045
|
/**
|
|
@@ -5644,7 +6145,9 @@ class ProgramManager {
|
|
|
5644
6145
|
throw Error("No private key provided and no private key set in the ProgramManager. Please set an account or provide a private key.");
|
|
5645
6146
|
}
|
|
5646
6147
|
// Check if the account has sufficient credits to pay for the transaction
|
|
5647
|
-
|
|
6148
|
+
if (!options.privateFee) {
|
|
6149
|
+
await this.checkFee(feeAddress.to_string(), tx.feeAmount());
|
|
6150
|
+
}
|
|
5648
6151
|
return await this.networkClient.submitTransaction(tx);
|
|
5649
6152
|
}
|
|
5650
6153
|
/**
|
|
@@ -5742,7 +6245,9 @@ class ProgramManager {
|
|
|
5742
6245
|
throw Error("No private key provided and no private key set in the ProgramManager. Please set an account or provide a private key.");
|
|
5743
6246
|
}
|
|
5744
6247
|
// Check if the account has sufficient credits to pay for the transaction
|
|
5745
|
-
|
|
6248
|
+
if (!options.privateFee) {
|
|
6249
|
+
await this.checkFee(feeAddress.to_string(), tx.feeAmount());
|
|
6250
|
+
}
|
|
5746
6251
|
return await this.networkClient.submitTransaction(tx);
|
|
5747
6252
|
}
|
|
5748
6253
|
/**
|
|
@@ -5836,7 +6341,9 @@ class ProgramManager {
|
|
|
5836
6341
|
throw Error("No private key provided and no private key set in the ProgramManager. Please set an account or provide a private key.");
|
|
5837
6342
|
}
|
|
5838
6343
|
// Check if the account has sufficient credits to pay for the transaction
|
|
5839
|
-
|
|
6344
|
+
if (!options.privateFee) {
|
|
6345
|
+
await this.checkFee(feeAddress.to_string(), tx.feeAmount());
|
|
6346
|
+
}
|
|
5840
6347
|
return await this.networkClient.submitTransaction(tx);
|
|
5841
6348
|
}
|
|
5842
6349
|
/**
|
|
@@ -5943,7 +6450,9 @@ class ProgramManager {
|
|
|
5943
6450
|
throw Error("No private key provided and no private key set in the ProgramManager. Please set an account or provide a private key.");
|
|
5944
6451
|
}
|
|
5945
6452
|
// Check if the account has sufficient credits to pay for the transaction
|
|
5946
|
-
|
|
6453
|
+
if (!options.privateFee) {
|
|
6454
|
+
await this.checkFee(feeAddress.to_string(), tx.feeAmount());
|
|
6455
|
+
}
|
|
5947
6456
|
return this.networkClient.submitTransaction(tx);
|
|
5948
6457
|
}
|
|
5949
6458
|
/**
|
|
@@ -6513,5 +7022,5 @@ async function initializeWasm() {
|
|
|
6513
7022
|
console.warn("initializeWasm is deprecated, you no longer need to use it");
|
|
6514
7023
|
}
|
|
6515
7024
|
|
|
6516
|
-
export { Account, AleoKeyProvider, AleoKeyProviderParams, AleoNetworkClient, BlockHeightSearch, CREDITS_PROGRAM_KEYS, KEY_STORE, NetworkRecordProvider, OfflineKeyProvider, OfflineSearchParams, PRIVATE_TO_PUBLIC_TRANSFER, PRIVATE_TRANSFER, PRIVATE_TRANSFER_TYPES, PUBLIC_TO_PRIVATE_TRANSFER, PUBLIC_TRANSFER, PUBLIC_TRANSFER_AS_SIGNER, ProgramManager, RECORD_DOMAIN, RecordScanner, SealanceMerkleTree, VALID_TRANSFER_TYPES, initializeWasm, logAndThrow };
|
|
7025
|
+
export { Account, AleoKeyProvider, AleoKeyProviderParams, AleoNetworkClient, BlockHeightSearch, CREDITS_PROGRAM_KEYS, KEY_STORE, NetworkRecordProvider, OfflineKeyProvider, OfflineSearchParams, PRIVATE_TO_PUBLIC_TRANSFER, PRIVATE_TRANSFER, PRIVATE_TRANSFER_TYPES, PUBLIC_TO_PRIVATE_TRANSFER, PUBLIC_TRANSFER, PUBLIC_TRANSFER_AS_SIGNER, ProgramManager, RECORD_DOMAIN, RecordScanner, SealanceMerkleTree, VALID_TRANSFER_TYPES, encryptAuthorization, encryptProvingRequest, encryptRegistrationRequest, encryptViewKey, initializeWasm, isProveApiErrorBody, isProvingResponse, logAndThrow };
|
|
6517
7026
|
//# sourceMappingURL=browser.js.map
|