@provablehq/sdk 0.6.9 → 0.6.11
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/README.md +200 -432
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/program-manager.d.ts +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +2 -2
- package/dist/worker.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -10,18 +10,18 @@
|
|
|
10
10
|
<a href="https://github.com/ProvableHQ/sdk#%EF%B8%8F-contributors"><img src="https://img.shields.io/badge/contributors-23-ee8449"/></a>
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
|
-
## Tools for Building Zero
|
|
13
|
+
## Tools for Building Zero-Knowledge Web Apps
|
|
14
14
|
|
|
15
|
-
The Aleo SDK is a collection of JavaScript libraries for building zero
|
|
16
|
-
and
|
|
15
|
+
The Aleo SDK is a collection of JavaScript libraries for building zero-knowledge web applications in both the browser
|
|
16
|
+
and Node.js.
|
|
17
17
|
|
|
18
18
|
## Overview
|
|
19
19
|
|
|
20
|
-
Aleo provides the ability to run programs
|
|
21
|
-
within the browser and all other levels of the web stack to build privacy
|
|
20
|
+
Aleo provides the ability to run programs with the power of zero-knowledge. The Aleo SDK provides the tools to use these programs
|
|
21
|
+
within the browser and all other levels of the web stack to build privacy-preserving applications.
|
|
22
22
|
|
|
23
23
|
The Aleo SDK provides the following functionality (Click to see examples):
|
|
24
|
-
1. [Aleo account
|
|
24
|
+
1. [Aleo account management](https://provable.tools/account)
|
|
25
25
|
2. [Web-based program execution and deployment](https://provable.tools/develop)
|
|
26
26
|
3. [Aleo credit transfers](https://provable.tools/transfer)
|
|
27
27
|
4. [Management of program state and data](https://provable.tools/record)
|
|
@@ -31,8 +31,8 @@ The Aleo SDK provides the following functionality (Click to see examples):
|
|
|
31
31
|
|
|
32
32
|
* [Installation](#Installation)
|
|
33
33
|
* [Usage](#Usage)
|
|
34
|
-
* [Zero
|
|
35
|
-
* [Create
|
|
34
|
+
* [Zero-Knowledge Web App Examples](#Zero-Knowledge-Web-App-Examples)
|
|
35
|
+
* [Create Leo App](#create-leo-app)
|
|
36
36
|
* [Provable.tools](#provabletools)
|
|
37
37
|
* [Create An Aleo Account](#1-create-an-aleo-account)
|
|
38
38
|
* [Execute Aleo Programs](#2-execute-aleo-programs)
|
|
@@ -58,54 +58,70 @@ The Aleo SDK provides the following functionality (Click to see examples):
|
|
|
58
58
|
* [Further Documentation](#further-documentation)
|
|
59
59
|
## Installation
|
|
60
60
|
|
|
61
|
+
### Clone the repository
|
|
62
|
+
|
|
63
|
+
To clone the repository, run:
|
|
64
|
+
|
|
65
|
+
`git clone git@github.com:ProvableHQ/sdk.git`
|
|
66
|
+
|
|
61
67
|
### NPM
|
|
62
68
|
|
|
63
69
|
To install the Aleo SDK from NPM run:
|
|
64
70
|
|
|
65
|
-
`npm install @provablehq/sdk` or `yarn add @provablehq/sdk`.
|
|
71
|
+
`npm install @provablehq/sdk` in your own project's root, or from within this repo run `cd sdk && yarn add @provablehq/sdk`.
|
|
66
72
|
|
|
67
73
|
### Build from source
|
|
68
74
|
|
|
69
|
-
To build the project from source, go to
|
|
75
|
+
To build the project from source, go to the project's root and execute:
|
|
76
|
+
|
|
77
|
+
`yarn build:all`
|
|
70
78
|
|
|
71
|
-
|
|
79
|
+
### Ensure compatibility with ES modules
|
|
80
|
+
|
|
81
|
+
In your project's `package.json`, ensure that the following line is added above `scripts`:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"type": "module",
|
|
86
|
+
}
|
|
87
|
+
```
|
|
72
88
|
|
|
73
|
-
## Getting Started: Zero
|
|
89
|
+
## Getting Started: Zero-Knowledge Web App Examples
|
|
74
90
|
|
|
75
|
-
### Create
|
|
76
|
-
A set of fully functional examples of zero
|
|
77
|
-
[create-
|
|
78
|
-
templates in common web frameworks such as React that can be used as a starting point for building zero
|
|
91
|
+
### Create Leo App
|
|
92
|
+
A set of fully functional examples of zero-knowledge web apps can be found in
|
|
93
|
+
[create-leo-app](https://github.com/ProvableHQ/sdk/tree/testnet3/create-leo-app). Create Leo App provides several web app
|
|
94
|
+
templates in common web frameworks such as React that can be used as a starting point for building zero-knowledge web apps.
|
|
79
95
|
|
|
80
|
-
Developers can get started immediately with create-
|
|
81
|
-
`npm create
|
|
96
|
+
Developers can get started immediately with create-leo-app by running:
|
|
97
|
+
`npm create leo-app@latest`
|
|
82
98
|
|
|
83
|
-
###
|
|
99
|
+
### provable.tools
|
|
84
100
|
|
|
85
101
|
Additionally, the SDK powers [provable.tools](https://provable.tools) - a React app that provides a graphical interface for most
|
|
86
102
|
of the functionality provided by the SDK and can be used as a reference for usage of the SDK. Source code for provable.tools
|
|
87
|
-
can be found [in the SDK repo here](https://github.com/ProvableHQ/sdk/tree/testnet3/website)
|
|
103
|
+
can be found [in the SDK repo here](https://github.com/ProvableHQ/sdk/tree/testnet3/website).
|
|
88
104
|
|
|
89
105
|
## Usage
|
|
90
106
|
|
|
91
107
|
## 1. Create an Aleo Account
|
|
92
108
|
|
|
93
|
-
The first step in operating a zero
|
|
109
|
+
The first step in operating a zero-knowledge web application is creating a private key which serves as a cryptographic
|
|
94
110
|
identity for a user. After a private key is generated, several keys that enable specialized methods of interacting with
|
|
95
111
|
Aleo programs can be derived.
|
|
96
112
|
|
|
97
113
|
These keys include:
|
|
98
114
|
#### Private Key
|
|
99
|
-
The `Private Key` can be treated as the identity of a user. It is used for critical functions like authorizing zero
|
|
100
|
-
program execution, decrypting private data, and proving ownership of data.
|
|
101
|
-
|
|
115
|
+
The `Private Key` can be treated as the identity of a user. It is used for critical functions like authorizing zero-knowledge
|
|
116
|
+
program execution, decrypting private data, and proving ownership of user data.
|
|
117
|
+
|
|
102
118
|
#### View Key
|
|
103
119
|
The `View Key` is derived from the private key and can be used to both decrypt encrypted data owned by a user and prove
|
|
104
120
|
ownership of that data.
|
|
105
121
|
#### Compute Key
|
|
106
122
|
The `Compute Key` can be used to trustlessly run applications and generate transactions on a user's behalf.
|
|
107
123
|
#### Address
|
|
108
|
-
The `Address` is a user's unique public identifier. It serves as an address for a user to receive both
|
|
124
|
+
The `Address` is a user's unique public identifier. It serves as an address for a user to receive both Aleo
|
|
109
125
|
credits and data from other zero-knowledge Aleo programs.
|
|
110
126
|
|
|
111
127
|
All of these keys can be created using the account object:
|
|
@@ -129,16 +145,16 @@ Please note that all keys are considered sensitive information and should be sto
|
|
|
129
145
|
Aleo programs provide the ability for users to make any input or output of a program private and prove that the program
|
|
130
146
|
was run correctly. Keeping program inputs and outputs private allows developers to build privacy into their applications.
|
|
131
147
|
|
|
132
|
-
Zero-
|
|
133
|
-
1. [Leo](https://
|
|
134
|
-
zero
|
|
135
|
-
|
|
136
|
-
grained control over the execution flow of zero
|
|
148
|
+
Zero-knowledge programs are written in one of two languages:
|
|
149
|
+
1. [Leo](https://docs.leo-lang.org/leo/language): A high-level, developer-friendly language for developing
|
|
150
|
+
zero-knowledge programs.
|
|
151
|
+
|
|
152
|
+
2. [Aleo Instructions](https://docs.leo-lang.org/aleo/language): A low-level language that provides developers with fine-grained control over the execution flow of zero-knowledge programs. Leo code is compiled into Aleo Instructions
|
|
137
153
|
under the hood.
|
|
138
154
|
|
|
139
|
-
Documentation for both languages can be found at [
|
|
155
|
+
Documentation for both languages can be found at [docs.leo-lang.org](https://docs.leo-lang.org/).
|
|
140
156
|
|
|
141
|
-
#### Hello
|
|
157
|
+
#### "Hello World" in Leo
|
|
142
158
|
```
|
|
143
159
|
// A simple program adding two numbers together
|
|
144
160
|
program helloworld.aleo {
|
|
@@ -149,11 +165,11 @@ program helloworld.aleo {
|
|
|
149
165
|
}
|
|
150
166
|
```
|
|
151
167
|
|
|
152
|
-
#### Hello
|
|
168
|
+
#### "Hello World" in Aleo Instructions
|
|
153
169
|
```
|
|
154
170
|
program helloworld.aleo;
|
|
155
171
|
|
|
156
|
-
// The
|
|
172
|
+
// The Leo code above compiles to the following Aleo Instructions:
|
|
157
173
|
function hello:
|
|
158
174
|
input r0 as u32.public;
|
|
159
175
|
input r1 as u32.private;
|
|
@@ -163,23 +179,23 @@ function hello:
|
|
|
163
179
|
|
|
164
180
|
### 2.2 Program Execution Model
|
|
165
181
|
|
|
166
|
-
The SDK provides the ability execute
|
|
182
|
+
The SDK provides the ability to execute Aleo programs 100% client-side within the browser.
|
|
167
183
|
|
|
168
|
-
The `ProgramManager` object encapsulates the functionality for executing programs and making zero
|
|
184
|
+
The `ProgramManager` object encapsulates the functionality for executing programs and making zero-knowledge proofs about
|
|
169
185
|
them. Under the hood it uses cryptographic code compiled from [SnarkVM](https://developer.aleo.org/aleo) into WebAssembly
|
|
170
|
-
with JavaScript bindings that allow execution of Aleo programs fully within the browser. Users interested in lower
|
|
171
|
-
details how this is achieved can visit the [aleo-wasm](https://
|
|
186
|
+
with JavaScript bindings that allow for the execution of Aleo programs fully within the browser. Users interested in lower-level
|
|
187
|
+
details on how this is achieved can visit the [aleo-wasm](https://www.npmjs.com/package/@provablehq/wasm) crate.
|
|
172
188
|
|
|
173
189
|
The basic execution flow of a program is as follows:
|
|
174
|
-
1. A web app is loaded with an instance of the `ProgramManager` object
|
|
175
|
-
2. The SDK wasm modules are loaded into the browser's WebAssembly runtime
|
|
176
|
-
2. An Aleo program in `Aleo Instructions` format is loaded into the `ProgramManager` as a wasm object
|
|
177
|
-
3. The web app provides a user input form for the program
|
|
178
|
-
4. The user submits the inputs and the zero
|
|
179
|
-
5. The result is returned to the user
|
|
180
|
-
6.
|
|
181
|
-
|
|
182
|
-
A diagramatic representation of the program execution flow is shown below
|
|
190
|
+
1. A web app is loaded with an instance of the `ProgramManager` object.
|
|
191
|
+
2. The SDK wasm modules are loaded into the browser's WebAssembly runtime.
|
|
192
|
+
2. An Aleo program in `Aleo Instructions` format is loaded into the `ProgramManager` as a wasm object.
|
|
193
|
+
3. The web app provides a user input form for the program.
|
|
194
|
+
4. The user submits the inputs and the zero-knowledge execution is performed entirely within the browser via WebAssembly.
|
|
195
|
+
5. The result is returned to the user.
|
|
196
|
+
6. A fully encrypted zero-knowledge transcript of the execution is optionally sent to the Aleo network.
|
|
197
|
+
|
|
198
|
+
A diagramatic representation of the program execution flow is shown below:
|
|
183
199
|
```mermaid
|
|
184
200
|
graph LR
|
|
185
201
|
p1[Leo Program]
|
|
@@ -198,14 +214,14 @@ graph LR
|
|
|
198
214
|
in-memory-program-."ZK result (Optional)".->Aleo-Network
|
|
199
215
|
```
|
|
200
216
|
|
|
201
|
-
### 2.3
|
|
217
|
+
### 2.3 Multithreading
|
|
202
218
|
|
|
203
|
-
You can enable
|
|
219
|
+
You can enable multithreading by calling the `initThreadPool` function. This will run the SDK on multiple workers, which significantly speeds up performance:
|
|
204
220
|
|
|
205
221
|
```typescript
|
|
206
222
|
import { Account, initThreadPool } from '@provablehq/sdk';
|
|
207
223
|
|
|
208
|
-
// Enables
|
|
224
|
+
// Enables multithreading
|
|
209
225
|
await initThreadPool();
|
|
210
226
|
|
|
211
227
|
// Create a new Aleo account
|
|
@@ -214,10 +230,11 @@ const account = new Account();
|
|
|
214
230
|
// Perform further program logic...
|
|
215
231
|
````
|
|
216
232
|
|
|
217
|
-
### 2.4 Local
|
|
218
|
-
|
|
233
|
+
### 2.4 Local program execution
|
|
234
|
+
|
|
235
|
+
A simple example of running the "hello world" program locally using Node.js and capturing its outputs is shown below:
|
|
219
236
|
```typescript
|
|
220
|
-
import { Account,
|
|
237
|
+
import { Account, ProgramManager } from '@provablehq/sdk';
|
|
221
238
|
|
|
222
239
|
/// Create the source for the "hello world" program
|
|
223
240
|
const program = "program helloworld.aleo;\n\nfunction hello:\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";
|
|
@@ -228,86 +245,103 @@ const account = new Account();
|
|
|
228
245
|
programManager.setAccount(account);
|
|
229
246
|
|
|
230
247
|
/// Get the response and ensure that the program executed correctly
|
|
231
|
-
const executionResponse = await programManager.
|
|
248
|
+
const executionResponse = await programManager.run(program, "hello", ["5u32", "5u32"]);
|
|
232
249
|
const result = executionResponse.getOutputs();
|
|
233
|
-
assert(result
|
|
250
|
+
assert.deepStrictEqual(result, ['10u32']);
|
|
234
251
|
```
|
|
235
252
|
|
|
236
|
-
### 2.5 Program execution on the Aleo
|
|
253
|
+
### 2.5 Program execution on the Aleo network
|
|
237
254
|
The SDK provides the ability to execute programs and store an encrypted transcript of the execution on the Aleo
|
|
238
255
|
network that anyone can trustlessly verify.
|
|
239
256
|
|
|
240
|
-
This process can be thought of being executed in the following steps:
|
|
241
|
-
1. A program is run locally
|
|
242
|
-
2. A proof that the program was executed correctly and that the outputs follow from the inputs is generated
|
|
257
|
+
This process can be thought of as being executed in the following steps:
|
|
258
|
+
1. A program is run locally.
|
|
259
|
+
2. A proof that the program was executed correctly and that the outputs follow from the inputs is generated.
|
|
243
260
|
3. A transcript of the proof is generated client-side containing encrypted proof data (see [Section 2.6](#4-managing-records-and-private-state))
|
|
244
|
-
and any public outputs or state the user of the program wishes to reveal
|
|
245
|
-
4. The proof transcript is posted to the Aleo network and verified by the Aleo validator nodes in a trustless manner
|
|
261
|
+
and any public outputs or state the user of the program wishes to reveal.
|
|
262
|
+
4. The proof transcript is posted to the Aleo network and verified by the Aleo validator nodes in a trustless manner.
|
|
246
263
|
5. If the proof is valid, it is stored and anyone can later verify the proof and read the outputs the author of the
|
|
247
264
|
program has chosen to make public. Private inputs will remain encrypted, but the author of the proof can also choose to
|
|
248
265
|
retrieve this encrypted state at any point and decrypt it locally for their own use.
|
|
249
266
|
|
|
250
|
-
Posting an execution to the Aleo
|
|
267
|
+
Posting an execution to the Aleo network serves as a globally trustless and verifiable record of a program execution as well as
|
|
251
268
|
any resulting state changes in private or public data.
|
|
252
269
|
|
|
253
|
-
A simple example of running the hello world program on the Aleo network is shown below:
|
|
270
|
+
A simple example of running the "hello world" program on the Aleo network is shown below:
|
|
254
271
|
```typescript
|
|
255
|
-
import { Account, AleoNetworkClient, NetworkRecordProvider, ProgramManager,
|
|
272
|
+
import { Account, AleoNetworkClient, NetworkRecordProvider, ProgramManager, AleoKeyProvider } from '@provablehq/sdk';
|
|
273
|
+
|
|
274
|
+
// Create an account
|
|
275
|
+
const account = new Account();
|
|
276
|
+
|
|
277
|
+
// Create a network client to connect to the Aleo network
|
|
278
|
+
const networkClient = new AleoNetworkClient("https://api.explorer.aleo.org/v1");
|
|
256
279
|
|
|
257
280
|
// Create a key provider that will be used to find public proving & verifying keys for Aleo programs
|
|
258
281
|
const keyProvider = new AleoKeyProvider();
|
|
259
282
|
keyProvider.useCache = true;
|
|
260
283
|
|
|
261
284
|
// Create a record provider that will be used to find records and transaction data for Aleo programs
|
|
262
|
-
const networkClient = new AleoNetworkClient("https://api.explorer.aleo.org/v1");
|
|
263
285
|
const recordProvider = new NetworkRecordProvider(account, networkClient);
|
|
264
286
|
|
|
265
287
|
// Initialize a program manager to talk to the Aleo network with the configured key and record providers
|
|
266
288
|
const programManager = new ProgramManager("https://api.explorer.aleo.org/v1", keyProvider, recordProvider);
|
|
267
289
|
|
|
268
|
-
//
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
290
|
+
// Set the account for the program manager
|
|
291
|
+
programManager.setAccount(account);
|
|
292
|
+
|
|
293
|
+
(async () => {
|
|
294
|
+
try {
|
|
295
|
+
// Provide a key search parameter to find the correct key for the program if they are stored in a memory cache
|
|
296
|
+
const keySearchParams = { cacheKey: "helloworld.aleo:main" };
|
|
297
|
+
console.log("Key search parameters set: ", keySearchParams);
|
|
298
|
+
|
|
299
|
+
// Execute the program using the options provided inline
|
|
300
|
+
const tx_id = await programManager.execute({
|
|
301
|
+
programName: "helloworld.aleo",
|
|
302
|
+
functionName: "main",
|
|
303
|
+
fee: 0.020,
|
|
304
|
+
privateFee: false, // Assuming a value for privateFee
|
|
305
|
+
inputs: ["5u32", "5u32"], // Example inputs matching the function definition
|
|
306
|
+
keySearchParams: keySearchParams,
|
|
307
|
+
privateKey: account.privateKey() // Set the private key
|
|
308
|
+
});
|
|
309
|
+
const transaction = await programManager.networkClient.getTransaction(tx_id);
|
|
310
|
+
console.log("Transaction details: ", transaction);
|
|
311
|
+
} catch (error) {
|
|
312
|
+
console.error("Error executing program:", error);
|
|
313
|
+
}
|
|
314
|
+
})();
|
|
281
315
|
```
|
|
282
316
|
|
|
283
317
|
A reader of the above example may notice the `RecordProvider` and `KeyProvider` classes that were not present in the local
|
|
284
318
|
execution example. The `KeyProvider` class helps users of the SDK find `Proving Keys` for programs. `Proving Keys`
|
|
285
|
-
allow zero
|
|
319
|
+
allow zero-knowledge proofs that the programs were executed correctly to be created. The `RecordProvider` class helps
|
|
286
320
|
find `Records` which are private data associated with programs that can be changed and updated throughout time.
|
|
287
321
|
These two concepts are explained in more detail below.
|
|
288
322
|
|
|
289
|
-
### 2.6 Program
|
|
323
|
+
### 2.6 Program proving keys & program records
|
|
290
324
|
|
|
291
|
-
Executing Aleo programs
|
|
325
|
+
Executing Aleo programs using zero-knowledge requires two additional pieces of information:
|
|
292
326
|
|
|
293
|
-
1. **Function Proving & Verifying Keys:** Proving and
|
|
294
|
-
program function is executed. These keys are public and unique for each function in a program. The proving
|
|
327
|
+
1. **Function Proving & Verifying Keys:** Proving and verifying keys are cryptographic keys that are generated when a
|
|
328
|
+
program function is executed. These keys are public and unique for each function in a program. The proving keys allows any party to
|
|
295
329
|
execute the program and generate a proof that the program was executed correctly. The verifying keys allow any party
|
|
296
330
|
to verify that the proof was generated correctly and the execution is correct. These keys are required to create the
|
|
297
|
-
zero
|
|
331
|
+
zero-knowledge property of program execution.
|
|
298
332
|
2. **Program Records:** Records are private state generated by a program belonging to a unique private keyholder. Records
|
|
299
|
-
are generated by a program's functions and can be changed and updated
|
|
333
|
+
are generated by a program's functions and can be changed and updated when a user runs various functions of the
|
|
300
334
|
program. These records are private by default and are used to manage updatable private state. One of the most clear
|
|
301
|
-
usages of records is to the `credits` record in the `credits.aleo
|
|
302
|
-
representing Aleo credits on the Aleo
|
|
303
|
-
on
|
|
335
|
+
usages of records is to the `credits` record in the `credits.aleo` program. Credits records are one of two official ways of
|
|
336
|
+
representing Aleo credits on the Aleo network and are used to pay all transaction fees on the network. More information
|
|
337
|
+
on records can be found in the [Records](#41-private-state-data--records) section below.
|
|
304
338
|
|
|
305
339
|
For this reason, all programs will need proving and verifying keys to operate and many functions in Aleo programs will
|
|
306
340
|
require records as inputs. To simplify the process of managing keys and records, the Aleo SDK provides two abstractions
|
|
307
341
|
for managing these concepts:
|
|
308
342
|
|
|
309
|
-
1. **KeyProvider:** When program functions execute, by default
|
|
310
|
-
make a zero
|
|
343
|
+
1. **KeyProvider:** When program functions execute, they will by default synthesize the proving and verifying keys needed to
|
|
344
|
+
make a zero-knowledge proof of the execution. However, these keys are large and expensive to generate. For this reason, applications may
|
|
311
345
|
want to store these keys and re-use them in future executions. The `KeyProvider` interface provides the ability for
|
|
312
346
|
users of the SDK to provide their own key storage and retrieval mechanism. The SDK provides a default implementation
|
|
313
347
|
of the `KeyProvider` interface via the `AleoKeyProvider` class.
|
|
@@ -319,14 +353,14 @@ searches the Aleo network for records uniquely belonging to a user.
|
|
|
319
353
|
The `ProgramManager` class is capable of taking a `KeyProvider` and `RecordProvider` as arguments and will use them to
|
|
320
354
|
find the correct keys and records for a program execution.
|
|
321
355
|
|
|
322
|
-
### 2.7 Deploy a new
|
|
356
|
+
### 2.7 Deploy a new program to the Aleo Network
|
|
323
357
|
|
|
324
|
-
The Aleo
|
|
325
|
-
to the network (as long as it doesn't already
|
|
358
|
+
The Aleo network contains a public registry of programs that can be executed by anyone. Any user can add an Aleo program
|
|
359
|
+
to the network (as long as it doesn't already exist) by paying a deployment fee in Aleo credits. The SDK
|
|
326
360
|
provides a simple interface for deploying programs to the Aleo network using the program manager.
|
|
327
361
|
|
|
328
362
|
```typescript
|
|
329
|
-
import { Account, AleoNetworkClient, NetworkRecordProvider, ProgramManager,
|
|
363
|
+
import { Account, AleoNetworkClient, NetworkRecordProvider, ProgramManager, AleoKeyProvider} from '@provablehq/sdk';
|
|
330
364
|
|
|
331
365
|
// Create a key provider that will be used to find public proving & verifying keys for Aleo programs
|
|
332
366
|
const keyProvider = new AleoKeyProvider();
|
|
@@ -350,7 +384,7 @@ programManager.setAccount(account)
|
|
|
350
384
|
const program = "program hello_hello.aleo;\n\nfunction hello:\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";
|
|
351
385
|
|
|
352
386
|
// Define a fee to pay to deploy the program
|
|
353
|
-
const fee =
|
|
387
|
+
const fee = 3.8; // 3.8 Aleo credits
|
|
354
388
|
|
|
355
389
|
// Deploy the program to the Aleo network
|
|
356
390
|
const tx_id = await programManager.deploy(program, fee);
|
|
@@ -359,7 +393,7 @@ const tx_id = await programManager.deploy(program, fee);
|
|
|
359
393
|
const transaction = await programManager.networkClient.getTransaction(tx_id);
|
|
360
394
|
```
|
|
361
395
|
|
|
362
|
-
The NetworkRecordProvider will attempt to scan the network for a fee record for the account provided. Doing a recent
|
|
396
|
+
The `NetworkRecordProvider` will attempt to scan the network for a fee record for the account provided. Doing a recent
|
|
363
397
|
public transfer to the deploying account will ensure a record is found quickly, or you can provide a fee record manually
|
|
364
398
|
by [scanning](https://developer.aleo.org/testnet/getting_started/deploy_execute/#scan) for a record and passing it as a
|
|
365
399
|
string.
|
|
@@ -372,302 +406,35 @@ const feeRecord = "{ owner: aleo1xxx...xxx.private, microcredits: 2000000u64.p
|
|
|
372
406
|
const tx_id = await programManager.deploy(program, fee, undefined, feeRecord);
|
|
373
407
|
```
|
|
374
408
|
|
|
375
|
-
### 2.8 React
|
|
409
|
+
### 2.8 React example
|
|
376
410
|
|
|
377
|
-
The above concepts can be tied together in a concrete example of a
|
|
411
|
+
The above concepts can be tied together in a concrete example of a single-page web app. This example can be installed in one
|
|
378
412
|
step by running:
|
|
379
413
|
|
|
380
|
-
`npm create
|
|
414
|
+
`npm create leo-app@latest`
|
|
381
415
|
|
|
382
|
-
|
|
416
|
+
You will then be prompted to select either Vanilla, React, or Node.js as the template for the project. For this example, select Vanilla.
|
|
383
417
|
|
|
384
|
-
Program execution
|
|
385
|
-
webworkers.
|
|
418
|
+
#### Program execution
|
|
386
419
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
A worker file that performs the execution can be created as follows:
|
|
391
|
-
`worker.js`
|
|
392
|
-
```jsx
|
|
393
|
-
import * as aleo from "@provablehq/sdk";
|
|
394
|
-
|
|
395
|
-
// Threads are then initialized to execute the program in parallel using multithreading
|
|
396
|
-
await aleo.initThreadPool();
|
|
397
|
-
|
|
398
|
-
/// The program manager is initialized with a key provider and a record provider
|
|
399
|
-
const defaultHost = "https://api.explorer.aleo.org/v1";
|
|
400
|
-
const keyProvider = new aleo.AleoKeyProvider();
|
|
401
|
-
const recordProvider = new aleo.NetworkRecordProvider(new Account(), "https://api.explorer.aleo.org/v1");
|
|
402
|
-
const programManager = new aleo.ProgramManager(
|
|
403
|
-
defaultHost,
|
|
404
|
-
keyProvider,
|
|
405
|
-
recordProvider,
|
|
406
|
-
);
|
|
407
|
-
|
|
408
|
-
// The key provider is set to use an in-memory cache to store keys
|
|
409
|
-
keyProvider.useCache(true);
|
|
410
|
-
|
|
411
|
-
self.postMessage({
|
|
412
|
-
type: "ALEO_WORKER_READY",
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
// The program is executed when specific events are dispatched and then communicates the result to the main thread
|
|
416
|
-
// when execution has finished
|
|
417
|
-
let lastLocalProgram = null;
|
|
418
|
-
self.addEventListener("message", (ev) => {
|
|
419
|
-
if (ev.data.type === "ALEO_EXECUTE_PROGRAM_LOCAL") {
|
|
420
|
-
const {localProgram, aleoFunction, inputs, privateKey} = ev.data;
|
|
421
|
-
|
|
422
|
-
console.log("Web worker: Executing function locally...");
|
|
423
|
-
let startTime = performance.now();
|
|
424
|
-
|
|
425
|
-
(async function () {
|
|
426
|
-
try {
|
|
427
|
-
// Ensure the program is valid and that it contains the function specified
|
|
428
|
-
const program = programManager.createProgramFromSource(localProgram);
|
|
429
|
-
const program_id = program.id();
|
|
430
|
-
if (!program.hasFunction(aleoFunction)) {
|
|
431
|
-
throw `Program ${program_id} does not contain function ${aleoFunction}`;
|
|
432
|
-
}
|
|
433
|
-
const cacheKey = `${program_id}:${aleoFunction}`;
|
|
434
|
-
|
|
435
|
-
// Get the program imports
|
|
436
|
-
const imports =
|
|
437
|
-
programManager.networkClient.getProgramImports(localProgram);
|
|
438
|
-
|
|
439
|
-
// Get the proving and verifying keys for the function
|
|
440
|
-
if (lastLocalProgram !== localProgram) {
|
|
441
|
-
const keys = programManager.executionEngine.synthesizeKeypair(
|
|
442
|
-
localProgram,
|
|
443
|
-
aleoFunction,
|
|
444
|
-
);
|
|
445
|
-
programManager.keyProvider.cacheKeys(cacheKey, [
|
|
446
|
-
keys.provingKey(),
|
|
447
|
-
keys.verifyingKey(),
|
|
448
|
-
]);
|
|
449
|
-
lastLocalProgram = localProgram;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// Pass the cache key to the execute function
|
|
453
|
-
const keyParams = new aleo.AleoKeyProviderParams({
|
|
454
|
-
cacheKey: cacheKey,
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
// Execute the function locally
|
|
458
|
-
let response = await programManager.executeOffline(
|
|
459
|
-
localProgram,
|
|
460
|
-
aleoFunction,
|
|
461
|
-
inputs,
|
|
462
|
-
imports,
|
|
463
|
-
keyParams,
|
|
464
|
-
undefined,
|
|
465
|
-
undefined,
|
|
466
|
-
aleo.PrivateKey.from_string(privateKey),
|
|
467
|
-
);
|
|
468
|
-
|
|
469
|
-
// Return the outputs to the main thread
|
|
470
|
-
self.postMessage({
|
|
471
|
-
type: "OFFLINE_EXECUTION_COMPLETED",
|
|
472
|
-
outputs,
|
|
473
|
-
});
|
|
474
|
-
} catch (error) {
|
|
475
|
-
console.error(error);
|
|
476
|
-
self.postMessage({
|
|
477
|
-
type: "ERROR",
|
|
478
|
-
errorMessage: error.toString(),
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
})();
|
|
482
|
-
}
|
|
483
|
-
});
|
|
484
|
-
```
|
|
420
|
+
Program execution is a computationally-expensive process. For this reason, it is recommended to execute programs in
|
|
421
|
+
web workers. Create-Leo-App will automatically create a web worker for you that performs the execution called `worker.js`.
|
|
485
422
|
|
|
486
|
-
The WebWorker can then be initialized in worker provider component which uses React effects
|
|
487
423
|
|
|
488
|
-
|
|
489
|
-
import { useEffect, useState } from "react";
|
|
490
|
-
import WorkerContext from "./WorkerContext";
|
|
491
|
-
|
|
492
|
-
const WorkerProvider = ({ children }) => {
|
|
493
|
-
const [worker, setWorker] = useState(null);
|
|
494
|
-
const [workerReady, setWorkerReady] = useState(false);
|
|
495
|
-
|
|
496
|
-
useEffect(() => {
|
|
497
|
-
let worker = new Worker(new URL("./worker.js", import.meta.url), {
|
|
498
|
-
type: "module",
|
|
499
|
-
});
|
|
500
|
-
setWorker(worker);
|
|
501
|
-
|
|
502
|
-
worker.onmessage = (event) => {
|
|
503
|
-
if (event.data.type === "ALEO_WORKER_READY") {
|
|
504
|
-
setWorkerReady(true);
|
|
505
|
-
}
|
|
506
|
-
};
|
|
507
|
-
|
|
508
|
-
return () => {
|
|
509
|
-
worker.terminate();
|
|
510
|
-
};
|
|
511
|
-
}, []);
|
|
512
|
-
|
|
513
|
-
if (!workerReady) {
|
|
514
|
-
return (
|
|
515
|
-
<>
|
|
516
|
-
<div className="spinner">
|
|
517
|
-
<div className="dot1"></div>
|
|
518
|
-
</div>
|
|
519
|
-
</>
|
|
520
|
-
);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
return (
|
|
524
|
-
<WorkerContext.Provider value={worker}>
|
|
525
|
-
{children}
|
|
526
|
-
</WorkerContext.Provider>
|
|
527
|
-
);
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
export default WorkerProvider;
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
</details>
|
|
534
|
-
|
|
535
|
-
Using both webworkers and a wasm initialization in a React hook, a single page app can be created that executes
|
|
536
|
-
Aleo zero knowledge programs.
|
|
537
|
-
|
|
538
|
-
<details>
|
|
539
|
-
<summary>Example App.jsx Implementing Zero Knowledge Program Execution</summary>
|
|
540
|
-
|
|
541
|
-
```jsx
|
|
542
|
-
import { useEffect, useState } from "react";
|
|
543
|
-
import reactLogo from "./assets/react.svg";
|
|
544
|
-
import aleoLogo from "./assets/aleo.png";
|
|
545
|
-
import "./App.css";
|
|
546
|
-
import { useAleoWASM } from "./aleo-wasm-hook";
|
|
547
|
-
|
|
548
|
-
function App() {
|
|
549
|
-
const [count, setCount] = useState(0);
|
|
550
|
-
const aleo = useAleoWASM();
|
|
551
|
-
const [account, setAccount] = useState(null);
|
|
552
|
-
const [loading, setLoading] = useState(false);
|
|
553
|
-
|
|
554
|
-
const generateAccount = () => {
|
|
555
|
-
setAccount(new aleo.PrivateKey());
|
|
556
|
-
};
|
|
557
|
-
|
|
558
|
-
const [worker, setWorker] = useState(null);
|
|
559
|
-
|
|
560
|
-
useEffect(() => {
|
|
561
|
-
if (worker === null) {
|
|
562
|
-
const spawnedWorker = spawnWorker();
|
|
563
|
-
setWorker(spawnedWorker);
|
|
564
|
-
return () => {
|
|
565
|
-
spawnedWorker.terminate();
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
|
-
}, []);
|
|
569
|
-
|
|
570
|
-
function spawnWorker() {
|
|
571
|
-
return new Worker(new URL("workers/worker.js", import.meta.url), {
|
|
572
|
-
type: "module",
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
function postMessagePromise(worker, message) {
|
|
577
|
-
return new Promise((resolve, reject) => {
|
|
578
|
-
worker.onmessage = (event) => {
|
|
579
|
-
resolve(event.data);
|
|
580
|
-
};
|
|
581
|
-
worker.onerror = (error) => {
|
|
582
|
-
reject(error);
|
|
583
|
-
};
|
|
584
|
-
worker.postMessage(message);
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
async function execute() {
|
|
589
|
-
const hello_hello_program =
|
|
590
|
-
"program hello_hello.aleo;\n" +
|
|
591
|
-
"\n" +
|
|
592
|
-
"function hello:\n" +
|
|
593
|
-
" input r0 as u32.public;\n" +
|
|
594
|
-
" input r1 as u32.private;\n" +
|
|
595
|
-
" add r0 r1 into r2;\n" +
|
|
596
|
-
" output r2 as u32.private;\n";
|
|
597
|
-
|
|
598
|
-
setLoading(true);
|
|
599
|
-
const result = await postMessagePromise(worker, {
|
|
600
|
-
type: "ALEO_EXECUTE_PROGRAM_LOCAL",
|
|
601
|
-
localProgram: hello_hello_program,
|
|
602
|
-
aleoFunction: "hello",
|
|
603
|
-
inputs: ["5u32", "5u32"],
|
|
604
|
-
privateKey: account.to_string(),
|
|
605
|
-
});
|
|
606
|
-
setLoading(false);
|
|
607
|
-
|
|
608
|
-
alert(JSON.stringify(result));
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
return (
|
|
612
|
-
<>
|
|
613
|
-
<div>
|
|
614
|
-
<a href="https://aleo.org" target="_blank">
|
|
615
|
-
<img src={aleoLogo} className="logo" alt="Aleo logo" />
|
|
616
|
-
</a>
|
|
617
|
-
<a href="https://react.dev" target="_blank">
|
|
618
|
-
<img src={reactLogo} className="logo react" alt="React logo" />
|
|
619
|
-
</a>
|
|
620
|
-
</div>
|
|
621
|
-
<h1>Aleo + React</h1>
|
|
622
|
-
<div className="card">
|
|
623
|
-
<button onClick={() => setCount((count) => count + 1)}>
|
|
624
|
-
count is {count}
|
|
625
|
-
</button>
|
|
626
|
-
<p>
|
|
627
|
-
<button onClick={generateAccount}>
|
|
628
|
-
{account
|
|
629
|
-
? `Account is ${JSON.stringify(account.to_string())}`
|
|
630
|
-
: `Click to generate account`}
|
|
631
|
-
</button>
|
|
632
|
-
</p>
|
|
633
|
-
<p>
|
|
634
|
-
<button disabled={!account || loading} onClick={execute}>
|
|
635
|
-
{loading
|
|
636
|
-
? `Executing...check console for details...`
|
|
637
|
-
: `Execute hello_hello.aleo`}
|
|
638
|
-
</button>
|
|
639
|
-
</p>
|
|
640
|
-
<p>
|
|
641
|
-
Edit <code>src/App.jsx</code> and save to test HMR
|
|
642
|
-
</p>
|
|
643
|
-
</div>
|
|
644
|
-
<p className="read-the-docs">
|
|
645
|
-
Click on the Aleo and React logos to learn more
|
|
646
|
-
</p>
|
|
647
|
-
</>
|
|
648
|
-
);
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
export default App;
|
|
652
|
-
```
|
|
653
|
-
</details>
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
A full example of this implementation can be found [here](https://github.com/ProvableHQ/sdk/blob/testnet3/create-aleo-app/template-react/src/App.jsx)
|
|
424
|
+
A full example of this implementation can be found [here](https://github.com/ProvableHQ/sdk/tree/testnet3/create-leo-app/template-vanilla)
|
|
657
425
|
|
|
658
426
|
## 3. Aleo Credit Transfers
|
|
659
427
|
|
|
660
|
-
### 3.1 Aleo
|
|
428
|
+
### 3.1 Aleo credits
|
|
661
429
|
|
|
662
|
-
|
|
663
|
-
execution on the Aleo network.
|
|
430
|
+
Aleo Credits are used to access blockspace and computational resources on the network, with users paying Credits to submit transactions and have them processed.
|
|
664
431
|
|
|
665
|
-
Aleo credits are defined in the [credits.aleo](https://
|
|
666
|
-
deployed to the Aleo
|
|
432
|
+
Aleo credits are defined in the [credits.aleo](https://explorer.aleo.org/program/credits.aleo) program. This program is
|
|
433
|
+
deployed to the Aleo network and defines data structures representing Aleo credits and the functions used to manage them.
|
|
667
434
|
|
|
668
|
-
There are two ways to hold Aleo credits
|
|
435
|
+
There are two ways to hold Aleo credits:
|
|
669
436
|
|
|
670
|
-
#### 1 - Private balances via
|
|
437
|
+
#### 1 - Private balances via `credits.aleo` records
|
|
671
438
|
The first method is owning a `credits` record which enables a participant in the Aleo
|
|
672
439
|
network to hold a private balance of Aleo credits.
|
|
673
440
|
```
|
|
@@ -676,11 +443,11 @@ record credits:
|
|
|
676
443
|
microcredits as u64.private;
|
|
677
444
|
```
|
|
678
445
|
|
|
679
|
-
A user's total private credits balance will consist of all unspent `credits` records owned by the user with a
|
|
446
|
+
A user's total private credits balance will consist of all unspent `credits` records owned by the user with a non-zero
|
|
680
447
|
`microcredits` value.
|
|
681
448
|
|
|
682
|
-
#### 2 - Public balances via credits.aleo account
|
|
683
|
-
The second is by holding a `balance` in the `account` mapping in the `credits.aleo` program on the Aleo
|
|
449
|
+
#### 2 - Public balances via `credits.aleo` account mappings
|
|
450
|
+
The second method is by holding a `balance` in the `account` mapping in the `credits.aleo` program on the Aleo network.
|
|
684
451
|
|
|
685
452
|
```
|
|
686
453
|
mapping account:
|
|
@@ -688,21 +455,21 @@ mapping account:
|
|
|
688
455
|
value microcredits as u64.public;
|
|
689
456
|
```
|
|
690
457
|
|
|
691
|
-
The total public credits balance of a user is the value of account mapping at the user's address. Users can hold both private and public balances simultaneously.
|
|
458
|
+
The total public credits balance of a user is the value of the account mapping at the user's address. Users can hold both private and public balances simultaneously.
|
|
692
459
|
|
|
693
|
-
More information about `records` and `mappings` and how they related to private and public balances are explained in the
|
|
460
|
+
More information about `records` and `mappings` and how they are related to private and public balances are explained in the
|
|
694
461
|
[Managing Program Data and Private State](#4-managing-program-data-and-private-state) section.
|
|
695
462
|
|
|
696
|
-
### 3.2
|
|
697
|
-
The `ProgramManager` allows transfers of
|
|
463
|
+
### 3.2 Transferring Aleo credits
|
|
464
|
+
The `ProgramManager` allows transfers of Aleo credits via the `transfer` method. This function executes the `credits.aleo`
|
|
698
465
|
program under the hood.
|
|
699
466
|
|
|
700
467
|
There are four transfer functions available.
|
|
701
468
|
|
|
702
|
-
#### 1. transfer_private
|
|
469
|
+
#### 1. `transfer_private`
|
|
703
470
|
|
|
704
|
-
Takes a `credits` record
|
|
705
|
-
to a new record owned by the receiver. This function is %
|
|
471
|
+
Takes a `credits` record owned by the sender, subtracts an amount from it, and adds that amount
|
|
472
|
+
to a new record owned by the receiver. This function is 100% private and does not affect the `account` mapping.
|
|
706
473
|
|
|
707
474
|
```mermaid
|
|
708
475
|
graph LR
|
|
@@ -713,9 +480,10 @@ graph LR
|
|
|
713
480
|
|
|
714
481
|
```
|
|
715
482
|
|
|
716
|
-
#### 2. transfer_private_to_public
|
|
717
|
-
|
|
718
|
-
|
|
483
|
+
#### 2. `transfer_private_to_public`
|
|
484
|
+
|
|
485
|
+
Takes a `credits` record owned by the sender, subtracts an amount from it, and adds
|
|
486
|
+
that amount to the `account` mapping of the receiver. This function is 50% private and 50% public. It consumes a record
|
|
719
487
|
as a private input and generates a public balance in the `account` mapping entry belonging to the receiver.
|
|
720
488
|
|
|
721
489
|
```mermaid
|
|
@@ -728,9 +496,9 @@ graph LR
|
|
|
728
496
|
t1--amount 3000u64-->m1
|
|
729
497
|
```
|
|
730
498
|
|
|
731
|
-
#### 3. transfer_public
|
|
499
|
+
#### 3. `transfer_public`
|
|
732
500
|
|
|
733
|
-
Subtracts an amount of `credits` stored in the `account` mapping of the `credits.aleo program
|
|
501
|
+
Subtracts an amount of `credits` stored in the `account` mapping of the `credits.aleo` program, and
|
|
734
502
|
adds that amount to the `account` mapping of the receiver. This function is 100% public and does not consume or generate
|
|
735
503
|
any records.
|
|
736
504
|
|
|
@@ -747,9 +515,10 @@ graph LR
|
|
|
747
515
|
end
|
|
748
516
|
```
|
|
749
517
|
|
|
750
|
-
#### 4. transfer_public_to_private
|
|
518
|
+
#### 4. `transfer_public_to_private`
|
|
519
|
+
|
|
751
520
|
Subtracts an amount `credits` stored in the `account` mapping of the `credits.aleo program`
|
|
752
|
-
and adds that amount to a new private record owned by the receiver. This function is %
|
|
521
|
+
and adds that amount to a new private record owned by the receiver. This function is 50% private and 50% public.
|
|
753
522
|
It publicly consumes a balance in the `account` mapping entry belonging to the sender and generates a private record
|
|
754
523
|
as a private output.
|
|
755
524
|
|
|
@@ -771,7 +540,7 @@ All four of these functions can be used to transfer credits between users via th
|
|
|
771
540
|
`ProgramManager` by specifying the transfer type as the third argument.
|
|
772
541
|
|
|
773
542
|
```typescript
|
|
774
|
-
import { Account, ProgramManager, AleoKeyProvider, NetworkRecordProvider, AleoNetworkClient } from '@
|
|
543
|
+
import { Account, ProgramManager, AleoKeyProvider, NetworkRecordProvider, AleoNetworkClient } from '@provablehq/sdk';
|
|
775
544
|
|
|
776
545
|
// Create a new NetworkClient, KeyProvider, and RecordProvider
|
|
777
546
|
const account = Account.from_string({privateKey: "user1PrivateKey"});
|
|
@@ -812,7 +581,7 @@ public_balance = programManager.networkClient.getMappingValue("credits.aleo", US
|
|
|
812
581
|
assert(public_balance === 0);
|
|
813
582
|
```
|
|
814
583
|
|
|
815
|
-
### 3.2 Checking
|
|
584
|
+
### 3.2 Checking public balances
|
|
816
585
|
As shown above, a public balance of any address can be checked with `getMappingValue` function of the `NetworkClient`.
|
|
817
586
|
|
|
818
587
|
```typescript
|
|
@@ -823,19 +592,19 @@ const public_balance = networkClient.getMappingValue("credits.aleo", USER_1_ADDR
|
|
|
823
592
|
|
|
824
593
|
## 4. Managing Program Data and Private State
|
|
825
594
|
|
|
826
|
-
### 4.1 Private
|
|
827
|
-
Records
|
|
595
|
+
### 4.1 Private state data: records
|
|
596
|
+
Records are analogous to the concept of [UTXOs](https://en.wikipedia.org/wiki/Unspent_transaction_output). When a record is
|
|
828
597
|
created by a program, it can then be consumed later by the same program as an input to a function. Once a record is used
|
|
829
|
-
as input, it is considered consumed and cannot be used again. In many cases a new record will be created from the output
|
|
598
|
+
as an input, it is considered consumed and cannot be used again. In many cases a new record will be created from the output
|
|
830
599
|
of the function. Records are private by default and are associated with a single Aleo program and a single private key
|
|
831
600
|
representing a user.
|
|
832
601
|
|
|
833
|
-
### 4.2 Record
|
|
602
|
+
### 4.2 Record usage example: private value transfers
|
|
834
603
|
|
|
835
604
|
A straightforward example of a usage of records in a program can be demonstrated by explaining the process of private
|
|
836
|
-
value transfers of
|
|
605
|
+
value transfers of Aleo credits on the Aleo network.
|
|
837
606
|
|
|
838
|
-
Aleo credits are
|
|
607
|
+
Aleo credits are used for all on-chain execution and deployment fees. Credits can be public
|
|
839
608
|
or private. Private credits are represented by the `credits` record in the [credits.aleo](https://www.aleo.network/programs/credits.aleo)
|
|
840
609
|
program.
|
|
841
610
|
|
|
@@ -865,10 +634,10 @@ function transfer_private:
|
|
|
865
634
|
output r5 as credits.record;
|
|
866
635
|
```
|
|
867
636
|
|
|
868
|
-
The `transfer_private` function can be graphically represented by the graph below. In the graph the first record
|
|
869
|
-
is
|
|
637
|
+
The `transfer_private` function can be graphically represented by the graph below. In the graph the first record, Record 1,
|
|
638
|
+
is consumed and can never be used again. From the data in Record 1, two more records are created. One containing
|
|
870
639
|
the intended amount for the recipient which is now owned by the recipient and another containing the remaining credits
|
|
871
|
-
which
|
|
640
|
+
which are sent back to the sender.
|
|
872
641
|
|
|
873
642
|
```mermaid
|
|
874
643
|
graph LR
|
|
@@ -880,8 +649,8 @@ graph LR
|
|
|
880
649
|
p1--Credits Record 3-->R1[Recipient Address]
|
|
881
650
|
```
|
|
882
651
|
|
|
883
|
-
This chain of ownership is tracked by the Aleo
|
|
884
|
-
|
|
652
|
+
This chain of ownership is tracked by the Aleo blockchain when users choose to submit their transactions to the Aleo
|
|
653
|
+
network. This allows other users who receive records to receive the updated data and verify that this data was
|
|
885
654
|
provably generated by the intended program.
|
|
886
655
|
|
|
887
656
|
What this process allows is a private chain of state to be created between multiple users. In the context of value
|
|
@@ -901,7 +670,7 @@ The above state chain would be executed in the following way using the SDK:
|
|
|
901
670
|
#### Step 1 - User 1 sends a private value transfer to User 2
|
|
902
671
|
```typescript
|
|
903
672
|
// USER 1
|
|
904
|
-
import { Account, ProgramManager, AleoKeyProvider, NetworkRecordProvider, AleoNetworkClient } from '@
|
|
673
|
+
import { Account, ProgramManager, AleoKeyProvider, NetworkRecordProvider, AleoNetworkClient } from '@provablehq/sdk';
|
|
905
674
|
|
|
906
675
|
// Create a new NetworkClient, KeyProvider, and RecordProvider
|
|
907
676
|
const account = Account.from_string({privateKey: "user1PrivateKey"});
|
|
@@ -914,15 +683,15 @@ const USER_2_ADDRESS = "user2Address";
|
|
|
914
683
|
const programManager = new ProgramManager("https://api.explorer.aleo.org/v1", keyProvider, recordProvider);
|
|
915
684
|
programManager.setAccount(account);
|
|
916
685
|
|
|
917
|
-
/// Send private transfer to
|
|
686
|
+
/// Send private transfer to User 2
|
|
918
687
|
const tx_id = await programManager.transfer(1, USER_2_ADDRESS, "transfer_private", 0.2);
|
|
919
688
|
```
|
|
920
689
|
|
|
921
|
-
#### Step 2 - User 2 receives the transaction ID and fetches the credits record they received from
|
|
690
|
+
#### Step 2 - User 2 receives the transaction ID and fetches the credits record they received from User 1 from the network. They then send it to User 3
|
|
922
691
|
|
|
923
692
|
```typescript
|
|
924
693
|
// USER 2
|
|
925
|
-
import { Account, ProgramManager, AleoKeyProvider, NetworkRecordProvider, AleoNetworkClient } from '@
|
|
694
|
+
import { Account, ProgramManager, AleoKeyProvider, NetworkRecordProvider, AleoNetworkClient } from '@provablehq/sdk';
|
|
926
695
|
|
|
927
696
|
// Create a new NetworkClient, KeyProvider, and RecordProvider
|
|
928
697
|
const account = Account.from_string({privateKey: "user2PrivateKey"});
|
|
@@ -947,19 +716,18 @@ const USER_3_ADDRESS = "user3Address";
|
|
|
947
716
|
const tx_id = await programManager.transfer(1, USER_3_ADDRESS, "transfer_private", 0.2, undefined, recordPlaintext);
|
|
948
717
|
```
|
|
949
718
|
|
|
950
|
-
When an execution such as `transfer_private` consumes or generates a record is posted on the network
|
|
951
|
-
of the execution is posted, containing an encrypted version of the record output and a transaction ID.
|
|
719
|
+
When an execution such as `transfer_private` consumes or generates a record, an encrypted transcript of the execution containing an encrypted version of the record output and a transaction ID is posted on the network.
|
|
952
720
|
|
|
953
721
|
Because the records are encrypted when they're posted on the network, they do not reveal any information about the party
|
|
954
722
|
who executed the program, nor the contents of the record. The only information that is revealed is the program ID,
|
|
955
723
|
function name, encrypted function inputs, and the transaction ID of the program execution. No user except for the recipient
|
|
956
724
|
of the record can see the contents of the record.
|
|
957
725
|
|
|
958
|
-
Below you can see
|
|
959
|
-
record, the amount transferred, and both the sender
|
|
726
|
+
Below, you can see the exact data which is posted to the Aleo network when `transfer_private` is run. Note that the
|
|
727
|
+
record, the amount transferred, and both the sender and recipient addresses are all encrypted.
|
|
960
728
|
|
|
961
729
|
<details>
|
|
962
|
-
<summary
|
|
730
|
+
<summary>`transfer_private` Execution Transcript</summary>
|
|
963
731
|
|
|
964
732
|
```json
|
|
965
733
|
"transactions": [
|
|
@@ -1024,7 +792,7 @@ that are not owned by the user will fail.
|
|
|
1024
792
|
Record decryption and ownership verification can be done in the SDK using the following code:
|
|
1025
793
|
|
|
1026
794
|
```typescript
|
|
1027
|
-
import { Account, RecordCiphertext, RecordPlaintext } from '@
|
|
795
|
+
import { Account, RecordCiphertext, RecordPlaintext } from '@provablehq/sdk';
|
|
1028
796
|
|
|
1029
797
|
// Create an account from an existing private key
|
|
1030
798
|
const account = Account.from_string({privateKey: "existingPrivateKey"});
|
|
@@ -1048,15 +816,15 @@ if (RecordCiphertext.is_owner(account.viewKey())) {
|
|
|
1048
816
|
Mappings are simple key value stores defined in a program. They are represented by a key and a value each of a specified
|
|
1049
817
|
type. They are stored directly within the Aleo blockchain and can be publicly read by any participant in the Aleo network.
|
|
1050
818
|
|
|
1051
|
-
An example of a mapping usage is `account` mapping in the `credits.aleo` program.
|
|
819
|
+
An example of a mapping usage is the `account` mapping in the `credits.aleo` program.
|
|
1052
820
|
```
|
|
1053
821
|
mapping account:
|
|
1054
822
|
key owner as address.public;
|
|
1055
823
|
value microcredits as u64.public;
|
|
1056
824
|
```
|
|
1057
825
|
|
|
1058
|
-
The `account` mapping is used to store public
|
|
1059
|
-
and a public u64 value representing the number of microcredits owned by the address.
|
|
826
|
+
The `account` mapping is used to store public credit balances on the Aleo network. It takes a public address as a key
|
|
827
|
+
and a public `u64` value representing the number of microcredits owned by the address.
|
|
1060
828
|
|
|
1061
829
|
Mappings within programs are identified by the `mapping` identifier. Any program where this keyword appears contains an
|
|
1062
830
|
on-chain mapping. An example of a program that uses a mapping is shown below:
|
|
@@ -1085,15 +853,15 @@ finalize update_score:
|
|
|
1085
853
|
|
|
1086
854
|
Note that the above function has a `finalize` identifier. This identifier is used to identify a portion of a function's
|
|
1087
855
|
code that should be executed by nodes on the Aleo network. Program mappings are updated exclusively by code run by nodes
|
|
1088
|
-
on the Aleo
|
|
856
|
+
on the Aleo network written in `finalize` blocks.
|
|
1089
857
|
|
|
1090
|
-
### 4.4 Reading
|
|
858
|
+
### 4.4 Reading mappings
|
|
1091
859
|
Any state within a program mapping is public and can be read by any participant in the Aleo network. The `NetworkClient`
|
|
1092
860
|
class provides the `getMapping` method to read the public mappings within an program and the `getMappingValue` method to
|
|
1093
861
|
read the value of a specific key within a mapping.
|
|
1094
862
|
|
|
1095
863
|
```typescript
|
|
1096
|
-
import {
|
|
864
|
+
import { AleoNetworkClient } from '@provablehq/sdk';
|
|
1097
865
|
|
|
1098
866
|
const networkClient = new AleoNetworkClient("https://api.explorer.aleo.org/v1");
|
|
1099
867
|
const creditsMappings = networkClient.getMappings("credits.aleo");
|
|
@@ -1103,9 +871,9 @@ const publicCredits = networkClient.getMapping("credits.aleo", "[a valid aleo ac
|
|
|
1103
871
|
assert(publicCredits === "0u64");
|
|
1104
872
|
```
|
|
1105
873
|
|
|
1106
|
-
### 4.5 Initializing &
|
|
874
|
+
### 4.5 Initializing & updating mappings
|
|
1107
875
|
Updating mappings is done by executing a program function on the Aleo network which has a finalize block that updates the
|
|
1108
|
-
program's mapping. For instance the `transfer_public` function in the `credits.aleo` program updates the `account`
|
|
876
|
+
program's mapping. For instance, the `transfer_public` function in the `credits.aleo` program updates the `account`
|
|
1109
877
|
mapping (and thus a user's balance) when called.
|
|
1110
878
|
|
|
1111
879
|
```
|
|
@@ -1130,15 +898,15 @@ finalize transfer_public:
|
|
|
1130
898
|
|
|
1131
899
|
From the perspective of the caller of the API, this is as simple as executing a normal Aleo function. Given the inputs
|
|
1132
900
|
to a function with a finalize scope that updates a mapping are valid, the mapping will either be intialized or updated
|
|
1133
|
-
by the Aleo network. All the user of the SDK must do is ensure that the inputs to the function are valid.
|
|
901
|
+
by the Aleo network. All that the user of the SDK must do is ensure that the inputs to the function are valid.
|
|
1134
902
|
|
|
1135
|
-
If function inputs are
|
|
1136
|
-
consumed.
|
|
903
|
+
If function inputs are invalid, the network will return an error, but the fee paid for the transaction will still be
|
|
904
|
+
consumed. Therefore, it is important to ensure that the inputs to a function are valid before executing it.
|
|
1137
905
|
|
|
1138
|
-
A simple example of a mapping update can be shown by simply executing
|
|
906
|
+
A simple example of a mapping update can be shown by simply executing 'transfer_public` as shown below.
|
|
1139
907
|
|
|
1140
908
|
```typescript
|
|
1141
|
-
import { Account, ProgramManager, AleoKeyProvider, NetworkRecordProvider, AleoNetworkClient } from '@
|
|
909
|
+
import { Account, ProgramManager, AleoKeyProvider, NetworkRecordProvider, AleoNetworkClient } from '@provablehq/sdk';
|
|
1142
910
|
|
|
1143
911
|
// Create a new NetworkClient, KeyProvider, and RecordProvider
|
|
1144
912
|
const account = Account.from_string({privateKey: "user1PrivateKey"});
|
|
@@ -1156,7 +924,7 @@ const tx_id = await programManager.transfer(1, RECIPIENT_ADDRESS, "transfer_priv
|
|
|
1156
924
|
```
|
|
1157
925
|
|
|
1158
926
|
|
|
1159
|
-
## 5. Communicating with the Aleo
|
|
927
|
+
## 5. Communicating with the Aleo network
|
|
1160
928
|
|
|
1161
929
|
Communication with the Aleo network is done through the `AleoNetworkClient` class. This class provides methods to query
|
|
1162
930
|
data from Aleo network nodes and submit transactions to the Aleo network.
|
|
@@ -1166,7 +934,7 @@ A full list of methods provided by the `AleoNetworkClient` class and usage examp
|
|
|
1166
934
|
|
|
1167
935
|
## Further Documentation
|
|
1168
936
|
|
|
1169
|
-
API documentation for this package, the Leo Language, and Aleo instructions can be found
|
|
937
|
+
API documentation for this package, the Leo Language, and Aleo instructions can be found in the [Leo Developer Docs](https://docs.leo-lang.org/getting_started).
|
|
1170
938
|
|
|
1171
939
|
To view the API documentation for this package locally, open `docs/index.html`.
|
|
1172
940
|
To regenerate the documentation, run `npx jsdoc --configure jsdoc.json --verbose`
|