Skip to content

Commit 3c5223d

Browse files
Merge pull request #1057 from ProvableHQ/feat/proving-requests
[Feature] Proving Requests
2 parents 1fdb815 + 149cbc3 commit 3c5223d

File tree

17 files changed

+810
-44
lines changed

17 files changed

+810
-44
lines changed

sdk/src/browser.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import { PlaintextArray} from "./models/plaintext/array.js";
2020
import { PlaintextLiteral} from "./models/plaintext/literal.js";
2121
import { PlaintextObject } from "./models/plaintext/plaintext.js";
2222
import { PlaintextStruct} from "./models/plaintext/struct.js";
23+
import { ProvingRequestJSON } from "./models/provingRequest.js";
24+
import { ProvingResponse } from "./models/provingResponse.js";
2325
import { RatificationJSON } from "./models/ratification.js";
2426
import { SolutionsJSON, SolutionJSON, PartialSolutionJSON } from "./models/solution.js";
2527
import { TransactionJSON } from "./models/transaction/transactionJSON.js";
@@ -51,7 +53,7 @@ async function initializeWasm() {
5153
console.warn("initializeWasm is deprecated, you no longer need to use it");
5254
}
5355

54-
export { ProgramManager } from "./program-manager.js";
56+
export { ProgramManager, ProvingRequestOptions, ExecuteOptions, FeeAuthorizationOptions, AuthorizationOptions } from "./program-manager.js";
5557

5658
export { logAndThrow } from "./utils.js";
5759

@@ -83,6 +85,7 @@ export {
8385
Program,
8486
ProgramManager as ProgramManagerBase,
8587
ProvingKey,
88+
ProvingRequest,
8689
RecordCiphertext,
8790
RecordPlaintext,
8891
Signature,
@@ -149,6 +152,8 @@ export {
149152
PlaintextObject,
150153
PlaintextStruct,
151154
ProgramImports,
155+
ProvingRequestJSON,
156+
ProvingResponse,
152157
RatificationJSON,
153158
RecordProvider,
154159
RecordSearchParams,

sdk/src/models/provingRequest.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { AuthorizationJSON } from "./authorization";
2+
3+
export interface ProvingRequestJSON {
4+
authorization: AuthorizationJSON;
5+
fee_authorization?: AuthorizationJSON;
6+
broadcast: boolean;
7+
}

sdk/src/models/provingResponse.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { TransactionJSON } from "./transaction/transactionJSON";
2+
3+
export interface ProvingResponse {
4+
transaction: TransactionJSON,
5+
broadcast?: boolean,
6+
}

sdk/src/program-manager.ts

Lines changed: 202 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
PrivateKey,
2222
Program,
2323
ProvingKey,
24+
ProvingRequest,
2425
VerifyingKey,
2526
Transaction,
2627
ProgramManager as WasmProgramManager,
@@ -107,6 +108,40 @@ interface FeeAuthorizationOptions {
107108
feeRecord?: RecordPlaintext,
108109
}
109110

111+
/**
112+
* Represents the options for executing a transaction in the Aleo network.
113+
* This interface is used to specify the parameters required for building and submitting an execution transaction.
114+
*
115+
* @property {string} programName - The name of the program containing the function to be executed.
116+
* @property {string} functionName - The name of the function to execute within the program.
117+
* @property {number} baseFee - The base fee to be paid for the transaction.
118+
* @property {number} priorityFee - The optional priority fee to be paid for the transaction.
119+
* @property {boolean} privateFee - If true, uses a private record to pay the fee; otherwise, uses the account's public credit balance.
120+
* @property {string[]} inputs - The inputs to the function being executed.
121+
* @property {RecordSearchParams} [recordSearchParams] - Optional parameters for searching for a record to pay the execution transaction fee.
122+
* @property {string | RecordPlaintext} [feeRecord] - Optional fee record to use for the transaction.
123+
* @property {PrivateKey} [privateKey] - Optional private key to use for the transaction.
124+
* @property {string | Program} [program] - Optional program source code to use for the transaction.
125+
* @property {string} uri - The URI send the ProvingRequest to.
126+
* @property {ProgramImports} [imports] - Optional programs that the program being executed imports.
127+
* @property {boolean} broadcast - Whether to broadcast the Transaction generated by the remove prover to the Aleo network.
128+
*/
129+
interface ProvingRequestOptions {
130+
programName: string;
131+
functionName: string;
132+
baseFee: number,
133+
priorityFee: number;
134+
privateFee: boolean;
135+
inputs: string[];
136+
recordSearchParams?: RecordSearchParams;
137+
feeRecord?: string | RecordPlaintext;
138+
privateKey?: PrivateKey;
139+
programSource?: string | Program;
140+
programImports?: ProgramImports;
141+
broadcast?: boolean;
142+
unchecked?: boolean;
143+
}
144+
110145
/**
111146
* The ProgramManager class is used to execute and deploy programs on the Aleo network and create value transfers.
112147
*/
@@ -316,13 +351,13 @@ class ProgramManager {
316351
try {
317352
feeRecord = privateFee
318353
? <RecordPlaintext>(
319-
await this.getCreditsRecord(
320-
priorityFee,
321-
[],
322-
feeRecord,
323-
recordSearchParams,
324-
)
325-
)
354+
await this.getCreditsRecord(
355+
priorityFee,
356+
[],
357+
feeRecord,
358+
recordSearchParams,
359+
)
360+
)
326361
: undefined;
327362
} catch (e: any) {
328363
logAndThrow(
@@ -530,13 +565,13 @@ class ProgramManager {
530565
try {
531566
feeRecord = privateFee
532567
? <RecordPlaintext>(
533-
await this.getCreditsRecord(
534-
priorityFee,
535-
[],
536-
feeRecord,
537-
recordSearchParams,
538-
)
539-
)
568+
await this.getCreditsRecord(
569+
priorityFee,
570+
[],
571+
feeRecord,
572+
recordSearchParams,
573+
)
574+
)
540575
: undefined;
541576
} catch (e: any) {
542577
logAndThrow(
@@ -790,6 +825,134 @@ class ProgramManager {
790825
);
791826
}
792827

828+
/**
829+
* Builds a `ProvingRequest` for submission to a prover for execution.
830+
*
831+
* @param {ProvingRequestOptions} options - The options for building the proving request
832+
* @returns {Promise<ProvingRequest>} - A promise that resolves to the transaction or an error.
833+
*
834+
* @example
835+
* /// Import the mainnet version of the sdk.
836+
* import { AleoKeyProvider, ProgramManager, NetworkRecordProvider } from "@provablehq/sdk/mainnet.js";
837+
*
838+
* // Create a new NetworkClient, KeyProvider, and RecordProvider.
839+
* const keyProvider = new AleoKeyProvider();
840+
* const recordProvider = new NetworkRecordProvider(account, networkClient);
841+
* keyProvider.useCache = true;
842+
*
843+
* // Initialize a ProgramManager with the key and record providers.
844+
* const programManager = new ProgramManager("https://api.explorer.provable.com/v1", keyProvider, recordProvider);
845+
*
846+
* // Build the proving request.
847+
* const provingRequest = await programManager.provingRequest({
848+
* programName: "credits.aleo",
849+
* functionName: "transfer_public",
850+
* baseFee: 100000,
851+
* priorityFee: 0,
852+
* privateFee: false,
853+
* inputs: [
854+
* "aleo1vwls2ete8dk8uu2kmkmzumd7q38fvshrht8hlc0a5362uq8ftgyqnm3w08",
855+
* "10000000u64",
856+
* ],
857+
* broadcast: false,
858+
* });
859+
*/
860+
async provingRequest(
861+
options: ProvingRequestOptions,
862+
): Promise<ProvingRequest> {
863+
// Destructure the options object to access the parameters.
864+
const {
865+
programName,
866+
functionName,
867+
baseFee,
868+
priorityFee,
869+
privateFee,
870+
inputs,
871+
recordSearchParams,
872+
broadcast = false,
873+
unchecked = false,
874+
} = options;
875+
876+
const privateKey = options.privateKey;
877+
let program = options.programSource;
878+
let feeRecord = options.feeRecord;
879+
let imports = options.programImports;
880+
881+
// Ensure the function exists on the network.
882+
if (program === undefined) {
883+
try {
884+
program = <string>(
885+
await this.networkClient.getProgram(programName)
886+
);
887+
} catch (e: any) {
888+
logAndThrow(
889+
`Error finding ${programName}. Network response: '${e.message}'. Please ensure you're connected to a valid Aleo network the program is deployed to the network.`,
890+
);
891+
}
892+
} else if (program instanceof Program) {
893+
program = program.toString();
894+
}
895+
896+
// Get the private key from the account if it is not provided in the parameters.
897+
let executionPrivateKey = privateKey;
898+
if (
899+
typeof privateKey === "undefined" &&
900+
typeof this.account !== "undefined"
901+
) {
902+
executionPrivateKey = this.account.privateKey();
903+
}
904+
905+
if (typeof executionPrivateKey === "undefined") {
906+
throw "No private key provided and no private key set in the ProgramManager";
907+
}
908+
909+
// Get the fee record from the account if it is not provided in the parameters.
910+
try {
911+
feeRecord = privateFee
912+
? <RecordPlaintext>(
913+
await this.getCreditsRecord(
914+
priorityFee,
915+
[],
916+
feeRecord,
917+
recordSearchParams,
918+
)
919+
)
920+
: undefined;
921+
} catch (e: any) {
922+
logAndThrow(
923+
`Error finding fee record. Record finder response: '${e.message}'. Please ensure you're connected to a valid Aleo network and a record with enough balance exists.`,
924+
);
925+
}
926+
927+
// Resolve the program imports if they exist.
928+
const numberOfImports = Program.fromString(program).getImports().length;
929+
if (numberOfImports > 0 && !imports) {
930+
try {
931+
imports = <ProgramImports>(
932+
await this.networkClient.getProgramImports(programName)
933+
);
934+
} catch (e: any) {
935+
logAndThrow(
936+
`Error finding program imports. Network response: '${e.message}'. Please ensure you're connected to a valid Aleo network and the program is deployed to the network.`,
937+
);
938+
}
939+
}
940+
941+
// Build and return the `ProvingRequest`.
942+
return await WasmProgramManager.buildProvingRequest(
943+
executionPrivateKey,
944+
program,
945+
functionName,
946+
inputs,
947+
baseFee,
948+
priorityFee,
949+
feeRecord,
950+
imports,
951+
broadcast,
952+
unchecked
953+
);
954+
}
955+
793956
/**
794957
* Builds a SnarkVM fee `Authorization` for `credits.aleo/fee_private` or `credits.aleo/fee_public`. If a record is provided `fee_private` will be executed, otherwise `fee_public` will be executed.
795958
*
@@ -1082,13 +1245,13 @@ class ProgramManager {
10821245
try {
10831246
feeRecord = privateFee
10841247
? <RecordPlaintext>(
1085-
await this.getCreditsRecord(
1086-
priorityFee,
1087-
[],
1088-
feeRecord,
1089-
recordSearchParams,
1090-
)
1091-
)
1248+
await this.getCreditsRecord(
1249+
priorityFee,
1250+
[],
1251+
feeRecord,
1252+
recordSearchParams,
1253+
)
1254+
)
10921255
: undefined;
10931256
} catch (e: any) {
10941257
logAndThrow(
@@ -1168,14 +1331,14 @@ class ProgramManager {
11681331
privateKey?: PrivateKey,
11691332
offlineQuery?: OfflineQuery,
11701333
): Promise<string> {
1171-
// Get the private key from the account if it is not provided in the parameters
1172-
let executionPrivateKey = privateKey;
1173-
if (
1174-
typeof privateKey === "undefined" &&
1175-
typeof this.account !== "undefined"
1176-
) {
1177-
executionPrivateKey = this.account.privateKey();
1178-
}
1334+
// Get the private key from the account if it is not provided in the parameters
1335+
let executionPrivateKey = privateKey;
1336+
if (
1337+
typeof privateKey === "undefined" &&
1338+
typeof this.account !== "undefined"
1339+
) {
1340+
executionPrivateKey = this.account.privateKey();
1341+
}
11791342

11801343
if (typeof executionPrivateKey === "undefined") {
11811344
throw "No private key provided and no private key set in the ProgramManager";
@@ -1368,13 +1531,13 @@ class ProgramManager {
13681531
}
13691532
feeRecord = privateFee
13701533
? <RecordPlaintext>(
1371-
await this.getCreditsRecord(
1372-
priorityFee,
1373-
nonces,
1374-
feeRecord,
1375-
recordSearchParams,
1376-
)
1377-
)
1534+
await this.getCreditsRecord(
1535+
priorityFee,
1536+
nonces,
1537+
feeRecord,
1538+
recordSearchParams,
1539+
)
1540+
)
13781541
: undefined;
13791542
} catch (e: any) {
13801543
logAndThrow(
@@ -2376,8 +2539,8 @@ function validateTransferType(transferType: string): string {
23762539
return VALID_TRANSFER_TYPES.has(transferType)
23772540
? transferType
23782541
: logAndThrow(
2379-
`Invalid transfer type '${transferType}'. Valid transfer types are 'private', 'privateToPublic', 'public', and 'publicToPrivate'.`,
2380-
);
2542+
`Invalid transfer type '${transferType}'. Valid transfer types are 'private', 'privateToPublic', 'public', and 'publicToPrivate'.`,
2543+
);
23812544
}
23822545

2383-
export { ProgramManager, AuthorizationOptions, FeeAuthorizationOptions, ExecuteOptions };
2546+
export { ProgramManager, AuthorizationOptions, FeeAuthorizationOptions, ExecuteOptions, ProvingRequestOptions };

sdk/src/wasm.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export {
2727
Program,
2828
ProgramManager,
2929
ProvingKey,
30+
ProvingRequest,
3031
RecordCiphertext,
3132
RecordPlaintext,
3233
Scalar,

sdk/tests/network-client.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,8 @@ describe("NodeConnection", () => {
323323
? testnetAcceptedTx
324324
: mainnetAcceptedTx
325325
: isTestnet
326-
? testnetRejectedTx
327-
: mainnetRejectedTx;
326+
? testnetRejectedTx
327+
: mainnetRejectedTx;
328328
}
329329

330330
it("should return confirmed transaction data for an accepted tx ID", async () => {

0 commit comments

Comments
 (0)