diff --git a/sdk/src/browser.ts b/sdk/src/browser.ts index a22740e4f..47313d8a7 100644 --- a/sdk/src/browser.ts +++ b/sdk/src/browser.ts @@ -6,6 +6,7 @@ import { BlockJSON, Header, Metadata } from "./models/blockJSON.js"; import { ConfirmedTransactionJSON } from "./models/confirmed_transaction.js"; import { DeploymentJSON, VerifyingKeys } from "./models/deployment/deploymentJSON.js"; import { DeploymentObject } from "./models/deployment/deploymentObject.js"; +import { EncryptedRecord } from "./models/record-provider/encryptedRecord.js"; import { ExecutionJSON, FeeExecutionJSON } from "./models/execution/executionJSON.js"; import { ExecutionObject, FeeExecutionObject } from "./models/execution/executionObject.js"; import { FinalizeJSON } from "./models/finalizeJSON.js"; @@ -15,6 +16,8 @@ import { InputJSON } from "./models/input/inputJSON.js"; import { InputObject } from "./models/input/inputObject.js"; import { OutputJSON } from "./models/output/outputJSON.js"; import { OutputObject } from "./models/output/outputObject.js"; +import { OwnedFilter } from "./models/record-scanner/ownedFilter.js"; +import { OwnedRecord } from "./models/record-provider/ownedRecord.js"; import { OwnerJSON } from "./models/owner/ownerJSON.js"; import { PlaintextArray} from "./models/plaintext/array.js"; import { PlaintextLiteral} from "./models/plaintext/literal.js"; @@ -23,6 +26,9 @@ import { PlaintextStruct} from "./models/plaintext/struct.js"; import { ProvingRequestJSON } from "./models/provingRequest.js"; import { ProvingResponse } from "./models/provingResponse.js"; import { RatificationJSON } from "./models/ratification.js"; +import { RecordsFilter } from "./models/record-scanner/recordsFilter.js"; +import { RecordsResponseFilter } from "./models/record-scanner/recordsResponseFilter.js"; +import { RecordSearchParams } from "./models/record-provider/recordSearchParams.js"; import { SolutionsJSON, SolutionJSON, PartialSolutionJSON } from "./models/solution.js"; import { TransactionJSON } from "./models/transaction/transactionJSON.js"; import { TransactionObject } from "./models/transaction/transactionObject.js"; @@ -45,7 +51,6 @@ import { BlockHeightSearch, NetworkRecordProvider, RecordProvider, - RecordSearchParams, } from "./record-provider.js"; // @TODO: This function is no longer needed, remove it. @@ -136,6 +141,7 @@ export { ConfirmedTransactionJSON, DeploymentJSON, DeploymentObject, + EncryptedRecord, ExecutionJSON, ExecutionObject, FeeExecutionJSON, @@ -156,6 +162,8 @@ export { OfflineSearchParams, OutputJSON, OutputObject, + OwnedFilter, + OwnedRecord, OwnerJSON, PartialSolutionJSON, PlaintextArray, @@ -166,6 +174,8 @@ export { ProvingRequestJSON, ProvingResponse, RatificationJSON, + RecordsFilter, + RecordsResponseFilter, RecordProvider, RecordSearchParams, SolutionJSON, diff --git a/sdk/src/models/record-provider/encryptedRecord.ts b/sdk/src/models/record-provider/encryptedRecord.ts new file mode 100644 index 000000000..59e14fa42 --- /dev/null +++ b/sdk/src/models/record-provider/encryptedRecord.ts @@ -0,0 +1,58 @@ +/** + * Encrypted Record found on chain. This type provides the record ciphertext and metadata from the ledger such as the record's name, the program/function that produced it, etc. + * + * @property {string} commitment - The commitment of the record. + * @property {string | undefined} checksum - The checksum of the record. + * @property {number | undefined} block_height - The block height of the record. + * @property {number | undefined} block_timestamp - The block timestamp of the record. + * @property {string | undefined} program_name - The name of the program that produced the record. + * @property {string | undefined} function_name - The name of the function that produced the record. + * @property {number | undefined} output_index - The output index of the record. + * @property {string | undefined} owner - The owner of the record. + * @property {string | undefined} record_ciphertext - The ciphertext of the record. + * @property {string | undefined} record_name - The name of the record. + * @property {string | undefined} record_nonce - The nonce of the record. + * @property {string | undefined} sender_ciphertext - The ciphertext of the sender. + * @property {string | undefined} transaction_id - The ID of the transaction that produced the record. + * @property {string | undefined} transition_id - The ID of the transition that produced the record. + * @property {number | undefined} transaction_index - The index of the transaction that produced the record. + * @property {number | undefined} transition_index - The index of the transition that produced the record. + * + * @example + * const encryptedRecord: EncryptedRecord = { + * commitment: "1754131901135854615627743152473414463769543922079966020586765988138574911385field", + * checksum: "731623304764338277682996290553427512270277231686866672455141481050283829616field", + * block_height: 123456, + * block_timestamp: 1725845998, + * program_name: "credits.aleo", + * function_name: "transfer_private", + * output_index: 0, + * owner: "ciphertext1qgqdetlfzk98jkm4e7sgqml66e3x2gpg5d6udkpw0g67z0tplkpmzrm6q5dyfd7xhgmhedvptxzwfhrtxaqn7n0hs0esge3lwg9s2zukqgzxd0cr", + * record_ciphertext: "record1qyqsqt43u9kp97svljyyup3v4jmppd0vgght9edvvmtxx6mxycsej8cwqsrxzmt0w4h8ggcqqgqspf8zqut2ycnap7f0uzz5ktu0cxscca96urtkg2aweuzn70787dsrpp6x76m9de0kjezrqqpqyqp3mn3xeh53lukvcy406amjf5g0ksl3saauzjk0j4ljtjqq6kqlqhdz05sw92zye96qym7kp83ra0eesgtwhaw37c85r499456se8ts28m90p6x2unwv9k97ct4w35x7unf0fshg6t0de0hyet3w45hyetyyvqqyqgq4t2wr9tmcrfha5tfz5j585ptvvslqe0f6sf29vytshhdh7ym05rpqct4w35x7unf0fjkghm4de6xjmprqqpqzqru6p7fef29vuz6smyqwcn3z7jhxtdgjdw5xv23ppxhpgnvu72fp8hz6fjt6gsdn8yxhzq7gpsah0rscwqrzxwl5e8aemkj5gt09y7q5506yrf", + * record_name: "credits", + * record_nonce: "3077450429259593211617823051143573281856129402760267155982965992208217472983group", + * sender_ciphertext: "1754131901135854615627743152473414463769543922079966020586765988138574911385field", + * transaction_id: "at1f8ueqxu3x49sckpc6jlg676tmxumddzer3fwe2l0dxwj4dqxygyqua4u2q", + * transition_id: "au17mm5v7sfwus6y40xsyc99d5rtsr4vsajdec6twdjzv0m458q85zspqdnka", + * transaction_index: 0, + * transition_index: 0, + * } + */ +export type EncryptedRecord = { + commitment: string; + checksum?: string; + block_height?: number; + block_timestamp?: number; + program_name?: string; + function_name?: string; + output_index?: number; + owner?: string; + record_ciphertext?: string; + record_name?: string; + record_nonce?: string; + sender_ciphertext?: string; + transaction_id?: string; + transition_id?: string; + transaction_index?: number; + transition_index?: number; +} \ No newline at end of file diff --git a/sdk/src/models/record-provider/ownedRecord.ts b/sdk/src/models/record-provider/ownedRecord.ts new file mode 100644 index 000000000..d905558e2 --- /dev/null +++ b/sdk/src/models/record-provider/ownedRecord.ts @@ -0,0 +1,60 @@ +/** + * Record owned by a registered view key. This type provides the record ciphertext, record plaintext and metadata from the ledger such as the record's name, the program/function that produced it, etc. + * + * @property {number | undefined} block_height - Block height where the record was created. + * @property {number | undefined} block_timestamp - The timestamp of the block that the record was created in. + * @property {string | undefined} commitment - Commitment of the record. + * @property {string | undefined} function_name - Name of the function that created the record. + * @property {number | undefined} output_index - Index of the output in the function call that created the record. + * @property {string | undefined} owner - Address of the record owner. + * @property {string | undefined} program_name - Name of the program that created the record. + * @property {string | undefined} record_ciphertext - Encrypted ciphertext of the record. + * @property {string | undefined} record_name - Name of the record. + * @property {string | undefined} sender - Address of the sender. + * @property {boolean | undefined} spent - Whether the record has been spent. + * @property {string | undefined} tag - Tag associated with the record. + * @property {string | undefined} transaction_id - ID of the transaction that created the record. + * @property {string | undefined} transition_id - ID of the transition that created the record. + * @property {string | undefined} transaction_index - Index of the transaction in the block. + * @property {string | undefined} transition_index - Index of the transition in the transaction. + * + * @example + * const ownedRecord: OwnedRecord = { + * block_height: 123456, + * block_timestamp: 1725845998, + * commitment: "1754131901135854615627743152473414463769543922079966020586765988138574911385field", + * function_name: "transfer_public_to_private", + * output_index: 0, + * owner: "ciphertext1qgqdetlfzk98jkm4e7sgqml66e3x2gpg5d6udkpw0g67z0tplkpmzrm6q5dyfd7xhgmhedvptxzwfhrtxaqn7n0hs0esge3lwg9s2zukqgzxd0cr", + * program_name: "credits.aleo", + * record_ciphertext: "record1qyqsqt43u9kp97svljyyup3v4jmppd0vgght9edvvmtxx6mxycsej8cwqsrxzmt0w4h8ggcqqgqspf8zqut2ycnap7f0uzz5ktu0cxscca96urtkg2aweuzn70787dsrpp6x76m9de0kjezrqqpqyqp3mn3xeh53lukvcy406amjf5g0ksl3saauzjk0j4ljtjqq6kqlqhdz05sw92zye96qym7kp83ra0eesgtwhaw37c85r499456se8ts28m90p6x2unwv9k97ct4w35x7unf0fshg6t0de0hyet3w45hyetyyvqqyqgq4t2wr9tmcrfha5tfz5j585ptvvslqe0f6sf29vytshhdh7ym05rpqct4w35x7unf0fjkghm4de6xjmprqqpqzqru6p7fef29vuz6smyqwcn3z7jhxtdgjdw5xv23ppxhpgnvu72fp8hz6fjt6gsdn8yxhzq7gpsah0rscwqrzxwl5e8aemkj5gt09y7q5506yrf", + * record_plaintext: "{ owner: aleo1j7qxyunfldj2lp8hsvy7mw5k8zaqgjfyr72x2gh3x4ewgae8v5gscf5jh3.private, microcredits: 1500000000000000u64.private, _nonce: 3077450429259593211617823051143573281856129402760267155982965992208217472983group.public , _version: 1u8 }", + * record_name: "credits", + * spent: true, + * sender: "aleo1sf5kk4f8mcmgjasw9fannmm0h8z2nwqxu5e200cjneu28jxvtvpqulfxsa", + * tag: "6511661650536816422260305447175136877451468301541296257226129781611237851030field", + * transaction_id: "at1f8ueqxu3x49sckpc6jlg676tmxumddzer3fwe2l0dxwj4dqxygyqua4u2q", + * transition_id: "au17mm5v7sfwus6y40xsyc99d5rtsr4vsajdec6twdjzv0m458q85zspqdnka", + * transaction_index: 0, + * transition_index: 0, + * } + */ +export type OwnedRecord = { + block_height?: number; + block_timestamp?: number; + commitment?: string; + function_name?: string; + output_index?: number; + owner?: string; + program_name?: string; + record_ciphertext?: string; + record_plaintext?: string; + record_name?: string; + sender?: string; + spent?: boolean; + tag?: string; + transaction_id?: string; + transition_id?: string; + transaction_index?: number; + transition_index?: number; +} \ No newline at end of file diff --git a/sdk/src/models/record-provider/recordSearchParams.ts b/sdk/src/models/record-provider/recordSearchParams.ts new file mode 100644 index 000000000..10820e65f --- /dev/null +++ b/sdk/src/models/record-provider/recordSearchParams.ts @@ -0,0 +1,19 @@ +/** + * Interface for record search parameters. This allows for arbitrary search parameters to be passed to record provider + * implementations. + * + * @example + * const recordSearchParams: RecordSearchParams = { + * // Declared fields + * unspent: true, + * nonces: ["3077450429259593211617823051143573281856129402760267155982965992208217472983group"], + * // Arbitrary fields + * startHeight: 123456, + * programName: "credits.aleo" + * } + */ +export interface RecordSearchParams { + unspent?: boolean; + nonces?: string[]; + [key: string]: any; // This allows for arbitrary keys with any type values +} \ No newline at end of file diff --git a/sdk/src/models/record-scanner/ownedFilter.ts b/sdk/src/models/record-scanner/ownedFilter.ts new file mode 100644 index 000000000..dd91fb626 --- /dev/null +++ b/sdk/src/models/record-scanner/ownedFilter.ts @@ -0,0 +1,25 @@ +import { RecordSearchParams } from "../record-provider/recordSearchParams"; +import { RecordsFilter } from "./recordsFilter"; +import { OwnedRecordsResponseFilter } from "./ownedRecordsResponseFilter"; + +/** + * OwnedFilter is an extension of RecordSearchParams that represents a filter for scanning owned records. + * + * @example + * const ownedFilter: OwnedFilter = { + * unspent: true, + * nonces: ["3077450429259593211617823051143573281856129402760267155982965992208217472983group"], + * decrypt: true, + * filter: { + * program: "credits.aleo", + * record: "credits", + * }, + * } + */ +export interface OwnedFilter extends RecordSearchParams { + decrypt?: boolean; + filter?: RecordsFilter; + responseFilter?: OwnedRecordsResponseFilter; + unspent?: boolean; + uuid?: string; +} \ No newline at end of file diff --git a/sdk/src/models/record-scanner/ownedRecordsResponseFilter.ts b/sdk/src/models/record-scanner/ownedRecordsResponseFilter.ts new file mode 100644 index 000000000..0dc72bf4e --- /dev/null +++ b/sdk/src/models/record-scanner/ownedRecordsResponseFilter.ts @@ -0,0 +1,42 @@ +/** + * OwnedRecordsResponseFilter is a type that represents a filter for the response from a record provider. + * A `true` value for a field in the filter will include that field in the response. + * + * @example + * const ownedRecordsResponseFilter: OwnedRecordsResponseFilter = { + * commitment: true, + * owner: true, + * tag: true, + * sender: true, + * spent: true, + * record_ciphertext: true, + * block_height: true, + * block_timestamp: true, + * output_index: true, + * record_name: true, + * function_name: true, + * program_name: true, + * transition_id: true, + * transaction_id: true, + * transaction_index: true, + * transition_index: true, + * } + */ +export interface OwnedRecordsResponseFilter { + commitment?: boolean; + owner?: boolean; + tag?: boolean; + sender?: boolean; + spent?: boolean; + record_ciphertext?: boolean; + block_height?: boolean; + block_timestamp?: boolean; + output_index?: boolean; + record_name?: boolean; + function_name?: boolean; + program_name?: boolean; + transition_id?: boolean; + transaction_id?: boolean; + transaction_index?: boolean; + transition_index?: boolean; +} \ No newline at end of file diff --git a/sdk/src/models/record-scanner/recordsFilter.ts b/sdk/src/models/record-scanner/recordsFilter.ts new file mode 100644 index 000000000..bc65024f3 --- /dev/null +++ b/sdk/src/models/record-scanner/recordsFilter.ts @@ -0,0 +1,36 @@ +import { RecordSearchParams } from "../record-provider/recordSearchParams"; +import { RecordsResponseFilter } from "./recordsResponseFilter"; + +/** + * RecordsFilter is an extension of RecordSearchParams that represents a filter for scanning encrypted or owned records. + * + * @example + * const recordsFilter: RecordsFilter = { + * start: 0, + * end: 100, + * programs: ["credits.aleo"], + * records: ["credits"], + * functions: ["transfer_public_to_private"], + * response: { + * program: true, + * record: true, + * function: true, + * transition: true, + * block_height: true, + * transaction_id: true, + * } + * results_per_page: 100, + * page: 0, + * } + */ +export interface RecordsFilter extends RecordSearchParams { + commitments?: string[]; + response?: RecordsResponseFilter; + start?: number; + end?: number; + programs?: string[]; + records?: string[]; + functions?: string[]; + results_per_page?: number; + page?: number; +} \ No newline at end of file diff --git a/sdk/src/models/record-scanner/recordsResponseFilter.ts b/sdk/src/models/record-scanner/recordsResponseFilter.ts new file mode 100644 index 000000000..a971a5b1f --- /dev/null +++ b/sdk/src/models/record-scanner/recordsResponseFilter.ts @@ -0,0 +1,38 @@ +/** + * RecordsResponseFilter is a type that represents a filter for the response from a record provider. + * A `true` value for a field in the filter will include that field in the response. + * + * @example + * const recordsResponseFilter: RecordsResponseFilter = { + * block_height: true, + * checksum: true, + * commitment: true, + * record_ciphertext: true, + * function_name: true, + * nonce: true, + * output_index: true, + * owner: true, + * program_name: true, + * record_name: true, + * transaction_id: true, + * transition_id: true, + * transaction_index: true, + * transition_index: true, + * } + */ +export type RecordsResponseFilter = { + blockHeight?: boolean; + checksum?: boolean; + commitment?: boolean; + record_ciphertext?: boolean; + function_name?: boolean; + nonce?: boolean; + output_index?: boolean; + owner?: boolean; + program_name?: boolean; + record_name?: boolean; + transaction_id?: boolean; + transition_id?: boolean; + transaction_index?: boolean; + transition_index?: boolean; +} \ No newline at end of file diff --git a/sdk/src/models/record-scanner/registrationRequest.ts b/sdk/src/models/record-scanner/registrationRequest.ts new file mode 100644 index 000000000..53cb71dd0 --- /dev/null +++ b/sdk/src/models/record-scanner/registrationRequest.ts @@ -0,0 +1,13 @@ +/** + * RegistrationRequest is a type that represents a request to register an account's view key with a record scanning service. + * + * @example + * const registrationRequest: RegistrationRequest = { + * view_key: "AViewKey1ccEt8A2Ryva5rxnKcAbn7wgTaTsb79tzkKHFpeKsm9NX", + * start: 123456, + * } + */ +export type RegistrationRequest = { + view_key: string; + start: number; +} \ No newline at end of file diff --git a/sdk/src/models/record-scanner/registrationResponse.ts b/sdk/src/models/record-scanner/registrationResponse.ts new file mode 100644 index 000000000..12177f2e9 --- /dev/null +++ b/sdk/src/models/record-scanner/registrationResponse.ts @@ -0,0 +1,15 @@ +/** + * RegistrationResponse is a type that represents a response from a record scanning service. + * + * @example + * const registrationResponse: RegistrationResponse = { + * uuid: "5291249998620209321712738612705518874926462927543783711572375085855029172391field", + * job_id: "3019177021147406178755252788128212930359855601860174268911518336835545087409field", + * status: "pending", + * } + */ +interface RegistrationResponse { + uuid: string, + job_id?: string, + status?: string + } \ No newline at end of file diff --git a/sdk/src/program-manager.ts b/sdk/src/program-manager.ts index 1474c213d..b45da6ee4 100644 --- a/sdk/src/program-manager.ts +++ b/sdk/src/program-manager.ts @@ -1,7 +1,8 @@ import { Account } from "./account.js"; import { AleoNetworkClient, AleoNetworkClientOptions, ProgramImports } from "./network-client.js"; import { ImportedPrograms, ImportedVerifyingKeys } from "./models/imports.js"; -import { RecordProvider, RecordSearchParams } from "./record-provider.js"; +import { RecordProvider } from "./record-provider.js"; +import { RecordSearchParams } from "./models/record-provider/recordSearchParams.js"; import { AleoKeyProvider, @@ -35,6 +36,7 @@ import { } from "./constants.js"; import { logAndThrow } from "./utils.js"; +import { OwnedRecord } from "./models/record-provider/ownedRecord.js"; /** * Represents the options for executing a transaction in the Aleo network. @@ -353,14 +355,12 @@ class ProgramManager { // Get the fee record from the account if it is not provided in the parameters try { feeRecord = privateFee - ? ( - await this.getCreditsRecord( + ? RecordPlaintext.fromString((await this.getCreditsRecord( priorityFee, [], feeRecord, recordSearchParams, - ) - ) + )).record_plaintext?? '') : undefined; } catch (e: any) { logAndThrow( @@ -583,14 +583,12 @@ class ProgramManager { // Get the fee record from the account if it is not provided in the parameters try { feeRecord = privateFee - ? ( - await this.getCreditsRecord( + ? RecordPlaintext.fromString((await this.getCreditsRecord( priorityFee, [], feeRecord, recordSearchParams, - ) - ) + )).record_plaintext?? '') : undefined; } catch (e: any) { logAndThrow( @@ -976,14 +974,12 @@ class ProgramManager { // Get the fee record from the account if it is not provided in the parameters. try { feeRecord = privateFee - ? ( - await this.getCreditsRecord( + ? RecordPlaintext.fromString((await this.getCreditsRecord( priorityFee, [], feeRecord, recordSearchParams, - ) - ) + )).record_plaintext?? '') : undefined; } catch (e: any) { logAndThrow( @@ -1314,14 +1310,12 @@ class ProgramManager { // Get the fee record from the account if it is not provided in the parameters try { feeRecord = privateFee - ? ( - await this.getCreditsRecord( + ? RecordPlaintext.fromString((await this.getCreditsRecord( priorityFee, [], feeRecord, recordSearchParams, - ) - ) + )).record_plaintext?? '') : undefined; } catch (e: any) { logAndThrow( @@ -1587,27 +1581,23 @@ class ProgramManager { const nonces: string[] = []; if (requiresAmountRecord(transferType)) { // If the transfer type is private and requires an amount record, get it from the record provider - amountRecord = ( - await this.getCreditsRecord( + amountRecord = RecordPlaintext.fromString((await this.getCreditsRecord( priorityFee, [], amountRecord, recordSearchParams, - ) - ); + )).record_plaintext?? ''); nonces.push(amountRecord.nonce()); } else { amountRecord = undefined; } feeRecord = privateFee - ? ( - await this.getCreditsRecord( + ? RecordPlaintext.fromString((await this.getCreditsRecord( priorityFee, nonces, feeRecord, recordSearchParams, - ) - ) + )).record_plaintext?? '') : undefined; } catch (e: any) { logAndThrow( @@ -2574,21 +2564,25 @@ class ProgramManager { nonces: string[], record?: RecordPlaintext | string, params?: RecordSearchParams, - ): Promise { + ): Promise { try { - return record instanceof RecordPlaintext - ? record - : RecordPlaintext.fromString(record); + // return record instanceof RecordPlaintext + // ? record + // : RecordPlaintext.fromString(record); + if (record && record instanceof RecordPlaintext) { + record = record.toString(); + } + return ({ + recordPlaintext: record, + programName: 'credits.aleo', + recordName: 'credits', + }) } catch (e) { try { const recordProvider = this.recordProvider; - return ( - await recordProvider.findCreditsRecord( - amount, - true, - nonces, - params, - ) + return await recordProvider.findCreditsRecord( + amount, + { ...params, unspent: true, nonces } ); } catch (e: any) { logAndThrow( diff --git a/sdk/src/record-provider.ts b/sdk/src/record-provider.ts index 5f6afdc73..d95c772cc 100644 --- a/sdk/src/record-provider.ts +++ b/sdk/src/record-provider.ts @@ -1,15 +1,10 @@ -import { RecordPlaintext } from "./wasm.js"; -import { logAndThrow } from "./utils.js"; import { Account } from "./account.js"; import { AleoNetworkClient } from "./network-client.js"; - -/** - * Interface for record search parameters. This allows for arbitrary search parameters to be passed to record provider - * implementations. - */ -interface RecordSearchParams { - [key: string]: any; // This allows for arbitrary keys with any type values -} +import { EncryptedRecord } from "./models/record-provider/encryptedRecord.js"; +import { logAndThrow } from "./utils.js"; +import { OwnedRecord } from "./models/record-provider/ownedRecord.js"; +import { RecordSearchParams } from "./models/record-provider/recordSearchParams.js"; +import { RecordsResponseFilter } from "./models/record-scanner/recordsResponseFilter.js"; /** * Interface for a record provider. A record provider is used to find records for use in deployment and execution @@ -18,64 +13,86 @@ interface RecordSearchParams { * implementing this interface. */ interface RecordProvider { - account: Account + /** + * The account used to search for records. + */ + account?: Account; + + /** + * Find encrypted records from the chosen provider. + * + * @param {RecordSearchParams} recordsFilter The filter used to find the records. + * @param {RecordsResponseFilter} responseFilter The filter used to filter the response. + * @returns {Promise} The encrypted records. + */ + encryptedRecords(recordsFilter: RecordSearchParams, responseFilter?: RecordsResponseFilter): Promise; /** - * Find a credits.aleo record with a given number of microcredits from the chosen provider + * Check if a list of serial numbers exist in the chosen provider. * - * @param {number} microcredits The number of microcredits to search for - * @param {boolean} unspent Whether or not the record is unspent - * @param {string[]} nonces Nonces of records already found so they are not found again - * @param {RecordSearchParams} searchParameters Additional parameters to search for - * @returns {Promise} The record if found, otherwise an error + * @param {string[]} serialNumbers The serial numbers to check. + * @returns {Promise>} Map of Aleo Record serial numbers and whether they appeared in any inputs on chain. If boolean corresponding to the Serial Number has a true value, that Record is considered spent by the Aleo Network. + */ + checkSerialNumbers(serialNumbers: string[]): Promise>; + + /** + * Check if a list of tags exist in the chosen provider. + * + * @param {string[]} tags The tags to check. + * @returns {Promise>} Map of Aleo Record tags and whether they appeared in any inputs on chain. If boolean corresponding to the tag has a true value, that Record is considered spent by the Aleo Network. + */ + checkTags(tags: string[]): Promise>; + + /** + * Find a credits.aleo record with a given number of microcredits from the chosen provider. + * + * @param {number} microcredits The number of microcredits to search for. + * @param {RecordSearchParams} searchParameters Additional parameters to search for. + * @returns {Promise} The record if one is found. * * @example * // A class implementing record provider can be used to find a record with a given number of microcredits - * const record = await recordProvider.findCreditsRecord(5000, true, []); + * const record = await recordProvider.findCreditsRecord(5000, { unspent: true, nonces: [] }); * * // When a record is found but not yet used, its nonce should be added to the nonces array so that it is not * // found again if a subsequent search is performed - * const record2 = await recordProvider.findCreditsRecord(5000, true, [record.nonce()]); + * const record2 = await recordProvider.findCreditsRecord(5000, { unspent: true, nonces: [record.nonce()] }); * * // When the program manager is initialized with the record provider it will be used to find automatically find * // fee records and amount records for value transfers so that they do not need to be specified manually * const programManager = new ProgramManager("https://api.explorer.provable.com/v1", keyProvider, recordProvider); * programManager.transfer(1, "aleo166q6ww6688cug7qxwe7nhctjpymydwzy2h7rscfmatqmfwnjvggqcad0at", "public", 0.5); */ - findCreditsRecord(microcredits: number, unspent: boolean, nonces?: string[], searchParameters?: RecordSearchParams): Promise; + findCreditsRecord(microcredits: number, searchParameters: RecordSearchParams): Promise; /** * Find a list of credit.aleo records with a given number of microcredits from the chosen provider * - * @param {number} microcreditAmounts A list of separate microcredit amounts to search for (e.g. [5000, 100000]) - * @param {boolean} unspent Whether or not the record is unspent - * @param {string[]} nonces Nonces of records already found so that they are not found again - * @param {RecordSearchParams} searchParameters Additional parameters to search for - * @returns {Promise} A list of records with a value greater or equal to the amounts specified if such records exist, otherwise an error + * @param {number[]} microcreditAmounts A list of separate microcredit amounts to search for (e.g. [5000, 100000]). + * @param {RecordSearchParams} searchParameters Additional parameters to search for. + * @returns {Promise} A list of records with a value greater or equal to the amounts specified if such records exist, otherwise an error. * * @example * // A class implementing record provider can be used to find a record with a given number of microcredits - * const records = await recordProvider.findCreditsRecords([5000, 5000], true, []); + * const records = await recordProvider.findCreditsRecords([5000, 5000], { unspent: true, nonces: [] }); * * // When a record is found but not yet used, it's nonce should be added to the nonces array so that it is not * // found again if a subsequent search is performed * const nonces = []; * records.forEach(record => { nonces.push(record.nonce()) }); - * const records2 = await recordProvider.findCreditsRecord(5000, true, nonces); + * const records2 = await recordProvider.findCreditsRecord(5000, { unspent: true, nonces }); * * // When the program manager is initialized with the record provider it will be used to find automatically find * // fee records and amount records for value transfers so that they do not need to be specified manually * const programManager = new ProgramManager("https://api.explorer.provable.com/v1", keyProvider, recordProvider); * programManager.transfer(1, "aleo166q6ww6688cug7qxwe7nhctjpymydwzy2h7rscfmatqmfwnjvggqcad0at", "public", 0.5); */ - findCreditsRecords(microcreditAmounts: number[], unspent: boolean, nonces?: string[], searchParameters?: RecordSearchParams): Promise; + findCreditsRecords(microcreditAmounts: number[], searchParameters: RecordSearchParams): Promise; /** * Find an arbitrary record - * @param {boolean} unspent Whether or not the record is unspent - * @param {string[]} nonces Nonces of records already found so that they are not found again - * @param {RecordSearchParams} searchParameters Additional parameters to search for - * @returns {Promise} The record if found, otherwise an error + * @param {RecordSearchParams} searchParameters Additional parameters to search for. + * @returns {Promise} The record if found, otherwise an error. * * @example * // The RecordSearchParams interface can be used to create parameters for custom record searches which can then @@ -88,29 +105,41 @@ interface RecordProvider { * amount: number; * program: string; * recordName: string; - * constructor(startHeight: number, endHeight: number, credits: number, maxRecords: number, programName: string, recordName: string) { + * nonces: string[]; + * unspent: boolean; + * constructor( + * startHeight: number, + * endHeight: number, + * credits: number, + * maxRecords: number, + * programName: string, + * recordName: string, + * nonces: string[], + * unspent: boolean + * ) { * this.startHeight = startHeight; * this.endHeight = endHeight; * this.amount = amount; * this.program = programName; * this.recordName = recordName; + * this.nonces = nonces; + * this.unspent = unspent; * } * } * - * const params = new CustomRecordSearch(0, 100, 5000, "credits.aleo", "credits"); + * const params = new CustomRecordSearch(0, 100, 5000, "credits.aleo", "credits", [], true); * - * const record = await recordProvider.findRecord(true, [], params); + * const record = await recordProvider.findRecord(params); */ - findRecord(unspent: boolean, nonces?: string[], searchParameters?: RecordSearchParams): Promise; + findRecord(searchParameters: RecordSearchParams): Promise; /** * Find multiple records from arbitrary programs * - * @param {boolean} unspent Whether or not the record is unspent - * @param {string[]} nonces Nonces of records already found so that they are not found again - * @param {RecordSearchParams} searchParameters Additional parameters to search for - * @returns {Promise} The record if found, otherwise an error + * @param {RecordSearchParams} searchParameters Additional parameters to search for. + * @returns {Promise} The records if found, otherwise an error. * + * @example * // The RecordSearchParams interface can be used to create parameters for custom record searches which can then * // be passed to the record provider. An example of how this would be done for the credits.aleo program is shown * // below. @@ -118,24 +147,35 @@ interface RecordProvider { * class CustomRecordSearch implements RecordSearchParams { * startHeight: number; * endHeight: number; - * amount: number; - * maxRecords: number; - * programName: string; + * credits: number; + * program: string; * recordName: string; - * constructor(startHeight: number, endHeight: number, credits: number, maxRecords: number, programName: string, recordName: string) { + * nonces: string[]; + * unspent: boolean; + * constructor( + * startHeight: number, + * endHeight: number, + * credits: number, + * maxRecords: number, + * programName: string, + * recordName: string, + * nonces: string[], + * unspent: boolean + * ) { * this.startHeight = startHeight; * this.endHeight = endHeight; - * this.amount = amount; - * this.maxRecords = maxRecords; - * this.programName = programName; + * this.credits = credits; + * this.program = programName; * this.recordName = recordName; + * this.nonces = nonces; + * this.unspent = unspent; * } * } * * const params = new CustomRecordSearch(0, 100, 5000, 2, "credits.aleo", "credits"); * const records = await recordProvider.findRecord(true, [], params); */ - findRecords(unspent: boolean, nonces?: string[], searchParameters?: RecordSearchParams): Promise; + findRecords(searchParameters: RecordSearchParams): Promise; } /** @@ -153,7 +193,7 @@ class NetworkRecordProvider implements RecordProvider { /** * Set the account used to search for records * - * @param {Account} account The account to use for searching for records + * @param {Account} account The account used to use for searching for records. */ setAccount(account: Account) { this.account = account; @@ -162,11 +202,9 @@ class NetworkRecordProvider implements RecordProvider { /** * Find a list of credit records with a given number of microcredits by via the official Aleo API * - * @param {number[]} microcredits The number of microcredits to search for - * @param {boolean} unspent Whether or not the record is unspent - * @param {string[]} nonces Nonces of records already found so that they are not found again - * @param {RecordSearchParams} searchParameters Additional parameters to search for - * @returns {Promise} The record if found, otherwise an error + * @param {number[]} microcredits The number of microcredits to search for. + * @param {RecordSearchParams} searchParameters Additional parameters to search for. + * @returns {Promise} The records if found, otherwise an error. * * @example * // Create a new NetworkRecordProvider @@ -175,11 +213,11 @@ class NetworkRecordProvider implements RecordProvider { * const recordProvider = new NetworkRecordProvider(account, networkClient); * * // The record provider can be used to find records with a given number of microcredits - * const record = await recordProvider.findCreditsRecord(5000, true, []); + * const record = await recordProvider.findCreditsRecord(5000, { unspent: true, nonces: [] }); * * // When a record is found but not yet used, it's nonce should be added to the nonces parameter so that it is not * // found again if a subsequent search is performed - * const records = await recordProvider.findCreditsRecords(5000, true, [record.nonce()]); + * const records = await recordProvider.findCreditsRecords(5000, { unspent: true, nonces: [record.nonce()] }); * * // When the program manager is initialized with the record provider it will be used to find automatically find * // fee records and amount records for value transfers so that they do not need to be specified manually @@ -187,7 +225,7 @@ class NetworkRecordProvider implements RecordProvider { * programManager.transfer(1, "aleo166q6ww6688cug7qxwe7nhctjpymydwzy2h7rscfmatqmfwnjvggqcad0at", "public", 0.5); * * */ - async findCreditsRecords(microcredits: number[], unspent: boolean, nonces?: string[], searchParameters?: RecordSearchParams): Promise { + async findCreditsRecords(microcredits: number[], searchParameters: RecordSearchParams): Promise { let startHeight = 0; let endHeight = 0; let maxAmount = undefined; @@ -208,10 +246,6 @@ class NetworkRecordProvider implements RecordProvider { if ("maxAmount" in searchParameters && typeof searchParameters["maxAmount"] == "number") { maxAmount = searchParameters["maxAmount"]; } - - if ("unspent" in searchParameters && typeof searchParameters["unspent"] == "boolean") { - unspent = searchParameters["unspent"] - } } // If the end height is not specified, use the current block height @@ -225,17 +259,21 @@ class NetworkRecordProvider implements RecordProvider { logAndThrow("Start height must be less than end height"); } - return await this.networkClient.findRecords(startHeight, endHeight, unspent, ["credits.aleo"], microcredits, maxAmount, nonces, this.account.privateKey()); + const recordsPts = await this.networkClient.findRecords(startHeight, endHeight, searchParameters.unspent, ["credits.aleo"], microcredits, maxAmount, searchParameters.nonces, this.account.privateKey()); + return recordsPts.map((record) => ({ + owner: record.owner().toString(), + programName: 'credits.aleo', + recordName: 'credits', + recordPlaintext: record.toString(), + })); } /** * Find a credit record with a given number of microcredits by via the official Aleo API * - * @param {number} microcredits The number of microcredits to search for - * @param {boolean} unspent Whether or not the record is unspent - * @param {string[]} nonces Nonces of records already found so that they are not found again - * @param {RecordSearchParams} searchParameters Additional parameters to search for - * @returns {Promise} The record if found, otherwise an error + * @param {number} microcredits The number of microcredits to search for. + * @param {RecordSearchParams} searchParameters Additional parameters to search for. + * @returns {Promise} The record if found, otherwise an error. * * @example * // Create a new NetworkRecordProvider @@ -244,22 +282,22 @@ class NetworkRecordProvider implements RecordProvider { * const recordProvider = new NetworkRecordProvider(account, networkClient); * * // The record provider can be used to find records with a given number of microcredits - * const record = await recordProvider.findCreditsRecord(5000, true, []); + * const record = await recordProvider.findCreditsRecord(5000, { unspent: true, nonces: [] }); * * // When a record is found but not yet used, it's nonce should be added to the nonces parameter so that it is not * // found again if a subsequent search is performed - * const records = await recordProvider.findCreditsRecords(5000, true, [record.nonce()]); + * const records = await recordProvider.findCreditsRecords(5000, { unspent: true, nonces: [record.nonce()] }); * * // When the program manager is initialized with the record provider it will be used to find automatically find * // fee records and amount records for value transfers so that they do not need to be specified manually * const programManager = new ProgramManager("https://api.explorer.provable.com/v1", keyProvider, recordProvider); * programManager.transfer(1, "aleo166q6ww6688cug7qxwe7nhctjpymydwzy2h7rscfmatqmfwnjvggqcad0at", "public", 0.5); */ - async findCreditsRecord(microcredits: number, unspent: boolean, nonces?: string[], searchParameters?: RecordSearchParams): Promise { + async findCreditsRecord(microcredits: number, searchParameters: RecordSearchParams): Promise { let records = null; try { - records = await this.findCreditsRecords([microcredits], unspent, nonces, searchParameters); + records = await this.findCreditsRecords([microcredits], searchParameters); } catch (e) { console.log("No records found with error:", e); } @@ -275,14 +313,27 @@ class NetworkRecordProvider implements RecordProvider { /** * Find an arbitrary record. WARNING: This function is not implemented yet and will throw an error. */ - async findRecord(unspent: boolean, nonces?: string[], searchParameters?: RecordSearchParams): Promise { - throw new Error("Not implemented"); + async findRecord(searchParameters: RecordSearchParams): Promise { + let records; + + try { + records = await this.findRecords(searchParameters); + } catch (e) { + console.log("No records found with error:", e); + } + + if (records && records.length > 0) { + return records[0]; + } + + console.error("Record not found with error:", records); + throw new Error("Record not found"); } /** * Find multiple records from a specified program. */ - async findRecords(unspent: boolean, nonces?: string[], searchParameters?: RecordSearchParams): Promise { + async findRecords(searchParameters: RecordSearchParams): Promise { let startHeight = 0; let endHeight = 0; let amounts = undefined; @@ -306,10 +357,6 @@ class NetworkRecordProvider implements RecordProvider { maxAmount = searchParameters["maxAmount"]; } - if ("nonces" in searchParameters && Array.isArray(searchParameters["nonces"]) && searchParameters["nonces"].every((item: any) => typeof item === "string")) { - nonces = searchParameters["nonces"]; - } - if ("program" in searchParameters && typeof searchParameters["program"] == "string") { programs = [searchParameters["program"]]; } @@ -317,26 +364,36 @@ class NetworkRecordProvider implements RecordProvider { if ("programs" in searchParameters && Array.isArray(searchParameters["programs"]) && searchParameters["programs"].every((item: any) => typeof item === "string")) { programs = searchParameters["programs"]; } - - if ("unspent" in searchParameters && typeof searchParameters["unspent"] == "boolean") { - unspent = searchParameters["unspent"] - } } - // If the end height is not specified, use the current block height + // If the end height is not specified, use the current block height. if (endHeight == 0) { const end = await this.networkClient.getLatestHeight(); endHeight = end; } - // If the start height is greater than the end height, throw an error + // If the start height is greater than the end height, throw an error. if (startHeight >= endHeight) { logAndThrow("Start height must be less than end height"); } - return await this.networkClient.findRecords(startHeight, endHeight, unspent, programs, amounts, maxAmount, nonces, this.account.privateKey()); + const recordPts = await this.networkClient.findRecords(startHeight, endHeight, searchParameters.unspent, programs, amounts, maxAmount, searchParameters.nonces, this.account.privateKey()); + return recordPts.map((record) => ({ + record_plaintext: record.toString(), + })); } + async encryptedRecords(recordsFilter: RecordSearchParams, responseFilter?: RecordsResponseFilter): Promise { + throw new Error("Not implemented"); + } + + async checkSerialNumbers(serialNumbers: string[]): Promise> { + throw new Error("Not implemented"); + } + + async checkTags(tags: string[]): Promise> { + throw new Error("Not implemented"); + } } /** @@ -354,16 +411,22 @@ class NetworkRecordProvider implements RecordProvider { * * // The record provider can be used to find records with a given number of microcredits and the block height search * // can be used to find records within a given block height range - * const record = await recordProvider.findCreditsRecord(5000, true, [], params); + * const record = await recordProvider.findCreditsRecord(5000, { unspent: true, nonces: [], ...params }); * */ class BlockHeightSearch implements RecordSearchParams { startHeight: number; endHeight: number; - constructor(startHeight: number, endHeight: number) { + unspent: boolean; + constructor(startHeight: number, endHeight: number, unspent?: boolean) { this.startHeight = startHeight; this.endHeight = endHeight; + this.unspent = !!unspent; } } -export { BlockHeightSearch, NetworkRecordProvider, RecordProvider, RecordSearchParams}; +export { + BlockHeightSearch, + NetworkRecordProvider, + RecordProvider, +}; \ No newline at end of file diff --git a/sdk/tests/data/records.ts b/sdk/tests/data/records.ts index f95572ac5..7d53ecf76 100644 --- a/sdk/tests/data/records.ts +++ b/sdk/tests/data/records.ts @@ -27,11 +27,203 @@ const RECORD_PLAINTEXT_STRING = `{ const VIEW_KEY_STRING = "AViewKey1ccEt8A2Ryva5rxnKcAbn7wgTaTsb79tzkKHFpeKsm9NX"; const RECORD_VIEW_KEY_STRING = "4445718830394614891114647247073357094867447866913203502139893824059966201724field"; +const ENCRYPTED_RECORDS = [ + { + "commitment": "6965909872581584914039191373421463306059339471297771776610572511362422620805field", + "checksum": "2207226491095267609257407999738609780640985730602113917526120008525943934340field", + "block_height": 10002012, + "program_name": "credits.aleo", + "function_name": "transfer_public_to_private", + "output_index": 0, + "owner": "ciphertext1qyqzlxhmhtgtjaee6new2hsfls2ygj68va5h009u3h5htdp59gqasqcwfsafx", + "record_ciphertext": "record1qvqsqtu6lwadpwth88209e27p87pg3ztgankjaauhjx7jad5xs4qrkqrqyxx66trwfhkxun9v35hguerqqpqzqxkezwzg7z8lvpj4t2as605kn9ge8k9cvfls3mg0sqult798mfwqcskzfqlyn83lu3e9kexqmklf5ad9d4shvz5ntuenzrdujqpq0esqdddm55", + "record_name": "credits", + "record_nonce": "429364576614161221583920327616773968748250238602322587322300571348491329825group", + "transaction_id": "at1rdlnll8kljpuy506f0tx0r0xd2fck60hw7phkmjnptke77xukg8sekd6c9 ", + "transition_id": "au1f505f9uvu39f2mys9g0gl2qe5t3pr8tsdutzj4pd2apd5l6hzuqqv0t2n3 ", + "transaction_index": 0, + "transition_index": 0 + }, + { + "commitment": "1188397772964800575271786433438577861359270789629265569589281492544120074436field", + "checksum": "5605422683473081183936132265672104254159529769293480273428181950973232566109field", + "block_height": 10003899, + "program_name": "token_registry.aleo", + "function_name": "transfer_public_to_private", + "output_index": 0, + "owner": "ciphertext1qyqvlfsfleandncmy35mrzr2fwt0epgmnmj34dr6nq7zlndg2v3murskqakke", + "record_ciphertext": "record1qvqspnaxp8l8kdk0rvjxnvvgdf9edly9rw0w2x4502vrct7d4pfj80swqsrxzmt0w4h8ggcqqgqsprxt748jj4tl4lm799ys2qjnzz5s6zjrrq6r3ftpn26x4nscncqwpp6x76m9de0kjezrqqpqyq9x2mvm0uzcmt8unclhhze2aa0w2exzx6dwaqrzm879ya65gdytp55qf2ysvks4435vnzkmgwszppeh5vyud97kurp50zn95h7pakj3y8m90p6x2unwv9k97ct4w35x7unf0fshg6t0de0hyet3w45hyetyyvqqyqgqp7tq23f3nz56q6ptwrjyr3xf657pshhrmhvm8yqpuhkfjxjp85gpqct4w35x7unf0fjkghm4de6xjmprqqpqzqyp9aa48avx62cfnce36trczs0fj88ydw8cxg38pv69t983an7gqgaqvv25079m7w7gayzq25ddxadmnnxh5jttm4ra6jrn00vqn7cq7a36w4h", + "record_name": "Token", + "record_nonce": "7096758660619171646018003922303056044411325151108024435925109326208495060538group", + "transaction_id": "at1khgxe7rt7tlcv6kyrytlt57rdu4t67euelyy4fzrysa5spplms8qmyzm0g ", + "transition_id": "au1jxjw3vxpnjl7vrs3ckhkta0yxwq87wxeh7pwcs9q4nfw3knzlgzs95m32s ", + "transaction_index": 0, + "transition_index": 0 + } +] + +const OWNED_RECORDS = [ + { + block_height: 6090931, + commitment: '3190431573263899914391947973857035974322781794111836590387626738139790056909field', + function_name: 'place_bid', + output_index: 0, + owner: '7447609208500997115362207913251419702258326233440670198345216549215225004914field', + program_name: 'private_auction.aleo', + record_ciphertext: 'record1qyqspn9v8rwmmtwfynxl7z98sr3hgevduqk7wl4ufmp8yxanp9x5lhgdqsrxy6tyv3jhyscqqgpqp2k5sw5f37f86hge97ls2avx94pvg7fnaxr7uqwfwkqaljq8jlgyg480mg8fy67fkhqe6ysjxdr47whlt09gwuwmlme57nxvz4kn5qyqy6tygvqqyqsqaljsdk8g0g7f9t4s8z2utywzg6qwpgrl57k8fzvcz5qrthzy5qrk422ak9e9pwylg9k7fh99qa05qu4qj9k5mn7hjf5586fmlrk6qpqxv9kk7atwws3sqqspqryrtmup2kn26693c4f7e79gc0yfdammkxexk84vt0z5wms8dgnq2ztfwd0hw6twdejhygcqqgqsppdjyztk35ekkzq60jx7gg498tccxc9l0ysmk6hal0yglk436ng8pq5wrq99rlhqqglf0gvv70lfavzfu6mgf4sgzmuwej2a2f4umgzssk0fhc', + record_plaintext: '{\n' + + ' owner: aleo1q8zc0asncaw9d83ft2dynyqz08fcpq3p40depmrj4wjda28rdvrsvegg45.private,\n' + + ' bidder: aleo1jqnajd8g6ezqjq0eefm4zeqynwx6vzed8flnkmejw0afy09dusrszzk46k.private,\n' + + ' id: 127430097643352927347108200field.private,\n' + + ' amount: 2u64.private,\n' + + ' is_winner: false.private,\n' + + ' _nonce: 2648035478322331583038604395085314793293985787056490619358776499723646871560group.public,\n' + + ' _version: 0u8.public\n' + + '}', + record_name: 'Bid', + spent: false, + tag: '5941252181432651644402279701137165256963073258332916685063623109173576520831field', + transaction_id: 'at1unmfl5gv6d28c9dt405kxxj8nl7ytl5eq0ue9ctpc7lpmds8qgqqqglh2z ', + transition_id: 'au1rc32lk3umuye2ccpqkx8gw5m2cf92a29wzyfj5r7tg9jtnd2duxq6gtuss ', + transaction_index: 2, + transition_index: 0 + }, + { + block_height: 10139458, + commitment: '1402624598475573407524150006714553637670194594508553840106512461758960165497field', + function_name: 'transfer_public_to_private', + output_index: 0, + owner: '7447609208500997115362207913251419702258326233440670198345216549215225004914field', + program_name: 'credits.aleo', + record_ciphertext: 'record1qvqsq9pcyh8s0zlqwydq0uef42kanl88hct6c7f0y7m3gawxv8er20g2qyxx66trwfhkxun9v35hguerqqpqzqzue2ynz2mfnucdf9gft6cuqussdtge8efqwnlkqvq5nr52nhq9pmv47u20cmsk6mnsl70kxhengndepngqja8s5myu0778nncrttls576mt26', + record_plaintext: '{\n' + + ' owner: aleo1q8zc0asncaw9d83ft2dynyqz08fcpq3p40depmrj4wjda28rdvrsvegg45.private,\n' + + ' microcredits: 1000000u64.private,\n' + + ' _nonce: 4974295747251926833599773262811444029929021845727007977270637854284605120473group.public,\n' + + ' _version: 1u8.public\n' + + '}', + record_name: 'credits', + spent: false, + tag: '2965517500209150226508265073635793457193572667031485750956287906078711930968field', + transaction_id: 'at10g988ruzr70rv0jrnx67ay0f62gzn0vsmlpgsk9seqzd4k406sys8q9xhk ', + transition_id: 'au1wr7q6y6fw2gyrwem2zjm8kp2lvl04eay8hqmaz6l2gd4p60ddy9s2lj2qr ', + transaction_index: 0, + transition_index: 0 + }, + { + block_height: 10140546, + commitment: '6211743159355787867034474916630197652498323872351981366700814088987411118433field', + function_name: 'transfer_public_to_private', + output_index: 0, + owner: '7447609208500997115362207913251419702258326233440670198345216549215225004914field', + program_name: 'credits.aleo', + record_ciphertext: 'record1qvqspk7dttx96hemjmnzkf2vf7exfxt6uu04xxxhr987nycq5xx4lkc3qyxx66trwfhkxun9v35hguerqqpqzqqjw24ydxw5t5jgjhszz6dmtgwcw2r0ckgkg3kkxkh8y8cy0gump9an579cxeg5rxkawwdvh2wmesusl8tpwldpe60wkmgzdgd97pns2akmwge', + record_plaintext: '{\n' + + ' owner: aleo1q8zc0asncaw9d83ft2dynyqz08fcpq3p40depmrj4wjda28rdvrsvegg45.private,\n' + + ' microcredits: 2000000u64.private,\n' + + ' _nonce: 2445210375074181986314301912374182923270809668425048232267618676093400660603group.public,\n' + + ' _version: 1u8.public\n' + + '}', + record_name: 'credits', + spent: false, + tag: '8421937347379608036510120951995833971195343843566214313082589116311107280540field', + transaction_id: 'at1hy45m9w56cr8f5yzqp675heh3rde9996exy9875ylzk2w2nmt5qsfudud5 ', + transition_id: 'au1yp2x7t378w3d74kkkz9vcq7ckeg4h4amc3ltysmylz7a85yuy5pqefcjmh ', + transaction_index: 0, + transition_index: 0 + } +] + +const OWNED_CREDITS_RECORDS = [ + { + block_height: 6090931, + commitment: '3190431573263899914391947973857035974322781794111836590387626738139790056909field', + function_name: 'place_bid', + output_index: 0, + owner: '7447609208500997115362207913251419702258326233440670198345216549215225004914field', + program_name: 'private_auction.aleo', + record_ciphertext: 'record1qyqspn9v8rwmmtwfynxl7z98sr3hgevduqk7wl4ufmp8yxanp9x5lhgdqsrxy6tyv3jhyscqqgpqp2k5sw5f37f86hge97ls2avx94pvg7fnaxr7uqwfwkqaljq8jlgyg480mg8fy67fkhqe6ysjxdr47whlt09gwuwmlme57nxvz4kn5qyqy6tygvqqyqsqaljsdk8g0g7f9t4s8z2utywzg6qwpgrl57k8fzvcz5qrthzy5qrk422ak9e9pwylg9k7fh99qa05qu4qj9k5mn7hjf5586fmlrk6qpqxv9kk7atwws3sqqspqryrtmup2kn26693c4f7e79gc0yfdammkxexk84vt0z5wms8dgnq2ztfwd0hw6twdejhygcqqgqsppdjyztk35ekkzq60jx7gg498tccxc9l0ysmk6hal0yglk436ng8pq5wrq99rlhqqglf0gvv70lfavzfu6mgf4sgzmuwej2a2f4umgzssk0fhc', + record_plaintext: '{\n' + + ' owner: aleo1q8zc0asncaw9d83ft2dynyqz08fcpq3p40depmrj4wjda28rdvrsvegg45.private,\n' + + ' bidder: aleo1jqnajd8g6ezqjq0eefm4zeqynwx6vzed8flnkmejw0afy09dusrszzk46k.private,\n' + + ' id: 127430097643352927347108200field.private,\n' + + ' amount: 2u64.private,\n' + + ' is_winner: false.private,\n' + + ' _nonce: 2648035478322331583038604395085314793293985787056490619358776499723646871560group.public,\n' + + ' _version: 0u8.public\n' + + '}', + record_name: 'Bid', + spent: false, + tag: '5941252181432651644402279701137165256963073258332916685063623109173576520831field', + transaction_id: 'at1unmfl5gv6d28c9dt405kxxj8nl7ytl5eq0ue9ctpc7lpmds8qgqqqglh2z ', + transition_id: 'au1rc32lk3umuye2ccpqkx8gw5m2cf92a29wzyfj5r7tg9jtnd2duxq6gtuss ', + transaction_index: 2, + transition_index: 0 + }, + { + block_height: 10139458, + commitment: '1402624598475573407524150006714553637670194594508553840106512461758960165497field', + function_name: 'transfer_public_to_private', + output_index: 0, + owner: '7447609208500997115362207913251419702258326233440670198345216549215225004914field', + program_name: 'credits.aleo', + record_ciphertext: 'record1qvqsq9pcyh8s0zlqwydq0uef42kanl88hct6c7f0y7m3gawxv8er20g2qyxx66trwfhkxun9v35hguerqqpqzqzue2ynz2mfnucdf9gft6cuqussdtge8efqwnlkqvq5nr52nhq9pmv47u20cmsk6mnsl70kxhengndepngqja8s5myu0778nncrttls576mt26', + record_plaintext: '{\n' + + ' owner: aleo1q8zc0asncaw9d83ft2dynyqz08fcpq3p40depmrj4wjda28rdvrsvegg45.private,\n' + + ' microcredits: 1000000u64.private,\n' + + ' _nonce: 4974295747251926833599773262811444029929021845727007977270637854284605120473group.public,\n' + + ' _version: 1u8.public\n' + + '}', + record_name: 'credits', + spent: false, + tag: '2965517500209150226508265073635793457193572667031485750956287906078711930968field', + transaction_id: 'at10g988ruzr70rv0jrnx67ay0f62gzn0vsmlpgsk9seqzd4k406sys8q9xhk ', + transition_id: 'au1wr7q6y6fw2gyrwem2zjm8kp2lvl04eay8hqmaz6l2gd4p60ddy9s2lj2qr ', + transaction_index: 0, + transition_index: 0 + }, + { + block_height: 10140546, + commitment: '6211743159355787867034474916630197652498323872351981366700814088987411118433field', + function_name: 'transfer_public_to_private', + output_index: 0, + owner: '7447609208500997115362207913251419702258326233440670198345216549215225004914field', + program_name: 'credits.aleo', + record_ciphertext: 'record1qvqspk7dttx96hemjmnzkf2vf7exfxt6uu04xxxhr987nycq5xx4lkc3qyxx66trwfhkxun9v35hguerqqpqzqqjw24ydxw5t5jgjhszz6dmtgwcw2r0ckgkg3kkxkh8y8cy0gump9an579cxeg5rxkawwdvh2wmesusl8tpwldpe60wkmgzdgd97pns2akmwge', + record_plaintext: '{\n' + + ' owner: aleo1q8zc0asncaw9d83ft2dynyqz08fcpq3p40depmrj4wjda28rdvrsvegg45.private,\n' + + ' microcredits: 2000000u64.private,\n' + + ' _nonce: 2445210375074181986314301912374182923270809668425048232267618676093400660603group.public,\n' + + ' _version: 1u8.public\n' + + '}', + record_name: 'credits', + spent: false, + tag: '8421937347379608036510120951995833971195343843566214313082589116311107280540field', + transaction_id: 'at1hy45m9w56cr8f5yzqp675heh3rde9996exy9875ylzk2w2nmt5qsfudud5 ', + transition_id: 'au1yp2x7t378w3d74kkkz9vcq7ckeg4h4amc3ltysmylz7a85yuy5pqefcjmh ', + transaction_index: 0, + transition_index: 0 + } +] + +const CHECK_SNS_RESPONSE = { '3673836024253895240205884165890003872225300531298514519146928213266356324646field': true } + +const CHECK_TAGS_RESPONSE = { + '2965517500209150226508265073635793457193572667031485750956287906078711930968field': false, + '8421937347379608036510120951995833971195343843566214313082589116311107280540field': false, + '5941252181432651644402279701137165256963073258332916685063623109173576520831field': false +} + export { CREDITS_RECORD_V1, CREDITS_RECORD_VIEW_KEY, CREDITS_SENDER_CIPHERTEXT, CREDITS_SENDER_PLAINTEXT, + CHECK_SNS_RESPONSE, + CHECK_TAGS_RESPONSE, + ENCRYPTED_RECORDS, + OWNED_RECORDS, + OWNED_CREDITS_RECORDS, RECORD_CIPHERTEXT_STRING, RECORD_CIPHERTEXT_STRING_COPY, RECORD_CIPHERTEXT_STRING_NOT_OWNED, diff --git a/sdk/tests/network-client.test.ts b/sdk/tests/network-client.test.ts index 25ca9f762..b14c9abd5 100644 --- a/sdk/tests/network-client.test.ts +++ b/sdk/tests/network-client.test.ts @@ -370,17 +370,7 @@ describe("NodeConnection", () => { it("should throw for a malformed tx ID", async () => { const connection = new AleoNetworkClient(host); - try { - await connection.waitForTransactionConfirmation(invalidTx); - throw new Error( - "Expected waitForTransactionConfirmation to throw", - ); - } catch (err: any) { - console.log(err.message); - if (connection.network === "mainnet") { - expect(err.message).to.include("Malformed transaction ID"); - } - } + expectThrows(() => connection.waitForTransactionConfirmation(invalidTx)); }); }); diff --git a/sdk/tests/record-provider.integration.ts b/sdk/tests/record-provider.integration.ts index ef73616a3..53c864e0f 100644 --- a/sdk/tests/record-provider.integration.ts +++ b/sdk/tests/record-provider.integration.ts @@ -18,23 +18,25 @@ describe('RecordProvider', () => { try { // Find two records with findCreditsRecords const nonces: string[] = []; - const records = await recordProvider.findCreditsRecords([100, 200], true, []); + const records = await recordProvider.findCreditsRecords([100, 200], { unspent: true, nonces }); if (Array.isArray(records)) { expect(records.length).equal(2); records.forEach((record) => { - nonces.push(record.nonce()); + let pt = new RecordPlaintext(record.record_plaintext); + nonces.push(pt.nonce()); }); } else { expect(Array.isArray(records)).equal(true); } // Get another two records with findCreditsRecords and ensure they are unique - const records2 = await recordProvider.findCreditsRecords([100, 200], true, nonces); + const records2 = await recordProvider.findCreditsRecords([100, 200], { unspent: true, nonces }); if (Array.isArray(records2)) { expect(records2.length).equal(2); records2.forEach((record) => { - expect(nonces.includes(record.nonce())).equal(false); - nonces.push(record.nonce()); + let pt = new RecordPlaintext(record.record_plaintext); + expect(nonces.includes(pt.nonce())).equal(false); + nonces.push(pt.nonce()); }); } else { expect(Array.isArray(records2)).equal(true); diff --git a/sdk/tests/record-provider.test.ts b/sdk/tests/record-provider.test.ts index a54675637..20247f2c8 100644 --- a/sdk/tests/record-provider.test.ts +++ b/sdk/tests/record-provider.test.ts @@ -16,7 +16,7 @@ describe.skip('RecordProvider', () => { describe('Record provider', () => { it('should not find records where there are none', async () => { const params = new BlockHeightSearch(0, 100); - const records = await recordProvider.findCreditsRecords([100, 200], true, [], params); + const records = await recordProvider.findCreditsRecords([100, 200], params); expect(records).equal([]); }); });