From c5f6fa20134f6a31a5231dbdd96d61352ce65eb8 Mon Sep 17 00:00:00 2001 From: Michael Turner Date: Thu, 27 Jul 2023 18:56:17 -0400 Subject: [PATCH] Add program execution to the Aleo Javascript SDK --- sdk/package.json | 1 + sdk/src/account.ts | 2 +- sdk/src/aleo_network_client.ts | 160 +++++++++++++++++++++++++++++---- sdk/src/index.ts | 14 ++- 4 files changed, 156 insertions(+), 21 deletions(-) diff --git a/sdk/package.json b/sdk/package.json index 639fa0726..d824e94d0 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -36,6 +36,7 @@ "homepage": "https://github.com/AleoHQ/sdk#readme", "dependencies": { "@aleohq/nodejs": "0.5.1", + "@aleohq/wasm": "0.5.1", "axios": "^1.1.3", "jsdoc": "^3.6.11", "unfetch": "^5.0.0" diff --git a/sdk/src/account.ts b/sdk/src/account.ts index c50dc0c8b..f486a01fe 100644 --- a/sdk/src/account.ts +++ b/sdk/src/account.ts @@ -5,7 +5,7 @@ import { ViewKey, PrivateKeyCiphertext, RecordCiphertext, -} from "@aleohq/nodejs"; +} from "@aleohq/wasm"; interface AccountParam { privateKey?: string; diff --git a/sdk/src/aleo_network_client.ts b/sdk/src/aleo_network_client.ts index 616f1b02c..ac9cd8572 100644 --- a/sdk/src/aleo_network_client.ts +++ b/sdk/src/aleo_network_client.ts @@ -1,6 +1,6 @@ import axios from "axios"; -import { Account, Block, Transaction, Transition } from "."; -import { RecordCiphertext, RecordPlaintext, PrivateKey } from "@aleohq/nodejs"; +import {Account, Block, CREDITS_PROGRAM_KEYS, Transaction, Transition} from "."; +import { RecordCiphertext, Program, ProvingKey, RecordPlaintext, PrivateKey, Transaction as wasmTransaction, VerifyingKey} from "@aleohq/wasm"; /** * Connection management class that encapsulates REST calls to publicly exposed endpoints of Aleo nodes. @@ -18,6 +18,7 @@ export class AleoNetworkClient { host: string; account: Account | undefined; + constructor(host: string) { this.host = host + "/testnet3"; } @@ -40,19 +41,30 @@ export class AleoNetworkClient { * @example * let account = connection.getAccount(); */ - getAccount(): Account | undefined { + getAccount(): Account | undefined { return this.account; } async fetchData( - url = "/", + url = "/", ): Promise { - try { - const response = await axios.get(this.host + url); - return response.data; - } catch (error) { - throw new Error("Error fetching data."); - } + try { + const response = await axios.get(this.host + url); + return response.data; + } catch (error) { + throw new Error("Error fetching data."); + } + } + + async fetchBytes( + url = "/", + ): Promise { + try { + const response = await axios.get(this.host + url, {responseType: 'arraybuffer'}); + return new Uint8Array(response.data); + } catch (error) { + throw new Error("Error fetching data."); + } } /** @@ -250,6 +262,88 @@ export class AleoNetworkClient { } } + /** + * Returns the proving and verifying keys for a specified function in an Aleo Program given the url of the prover and + * verifier keys + * + * @param {string} url of the proving key + * @param {string} url of the verifying key + * + * @returns {Promise<[ProvingKey, VerifyingKey] | Error>} Proving and verifying keys for the specified program + */ + async getFunctionKeys(prover_url: string, verifier_url: string): Promise<[ProvingKey, VerifyingKey] | Error> { + try { + const proving_key = ProvingKey.fromBytes(await this.fetchBytes(prover_url)) + const verifying_key = VerifyingKey.fromBytes(await this.fetchBytes(verifier_url)); + return [proving_key, verifying_key]; + } catch (error) { + throw new Error(`Error fetching fee proving and verifying keys from ${prover_url} and ${verifier_url}.`); + } + } + + /** + * Returns the proving and verifying keys for the fee function in the credits.aleo program + * + * @returns {Promise<[ProvingKey, VerifyingKey] | Error>} Proving and verifying keys for the fee function + */ + async feeKeys(): Promise<[ProvingKey, VerifyingKey] | Error> { + return await this.getFunctionKeys(CREDITS_PROGRAM_KEYS.fee.prover, CREDITS_PROGRAM_KEYS.fee.verifier); + } + + /** + * Returns the proving and verifying keys for the transfer_private function in the credits.aleo program + * + * @returns {Promise<[ProvingKey, VerifyingKey] | Error>} Proving and verifying keys for the transfer_private function + * */ + async transferPrivateKeys(): Promise<[ProvingKey, VerifyingKey] | Error> { + return await this.getFunctionKeys(CREDITS_PROGRAM_KEYS.transfer_private.prover, CREDITS_PROGRAM_KEYS.transfer_private.verifier); + } + + /** + * Returns the proving and verifying keys for the transfer_private_to_public function in the credits.aleo program + * + * @returns {Promise<[ProvingKey, VerifyingKey] | Error>} Proving and verifying keys for the transfer_private_to_public function + */ + async transferPrivateToPublicKeys(): Promise<[ProvingKey, VerifyingKey] | Error> { + return await this.getFunctionKeys(CREDITS_PROGRAM_KEYS.transfer_private_to_public.prover, CREDITS_PROGRAM_KEYS.transfer_private_to_public.verifier); + } + + /** + * Returns the proving and verifying keys for the transfer_public function in the credits.aleo program + * + * @returns {Promise<[ProvingKey, VerifyingKey] | Error>} Proving and verifying keys for the transfer_public function + */ + async transferPublicKeys(): Promise<[ProvingKey, VerifyingKey] | Error> { + return await this.getFunctionKeys(CREDITS_PROGRAM_KEYS.transfer_public.prover, CREDITS_PROGRAM_KEYS.transfer_public.verifier); + } + + /** + * Returns the proving and verifying keys for the transfer_public_to_private program in the credits.aleo program + * + * @returns {Promise<[ProvingKey, VerifyingKey] | Error>} Proving and verifying keys for the transfer_public_to_private function + */ + async transferPublicToPrivateKeys(): Promise<[ProvingKey, VerifyingKey] | Error> { + return await this.getFunctionKeys(CREDITS_PROGRAM_KEYS.transfer_public_to_private.prover, CREDITS_PROGRAM_KEYS.transfer_public_to_private.verifier); + } + + /** + * Returns the proving and verifying keys for the join function in the credits.aleo program + * + * @returns {Promise<[ProvingKey, VerifyingKey] | Error>} Proving and verifying keys for the join function + */ + async joinKeys(): Promise<[ProvingKey, VerifyingKey] | Error> { + return await this.getFunctionKeys(CREDITS_PROGRAM_KEYS.join.prover, CREDITS_PROGRAM_KEYS.join.verifier); + } + + /** + * Returns the proving and verifying keys for the split function in the credits.aleo program + * + * @returns {Promise<[ProvingKey, VerifyingKey] | Error>} Proving and verifying keys for the split function + */ + async splitKeys(): Promise<[ProvingKey, VerifyingKey] | Error> { + return await this.getFunctionKeys(CREDITS_PROGRAM_KEYS.split.prover, CREDITS_PROGRAM_KEYS.split.verifier); + } + /** * Attempts to find unspent records in the Aleo blockchain for a specified private key * @@ -268,15 +362,15 @@ export class AleoNetworkClient { * let records = connection.findUnspentRecords(startHeight, undefined, privateKey, undefined, maxMicrocredits); */ async findUnspentRecords( - startHeight: number, - endHeight: number | undefined, - privateKey: string | undefined, - amounts: number[] | undefined, - maxMicrocredits: number | undefined, + startHeight: number, + endHeight: number | undefined, + privateKey: string | undefined, + amounts: number[] | undefined, + maxMicrocredits: number | undefined, ): Promise | Error> { // Ensure start height is not negative if (startHeight < 0) { - throw new Error("Start height must be greater than or equal to 0"); + throw new Error("Start height must be greater than or equal to 0"); } // Initialize search parameters @@ -324,8 +418,8 @@ export class AleoNetworkClient { } // If the starting is greater than the ending height, return an error - if (startHeight > end ) { - throw new Error("Start height must be less than or equal to end height."); + if (startHeight > end) { + throw new Error("Start height must be less than or equal to end height."); } // Iterate through blocks in reverse order in chunks of 50 @@ -424,4 +518,34 @@ export class AleoNetworkClient { } return records; } + + async resolveProgramImports(program_source: string | Program): object { + const program = program_source instanceof Program ? program_source : Program.fromString(program_source); + program.getImports() + } + + /** + * Submit a execute or deployment transaction to the Aleo network + * + * @param transaction [wasmTransaction | string] - The transaction to submit to the network + * @returns {string | Error} - The transaction id of the submitted transaction or the resulting error + */ + async submitTransaction(transaction: wasmTransaction | string): Promise { + const transaction_string = transaction instanceof wasmTransaction ? transaction.toString() : transaction; + try { + const response = await axios + .post( + this.host + "/testnet3/transaction/broadcast", + transaction_string, + { + headers: { + "Content-Type": "application/json", + }, + }, + ) + return response.data; + } catch (error) { + throw new Error(`Error posting transaction: ${error}`); + } + } } diff --git a/sdk/src/index.ts b/sdk/src/index.ts index fede3e79c..1d11ab031 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -7,7 +7,17 @@ import { Output} from "./models/output"; import { Transaction } from "./models/transaction"; import { Transition } from "./models/transition"; import { DevelopmentClient } from "./development_client"; +import { Address, PrivateKey, Program, Signature, ViewKey} from '@aleohq/wasm'; -import { Address, PrivateKey, Signature, ViewKey } from "@aleohq/nodejs"; +const key_store = "https://testnet3.parameters.aleo.org/"; +const CREDITS_PROGRAM_KEYS = { + transfer_private: {prover: key_store + "transfer_private.prover.2a9a6f2", verifier: key_store + "transfer_private.verifier.3a59762" }, + transfer_private_to_public: {prover:key_store + "transfer_private_to_public.prover.cf3b952", "verifier":key_store + "transfer_private_to_public.verifier.3a59762"}, + transfer_public: {prover:key_store + "transfer_public.prover.1117f0a", verifier: "transfer_public.verifier.5bd459b"}, + transfer_public_to_private: {prover: key_store + "transfer_public_to_private.prover.7b763af", verifier: key_store + "transfer_public_to_private.verifier.25f6542"}, + join: {prover: key_store + "join.prover.da05baf", verifier: key_store + "join.verifier.1489109"}, + split: {prover: key_store + "split.prover.8c585f2", verifier: key_store + "split.verifier.8281688"}, + fee: {prover: key_store + "fee.prover.36542ce", verifier: key_store + "fee.verifier.2de311b"}, +} -export { Account, Address, AleoNetworkClient, Block, DevelopmentClient, Execution, Input, PrivateKey, Output, Signature, Transaction, Transition, ViewKey }; +export { Account, Address, AleoNetworkClient, Block, DevelopmentClient, Execution, Input, PrivateKey, Program, Output, Signature, Transaction, Transition, ViewKey, CREDITS_PROGRAM_KEYS}