Skip to content

Commit 9d8c501

Browse files
moved record provider types to models dir. moved nonces out of record provider method signatures into RecordSearchParams interface. added jsdoc comments to record scanner
1 parent 4065cd7 commit 9d8c501

File tree

9 files changed

+281
-161
lines changed

9 files changed

+281
-161
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export type EncryptedRecord = {
2+
commitment: string;
3+
checksum?: string;
4+
blockHeight?: number;
5+
programName?: string;
6+
functionName?: string;
7+
outputIndex?: number;
8+
owner?: string;
9+
recordCiphertext?: string;
10+
recordName?: string;
11+
recordNonce?: string;
12+
transactionId?: string;
13+
transitionId?: string;
14+
transactionIndex?: number;
15+
transitionIndex?: number;
16+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export type OwnedRecord = {
2+
blockHeight?: number;
3+
commitment?: string;
4+
functionName?: string;
5+
outputIndex?: number;
6+
owner?: string;
7+
programName?: string;
8+
recordCiphertext?: string;
9+
recordPlaintext?: string;
10+
recordName?: string;
11+
spent?: boolean;
12+
tag?: string;
13+
transactionId?: string;
14+
transitionId?: string;
15+
transactionIndex?: number;
16+
transitionIndex?: number;
17+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* Interface for record search parameters. This allows for arbitrary search parameters to be passed to record provider
3+
* implementations.
4+
*/
5+
export interface RecordSearchParams {
6+
unspent: boolean;
7+
nonces?: string[];
8+
[key: string]: any; // This allows for arbitrary keys with any type values
9+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export type RecordsResponseFilter = {
2+
program: boolean;
3+
record: boolean;
4+
function: boolean;
5+
transition: boolean;
6+
blockHeight: boolean;
7+
transactionId: boolean;
8+
transitionId: boolean;
9+
ioIndex: boolean;
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { RecordSearchParams } from "../record-provider/recordSearchParams";
2+
import { RecordsFilter } from "./recordsFilter";
3+
import { RecordsResponseFilter } from "../record-provider/recordsResponseFilter";
4+
5+
export interface OwnedFilter extends RecordSearchParams {
6+
decrypt?: boolean;
7+
filter?: RecordsFilter;
8+
responseFilter?: RecordsResponseFilter;
9+
uuid?: string;
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { RecordSearchParams } from "../record-provider/recordSearchParams";
2+
3+
export interface RecordsFilter extends RecordSearchParams {
4+
start: number;
5+
end?: number;
6+
program?: string;
7+
record?: string;
8+
function?: string;
9+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export type RegistrationRequest = {
2+
viewKey: string;
3+
start: number;
4+
}

sdk/src/record-provider.ts

Lines changed: 92 additions & 120 deletions
Large diffs are not rendered by default.

sdk/src/record-scanner.ts

Lines changed: 114 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,38 @@
11
import { Account } from "./account";
22
import { EncryptedRecord, OwnedRecord, RecordProvider, RecordSearchParams, RecordsResponseFilter } from "./record-provider";
33
import { RecordPlaintext } from "./wasm";
4+
import { RegistrationRequest } from "./models/record-scanner/registrationRequest";
5+
import { RecordsFilter } from "./models/record-scanner/recordsFilter";
6+
import { OwnedFilter } from "./models/record-scanner/ownedFilter";
47

5-
type RegistrationRequest = {
6-
viewKey: string;
7-
start: number;
8-
}
9-
10-
interface RecordsFilter extends RecordSearchParams {
11-
start: number;
12-
end?: number;
13-
program?: string;
14-
record?: string;
15-
function?: string;
16-
}
17-
18-
interface OwnedFilter extends RecordSearchParams {
19-
decrypt?: boolean;
20-
filter?: RecordsFilter;
21-
responseFilter?: RecordsResponseFilter;
22-
}
23-
24-
interface OwnedFilterWithUuid extends OwnedFilter {
25-
uuid: string;
26-
}
27-
8+
/**
9+
* RecordScanner is a RecordProvider implementation that uses the record scanner service to find records.
10+
*
11+
* @example
12+
* const account = new Account({ privateKey: 'APrivateKey1...' });
13+
*
14+
* const recordScanner = new RecordScanner("https://record-scanner.aleo.org");
15+
* recordScanner.setAccount(account);
16+
* await recordScanner.register(0);
17+
*
18+
* const filter = {
19+
* start: 0,
20+
* end: 100,
21+
* program: "credits.aleo",
22+
* record: "credits",
23+
* };
24+
*
25+
* const responseFilter = {
26+
* program: true,
27+
* record: true,
28+
* function: true,
29+
* transition: true,
30+
* blockHeight: true,
31+
* transactionId: true,
32+
* };
33+
*
34+
* const records = await recordScanner.findRecords({ filter, responseFilter });
35+
*/
2836
class RecordScanner implements RecordProvider {
2937
readonly url: string;
3038
private account?: Account;
@@ -35,10 +43,21 @@ class RecordScanner implements RecordProvider {
3543
this.url = url;
3644
}
3745

46+
/**
47+
* Set the account to use for the record scanner.
48+
*
49+
* @param {Account} account The account to use for the record scanner.
50+
*/
3851
async setAccount(account: Account): Promise<void> {
52+
this.uuid = undefined;
3953
this.account = account;
4054
}
4155

56+
/**
57+
* Register the account with the record scanner service.
58+
*
59+
* @param {number} startBlock The block height to start scanning from.
60+
*/
4261
async register(startBlock: number): Promise<void> {
4362
let request: RegistrationRequest;
4463
if (!this.account) {
@@ -67,7 +86,14 @@ class RecordScanner implements RecordProvider {
6786
}
6887
}
6988

70-
async getEncryptedRecords(recordsFilter: RecordsFilter, responseFilter: RecordsResponseFilter): Promise<EncryptedRecord[]> {
89+
/**
90+
* Get encrypted records from the record scanner service.
91+
*
92+
* @param {RecordsFilter} recordsFilter The filter to use to find the records
93+
* @param {RecordsResponseFilter} responseFilter The filter to use to filter the response
94+
* @returns {Promise<EncryptedRecord[]>} The encrypted records
95+
*/
96+
async encryptedRecords(recordsFilter: RecordsFilter, responseFilter: RecordsResponseFilter): Promise<EncryptedRecord[]> {
7197
try {
7298
const response = await this.recordScannerServiceRequest(
7399
new Request(`${this.url}/records/encrypted?${this.buildQueryString(recordsFilter, responseFilter)}`, {
@@ -84,7 +110,13 @@ class RecordScanner implements RecordProvider {
84110
}
85111
}
86112

87-
async serialNumbersExist(serialNumbers: string[]): Promise<Record<string, boolean>> {
113+
/**
114+
* Check if a list of serial numbers exist in the record scanner service.
115+
*
116+
* @param {string[]} serialNumbers The serial numbers to check
117+
* @returns {Promise<Record<string, boolean>>} A record of serial numbers and whether they exist
118+
*/
119+
async checkSerialNumbers(serialNumbers: string[]): Promise<Record<string, boolean>> {
88120
try {
89121
const response = await this.recordScannerServiceRequest(
90122
new Request(`${this.url}/records/sns`, {
@@ -101,7 +133,13 @@ class RecordScanner implements RecordProvider {
101133
}
102134
}
103135

104-
async tagsExist(tags: string[]): Promise<Record<string, boolean>> {
136+
/**
137+
* Check if a list of tags exist in the record scanner service.
138+
*
139+
* @param {string[]} tags The tags to check
140+
* @returns {Promise<Record<string, boolean>>} A record of tags and whether they exist
141+
*/
142+
async checkTags(tags: string[]): Promise<Record<string, boolean>> {
105143
try {
106144
const response = await this.recordScannerServiceRequest(
107145
new Request(`${this.url}/records/tags`, {
@@ -118,9 +156,15 @@ class RecordScanner implements RecordProvider {
118156
}
119157
}
120158

121-
async findRecord(searchParameters: OwnedFilter, filterFn?: (record: RecordPlaintext) => boolean): Promise<OwnedRecord> {
159+
/**
160+
* Find a record in the record scanner service.
161+
*
162+
* @param {OwnedFilter} searchParameters The filter to use to find the record
163+
* @returns {Promise<OwnedRecord>} The record
164+
*/
165+
async findRecord(searchParameters: OwnedFilter): Promise<OwnedRecord> {
122166
try {
123-
const records = await this.findRecords(searchParameters, filterFn);
167+
const records = await this.findRecords(searchParameters);
124168

125169
if (records.length > 0) {
126170
return records[0];
@@ -133,34 +177,43 @@ class RecordScanner implements RecordProvider {
133177
}
134178
}
135179

136-
async findRecords(searchParameters: OwnedFilter, filterFn?: (record: RecordPlaintext) => boolean): Promise<OwnedRecord[]> {
180+
/**
181+
* Find records in the record scanner service.
182+
*
183+
* @param {OwnedFilter} filter The filter to use to find the records
184+
* @returns {Promise<OwnedRecord[]>} The records
185+
*/
186+
async findRecords(filter: OwnedFilter): Promise<OwnedRecord[]> {
137187
if (!this.uuid) {
138188
throw new Error("Not registered");
139189
}
140190

141-
const filterWithUuid: OwnedFilterWithUuid = {
142-
...searchParameters,
143-
uuid: this.uuid,
144-
};
191+
filter.uuid = this.uuid;
145192

146193
try {
147194
const response = await this.recordScannerServiceRequest(
148195
new Request(`${this.url}/records/owned`, {
149196
method: "POST",
150197
headers: { "Content-Type": "application/json" },
151-
body: JSON.stringify(filterWithUuid),
198+
body: JSON.stringify(filter),
152199
}),
153200
);
154201

155-
const records = await response.json();
156-
return filterFn ? records.filter(filterFn) : records;
202+
return await response.json();
157203
} catch (error) {
158204
console.error(`Failed to get owned records: ${error}`);
159205
throw error;
160206
}
161207
}
162208

163-
async findCreditsRecord(microcredits: number, searchParameters: OwnedFilter, nonces?: string[]): Promise<OwnedRecord> {
209+
/**
210+
* Find a credits record in the record scanner service.
211+
*
212+
* @param {number} microcredits The amount of microcredits to find
213+
* @param {OwnedFilter} searchParameters The filter to use to find the record
214+
* @returns {Promise<OwnedRecord>} The record
215+
*/
216+
async findCreditsRecord(microcredits: number, searchParameters: OwnedFilter): Promise<OwnedRecord> {
164217
try {
165218
const records = await this.findRecords({
166219
...searchParameters,
@@ -171,8 +224,9 @@ class RecordScanner implements RecordProvider {
171224

172225
const record = records.find(record => {
173226
const plaintext = RecordPlaintext.fromString(record.recordPlaintext);
174-
const amount = plaintext.getMember("microcredits").toString();
175-
return amount === `${microcredits}u64`;
227+
const amountStr = plaintext.getMember("microcredits").toString();
228+
const amount = parseInt(amountStr.replace("u64", ""));
229+
return amount >= microcredits;
176230
});
177231

178232
if (!record) {
@@ -186,7 +240,14 @@ class RecordScanner implements RecordProvider {
186240
}
187241
}
188242

189-
async findCreditsRecords(microcreditAmounts: number[], searchParameters: OwnedFilter, nonces?: string[]): Promise<OwnedRecord[]> {
243+
/**
244+
* Find credits records in the record scanner service.
245+
*
246+
* @param {number[]} microcreditAmounts The amounts of microcredits to find
247+
* @param {OwnedFilter} searchParameters The filter to use to find the records
248+
* @returns {Promise<OwnedRecord[]>} The records
249+
*/
250+
async findCreditsRecords(microcreditAmounts: number[], searchParameters: OwnedFilter): Promise<OwnedRecord[]> {
190251
try {
191252
const records = await this.findRecords({
192253
...searchParameters,
@@ -205,7 +266,12 @@ class RecordScanner implements RecordProvider {
205266
}
206267
}
207268

208-
269+
/**
270+
* Wrapper function to make a request to the record scanner service and handle any errors
271+
*
272+
* @param {Request} req The request to make
273+
* @returns {Promise<Response>} The response
274+
*/
209275
private async recordScannerServiceRequest(req: Request): Promise<Response> {
210276
try {
211277
const response = await fetch(req);
@@ -221,6 +287,13 @@ class RecordScanner implements RecordProvider {
221287
}
222288
}
223289

290+
/**
291+
* Helper function to build a query string from the records filter and response filter.
292+
*
293+
* @param {RecordSearchParams} recordsFilter The filter to use to find the records
294+
* @param {RecordsResponseFilter} responseFilter The filter to use to filter the response
295+
* @returns {string} The query string
296+
*/
224297
private buildQueryString(recordsFilter: RecordSearchParams, responseFilter: RecordsResponseFilter): string {
225298
return Object.entries({ ...recordsFilter, ...responseFilter })
226299
.map(([key, value]) => `${key}=${value}`)

0 commit comments

Comments
 (0)