From 55d7e3b90a91bcd81872de7a5d67f8a988d88cc0 Mon Sep 17 00:00:00 2001 From: Orloaft Date: Thu, 13 Apr 2023 14:07:40 -0400 Subject: [PATCH 1/5] document ethereum.js package --- yarn-project/ethereum.js/.eslintrc.cjs | 2 +- .../abi/abi-coder/ethers/abi-coder.ts | 555 ++++++++++++++++-- .../contract/abi/abi-coder/ethers/errors.ts | 20 + .../src/contract/abi/contract_abi.ts | 61 +- .../contract/abi/contract_abi_definition.ts | 116 +++- .../src/contract/abi/contract_entry.ts | 15 +- .../src/contract/abi/contract_error_entry.ts | 62 +- .../src/contract/abi/contract_event_entry.ts | 34 +- .../contract/abi/contract_function_entry.ts | 60 +- .../ethereum.js/src/contract/bytes.ts | 203 +++++++ .../src/contract/constructor_interaction.ts | 10 +- .../ethereum.js/src/contract/contract.test.ts | 8 +- .../ethereum.js/src/contract/contract.ts | 143 ++++- .../src/contract/contract_tx_receipt.ts | 97 ++- .../ethereum.js/src/contract/decode_error.ts | 22 +- .../src/contract/fixtures/TestContract.ts | 151 ++++- .../contract/fixtures/TestNoCtorContract.ts | 59 +- .../src/contract/function_interaction.ts | 118 +++- .../ethereum.js/src/contract/gen_def/index.ts | 214 +++++++ .../src/contract/gen_def/sources/config.ts | 134 ++++- .../src/contract/gen_def/sources/index.ts | 22 +- .../gen_def/sources/source-etherscan.ts | 18 + .../contract/gen_def/sources/source-files.ts | 8 + .../gen_def/sources/source-foundry.ts | 16 +- .../gen_def/sources/source-truffle.ts | 16 +- .../src/contract/sent_contract_tx.ts | 27 +- .../src/contract/sent_deploy_contract_tx.ts | 11 +- .../ethereum.js/src/crypto/keccak256/index.ts | 16 + .../ethereum.js/src/crypto/pbkdf2/index.ts | 21 + .../ethereum.js/src/crypto/scrypt/index.ts | 38 ++ .../src/eth_account/eth_account.ts | 123 +++- .../ethereum.js/src/eth_rpc/ethereum_rpc.ts | 194 +++++- .../ethereum.js/src/eth_rpc/sent_tx.ts | 34 +- .../ethereum.js/src/eth_rpc/tx_hash.ts | 74 ++- .../src/eth_rpc/types/block_response.ts | 250 ++++++-- .../src/eth_rpc/types/call_request.ts | 98 +++- .../src/eth_rpc/types/estimate_gas_request.ts | 96 ++- .../src/eth_rpc/types/log_request.ts | 60 +- .../src/eth_rpc/types/log_response.ts | 128 +++- .../src/eth_rpc/types/number_or_tag.ts | 3 + .../src/eth_rpc/types/transaction_receipt.ts | 138 ++++- .../src/eth_rpc/types/transaction_request.ts | 64 +- .../src/eth_rpc/types/transaction_response.ts | 193 ++++-- .../ethereum.js/src/eth_sign/hash_message.ts | 8 + yarn-project/ethereum.js/src/eth_sign/sign.ts | 106 +++- .../src/eth_transaction/eth_transaction.ts | 40 +- .../src/eth_transaction/sign_transaction.ts | 40 +- .../ethereum.js/src/eth_typed_data/index.ts | 10 + .../src/eth_typed_data/typed_data.ts | 51 +- .../ethereum.js/src/eth_wallet/eth_wallet.ts | 154 ++++- .../ethereum.js/src/hex_string/index.ts | 47 ++ .../ethereum.js/src/keystore/index.test.ts | 11 +- .../ethereum.js/src/keystore/index.ts | 189 +++++- yarn-project/ethereum.js/src/log/console.ts | 25 +- yarn-project/ethereum.js/src/log/debug.ts | 49 ++ .../src/provider/ethereum_provider.ts | 61 +- .../src/provider/json_rpc_provider.ts | 47 +- .../src/provider/wallet_provider.ts | 264 ++++++++- .../ethereum.js/src/provider/web3_adapter.ts | 29 +- .../ethereum.js/src/provider/web3_provider.ts | 71 ++- yarn-project/ethereum.js/src/retry/index.ts | 18 + .../ethereum.js/src/serialize/deserializer.ts | 123 +++- .../ethereum.js/src/serialize/free_funcs.ts | 92 ++- .../ethereum.js/src/serialize/serializer.ts | 71 ++- yarn-project/ethereum.js/src/sleep/index.ts | 40 +- yarn-project/ethereum.js/src/timer/index.ts | 26 +- 66 files changed, 4770 insertions(+), 534 deletions(-) diff --git a/yarn-project/ethereum.js/.eslintrc.cjs b/yarn-project/ethereum.js/.eslintrc.cjs index 97d6f187813..e659927475c 100644 --- a/yarn-project/ethereum.js/.eslintrc.cjs +++ b/yarn-project/ethereum.js/.eslintrc.cjs @@ -1 +1 @@ -module.exports = require('@aztec/foundation/eslint-legacy'); +module.exports = require('@aztec/foundation/eslint'); diff --git a/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts b/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts index 864d077ca35..57658916c67 100644 --- a/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts +++ b/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts @@ -7,11 +7,26 @@ const NegativeOne = BigInt(-1); const Zero = BigInt(0); const MaxUint256 = BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); +/** + * Type representing a parameter for Ethereum contract events and functions. + */ type ParamType = { - name?: string; - type: string; - indexed?: boolean; - components?: Array; + /** + * The name of the parameter or variable. + */ +name?: string; + /** + * The data type for a specific parameter. + */ +type: string; + /** + * Indicates whether the event parameter is indexed or not. + */ +indexed?: boolean; + /** + * An array of component objects representing the structure and types of a tuple. + */ +components?: Array; }; // type EventFragment = { @@ -59,25 +74,84 @@ function verifyType(type: string): string { return type; } +/** + * Type representing the state of a parser for parsing and validating Solidity signatures. + */ type ParseState = { - allowArray?: boolean; - allowName?: boolean; - allowParams?: boolean; - allowType?: boolean; - readArray?: boolean; + /** + * Indicates whether an array type is allowed. + */ +allowArray?: boolean; + /** + * Determines if a name is allowed for the parameter. + */ +allowName?: boolean; + /** + * Indicates whether parameters are allowed for the current node. + */ +allowParams?: boolean; + /** + * Determines if type can be accepted or not. + */ +allowType?: boolean; + /** + * Indicates whether the array is being read during parsing. + */ +readArray?: boolean; }; +/** + * Represents a node in the Abstract Syntax Tree (AST) during the parsing of Solidity signatures. It contains all necessary information about the current parsing state, such as type, name, parent, and components. + */ type ParseNode = { - parent?: any; - type?: string; - name?: string; - state?: ParseState; - indexed?: boolean; - components?: Array; + /** + * The parent node of the current parse tree. + */ +parent?: any; + /** + * The data type of the parameter. + */ +type?: string; + /** + * The name representing an identifiable entity. + */ +name?: string; + /** + * Represents the current state of parsing in a given node. + */ +state?: ParseState; + /** + * Indicates if the parameter is indexed in event logs. + */ +indexed?: boolean; + /** + * An array of nested parameter types. + */ +components?: Array; }; +/** + * Parses a parameter string into a ParamType object with its type, name, components, and indexed information. + * This function supports parsing complex types, such as tuples and arrays, as well as simple types like uint, int, etc. + * It also handles optional indexed property for event parameters. + * Throws an error if there is an unexpected character or mismatched parentheses in the input param string. + * + * @param param - The parameter string to be parsed. + * @param allowIndexed - Optional flag indicating whether to parse indexed property for event parameters. + * @returns A ParamType object with the parsed information. + */ function parseParam(param: string, allowIndexed?: boolean): ParamType { - function throwError(i: number) { + /** + * Throws a custom error with the specified reason, code, and additional error information. + * This function is used to generate standardized error messages for better error handling + * and debugging throughout the codebase. + * + * @param reason - The main reason for the error being thrown. + * @param code - The error code associated with the particular type of error. + * @param params - An optional object containing any additional information related to the error. + * @throws {Error} A custom error with the provided details. + */ +function throwError(i: number) { throw new Error('unexpected character "' + param[i] + '" at position ' + i + ' in "' + param + '"'); } @@ -380,7 +454,26 @@ function parseParam(param: string, allowIndexed?: boolean): ParamType { /////////////////////////////////// // Coders -type DecodedResult = { consumed: number; value: T }; +type DecodedResult = { /** + * The number of bytes consumed during decoding. + */ +/** + * The number of bytes consumed during decoding. + */ +consumed: number; /** + * The actual data value for the corresponding coder type. + */ +/** + * The actual data value for the corresponding coder type. + */ +value: T }; +/** + * The Coder class is an abstract base class that provides encoding and decoding functionality + * for specific types in the Ethereum ABI (Application Binary Interface) format. It handles the + * conversion of Solidity types to JavaScript types and vice versa, allowing for easy interaction + * with Ethereum smart contracts. Each derived Coder class corresponds to a specific Solidity type, + * implementing the necessary logic for encoding and decoding values of that type. + */ abstract class Coder { readonly name: string; readonly type: string; @@ -393,8 +486,26 @@ abstract class Coder { this.dynamic = dynamic; } - abstract encode(value: any): Buffer; - abstract decode(data: Buffer, offset: number): DecodedResult; + /** + * Encode the given value using the coder's type and rules. + * The function takes a value as input, processes it according to the specific + * coder implementation and returns a buffer containing the encoded value. + * Throws an error if the input value is not valid for the coder's type. + * + * @param value - The value to be encoded. + * @returns A Buffer containing the encoded value. + */ +abstract encode(value: any): Buffer; + /** + * Decodes the given data buffer at the specified offset using the coder's type and properties. + * Returns an object containing the number of bytes consumed during decoding and the decoded value. + * Throws an error if there is insufficient data or any issues encountered during the decoding process. + * + * @param data - The input data buffer to be decoded. + * @param offset - The starting position in the data buffer where decoding should begin. + * @returns A DecodedResult object with the 'consumed' and 'value' properties. + */ +abstract decode(data: Buffer, offset: number): DecodedResult; } // Clones the functionality of an existing Coder, but without a localName @@ -402,24 +513,69 @@ class CoderAnonymous extends Coder { constructor(private coder: Coder) { super(coder.name, coder.type, undefined, coder.dynamic); } - encode(value: any): Buffer { + /** + * Encode the given value into a Buffer based on the coder type. + * This function handles various data types such as numbers, booleans, fixed bytes, and strings. + * Throws an error if the input value is invalid or not compatible with the coder type. + * + * @param value - The value to be encoded according to the coder type. + * @returns A Buffer containing the encoded value. + */ +encode(value: any): Buffer { return this.coder.encode(value); } - decode(data: Buffer, offset: number): DecodedResult { + /** + * Decodes the given data starting from the specified offset using the associated coder. + * Returns an object containing the consumed bytes and the decoded value. + * Throws an error if there is insufficient data for decoding or any other issue occurs during decoding. + * + * @param data - The buffer containing the encoded data to be decoded. + * @param offset - The position in the buffer where the decoding should start. + * @returns An object with 'consumed' property indicating the number of bytes consumed during decoding, + * and 'value' property holding the decoded value. + */ +decode(data: Buffer, offset: number): DecodedResult { return this.coder.decode(data, offset); } } +/** + * CoderNull is a specific coder class for handling null values in encoding and decoding operations. + * It extends the base Coder class and provides custom implementations for encoding and decoding null values + * while complying with the Ethereum ABI specification. The encoded output for a null value is an empty buffer + * and consumes no data during the decoding process, returning a null value as the result. + */ class CoderNull extends Coder { constructor(localName: string) { super('null', '', localName, false); } - encode(): Buffer { + /** + * Encode the given value using the Coder's type and rules. + * Converts various data types (boolean, number, string, etc.) into a Buffer representation + * based on the ABI encoding specifications. Throws an error if the input value is invalid + * or cannot be encoded according to the Coder's rules. + * + * @param value - The value to be encoded according to the Coder's type and rules. + * @returns A Buffer containing the encoded representation of the input value. + */ +encode(): Buffer { return Buffer.alloc(0); } - decode(data: Buffer, offset: number): DecodedResult { + /** + * Decodes the provided data buffer starting from the given offset and returns an object with + * the decoded value and the number of bytes consumed during the decoding process. + * This function is used to decode ABI-encoded data for the specific coder type. + * + * @param data - The buffer containing the ABI-encoded data to be decoded. + * @param offset - The index at which to start decoding in the data buffer. + * @returns An object with the following properties: + * - `value`: The decoded value according to the coder type. + * - `consumed`: The number of bytes consumed during the decoding process. + * @throws An error if there is insufficient data or the data is invalid for the coder type. + */ +decode(data: Buffer, offset: number): DecodedResult { if (offset > data.length) { throw new Error('invalid null'); } @@ -430,6 +586,13 @@ class CoderNull extends Coder { } } +/** + * CoderNumber is a class that represents numeric values in the Ethereum ABI encoding/decoding process. + * It handles encoding and decoding of signed and unsigned integers of various sizes (number of bits). + * This class supports fixed-size integer types like int8, uint16, int256, etc. The encoded output + * is a Buffer of 32 bytes containing the value in big-endian format. When decoding, it returns the decoded + * result as a JavaScript BigInt or number (based on the size) along with the number of bytes consumed. + */ class CoderNumber extends Coder { readonly size: number; readonly signed: boolean; @@ -441,7 +604,17 @@ class CoderNumber extends Coder { this.signed = signed; } - encode(value: any): Buffer { + /** + * Encodes the given array of values according to the CoderArray rules. + * The input value must be an array, and its length should match + * the length specified in the CoderArray instance. If the length is dynamic, + * any number of elements are allowed. Throws an error if the input is not an array + * or its length does not match the expected length. + * + * @param value - The array of values to be encoded. + * @returns A Buffer containing the encoded data. + */ +encode(value: any): Buffer { try { let v = BigInt(value); if (this.signed) { @@ -475,7 +648,16 @@ class CoderNumber extends Coder { } } - decode(data: Buffer, offset: number): DecodedResult { + /** + * Decodes the provided data buffer at the specified offset using the current coder instance. + * Consumes a certain number of bytes from the data buffer and returns the decoded value along with the consumed byte count. + * Throws an error if there is insufficient data or any issues while decoding the given data. + * + * @param data - The data buffer to decode. + * @param offset - The starting offset in the data buffer for decoding. + * @returns An object containing the decoded value and the number of bytes consumed from the data buffer. + */ +decode(data: Buffer, offset: number): DecodedResult { if (data.length < offset + 32) { errors.throwError('insufficient data for ' + this.name + ' type', errors.INVALID_ARGUMENT, { arg: this.localName, @@ -497,16 +679,40 @@ class CoderNumber extends Coder { } const uint256Coder = new CoderNumber(32, false, 'none'); +/** + * CoderBoolean is a class that represents the 'bool' data type in Ethereum ABI encoding. + * It provides methods to encode and decode boolean values into their binary representation + * for use in Ethereum function calls and event logs. The class extends the abstract Coder class, + * inheriting its properties and methods while also implementing custom logic for handling boolean types. + * Instances of this class can be used to encode and decode boolean data, ensuring proper + * formatting and compatibility with the Ethereum blockchain. + */ class CoderBoolean extends Coder { constructor(localName: string) { super('bool', 'bool', localName, false); } - encode(value: boolean): Buffer { + /** + * Encodes the given value using the appropriate Coder, resulting in a Buffer. + * The encoded data can be later decoded using the corresponding 'decode' function. + * Throws an error if the input value is invalid or not compatible with the Coder type. + * + * @param value - The value to be encoded according to the Coder's type. + * @returns A Buffer containing the encoded data. + */ +encode(value: boolean): Buffer { return uint256Coder.encode(value ? 1 : 0); } - decode(data: Buffer, offset: number): DecodedResult { + /** + * Decodes the binary data from the provided buffer using the coder's associated type and offset. + * Throws an error if there is insufficient data, or if the decoded value does not match the expected format. + * + * @param data - The buffer containing the binary data to decode. + * @param offset - The starting position within the buffer to begin decoding. + * @returns An object containing the number of bytes consumed and the decoded value of the specified type. + */ +decode(data: Buffer, offset: number): DecodedResult { try { const result = uint256Coder.decode(data, offset); return { @@ -526,6 +732,11 @@ class CoderBoolean extends Coder { } } +/** + * The CoderFixedBytes class is responsible for encoding and decoding fixed-length byte arrays in ABI format. + * It inherits from the Coder base class and provides methods to encode and decode values of 'bytes' type with a specified length. + * The encoded data is compatible with Ethereum smart contracts, and this class plays a vital role in handling contract interactions. + */ class CoderFixedBytes extends Coder { readonly length: number; constructor(length: number, localName: string) { @@ -534,7 +745,17 @@ class CoderFixedBytes extends Coder { this.length = length; } - encode(value: Buffer | string): Buffer { + /** + * Encodes the given value using the coder and returns a Buffer. + * This function handles various data types such as numbers, booleans, fixed bytes, + * addresses, dynamic bytes, strings, arrays and tuples. It validates the input value + * based on the coder properties and converts them into a suitable binary format + * compatible with Ethereum encoding standards. + * + * @param value - The value to be encoded. + * @returns A Buffer containing the encoded value. + */ +encode(value: Buffer | string): Buffer { if (typeof value === 'string') { value = hexToBuffer(value); } @@ -554,7 +775,16 @@ class CoderFixedBytes extends Coder { return value; } - decode(data: Buffer, offset: number): DecodedResult { + /** + * Decode the given data buffer starting from the specified offset using the implemented coder. + * Returns an object containing the decoded value and the number of bytes consumed during decoding. + * Throws an error if the input data is insufficient or invalid for the implemented coder type. + * + * @param data - The data buffer to be decoded. + * @param offset - The starting index for decoding in the data buffer. + * @returns DecodedResult object containing the decoded value and the consumed bytes count. + */ +decode(data: Buffer, offset: number): DecodedResult { if (data.length < offset + 32) { errors.throwError('insufficient data for ' + name + ' type', errors.INVALID_ARGUMENT, { arg: this.localName, @@ -571,12 +801,29 @@ class CoderFixedBytes extends Coder { } } +/** + * The CoderAddress class extends the Coder base class, providing specific encoding and decoding + * functionality for Ethereum addresses. It ensures that address values are properly formatted + * and converted between different representations such as strings, BigNumber, and hexadecimal. + * This class facilitates ABI encoding and decoding of contract function parameters and event logs + * that involve Ethereum addresses. + */ class CoderAddress extends Coder { constructor(localName: string) { super('address', 'address', localName, false); } - encode(value: EthAddress | string): Buffer { + /** + * Encode the provided value according to the Coder type rules. + * This function converts any given value into a Buffer format based on the specific + * encoding rules defined for each Coder type, such as address, boolean, number, etc. + * Throws an error if the input value is not compatible with the Coder type or if + * any internal encoding operation fails. + * + * @param value - The value to be encoded according to the Coder rules. + * @returns A Buffer instance containing the encoded value. + */ +encode(value: EthAddress | string): Buffer { if (typeof value === 'string') { value = EthAddress.fromString(value); } @@ -591,7 +838,17 @@ class CoderAddress extends Coder { } } - decode(data: Buffer, offset: number): DecodedResult { + /** + * Decode the data buffer at the given offset according to the coder's type. + * This function extracts and interprets the relevant data from the buffer based on the coder specification, + * consuming a specific number of bytes in the process. It returns an object containing the decoded value + * and the number of bytes consumed during decoding. + * + * @param data - The data buffer to decode. + * @param offset - The starting offset within the data buffer to begin decoding. + * @returns An object containing the decoded value and the number of bytes consumed during decoding. + */ +decode(data: Buffer, offset: number): DecodedResult { if (data.length < offset + 32) { errors.throwError('insufficuent data for address type', errors.INVALID_ARGUMENT, { arg: this.localName, @@ -606,6 +863,14 @@ class CoderAddress extends Coder { } } +/** + * Encodes the given dynamic bytes value into a buffer with its length as a prefix. + * The function first encodes the length of the byte array as a uint256 and then concatenates + * the actual byte array followed by padding to align it to 32-byte boundary. + * + * @param value - The buffer or hex string representing the dynamic bytes value to be encoded. + * @returns A buffer containing the encoded dynamic bytes value, including length prefix and proper padding. + */ function _encodeDynamicBytes(value: Buffer): Buffer { const dataLength = 32 * Math.ceil(value.length / 32); const padding = new Buffer(dataLength - value.length); @@ -613,6 +878,16 @@ function _encodeDynamicBytes(value: Buffer): Buffer { return Buffer.concat([uint256Coder.encode(value.length), value, padding]); } +/** + * Decodes dynamic bytes from a given data buffer at the specified offset. + * Handles errors such as insufficient data, and returns an object containing + * the consumed size (number of bytes used) and the resulting value (the decoded bytes). + * + * @param data - The data buffer to decode from. + * @param offset - The starting position in the data buffer to begin decoding. + * @param localName - The name of the argument being processed, used for error reporting. + * @returns An object containing the number of bytes consumed and the decoded bytes as a Buffer. + */ function _decodeDynamicBytes(data: Buffer, offset: number, localName: string): DecodedResult { if (data.length < offset + 32) { errors.throwError('insufficient data for dynamicBytes length', errors.INVALID_ARGUMENT, { @@ -646,12 +921,27 @@ function _decodeDynamicBytes(data: Buffer, offset: number, localName: string): D }; } +/** + * The CoderDynamicBytes class is a coder for encoding and decoding dynamic bytes data types in ABI. + * It handles the variable-length byte arrays, allowing efficient serialization and deserialization of + * such data while interacting with the Ethereum blockchain through smart contracts. The class extends the + * base Coder class and overrides its methods to provide specific implementation for dynamic bytes. + */ class CoderDynamicBytes extends Coder { constructor(localName: string) { super('bytes', 'bytes', localName, true); } - encode(value: Buffer | string): Buffer { + /** + * Encodes the input values according to the specified ABI types, returning a hex-encoded string of the packed data. + * This function takes an array of types and an array of corresponding values as input, and generates a representation + * that can be used in Ethereum smart contracts for function calls or events. + * + * @param types - An array of strings or ParamType objects describing the types of the input values. + * @param values - An array of input values matching the types specified in the "types" parameter. + * @returns A hex-encoded string representing the packed data according to the ABI types. + */ +encode(value: Buffer | string): Buffer { try { if (typeof value === 'string') { value = hexToBuffer(value); @@ -666,19 +956,46 @@ class CoderDynamicBytes extends Coder { } } - decode(data: Buffer, offset: number): DecodedResult { + /** + * Decodes the given data according to the specified parameter types. + * The types array represents the data types of the expected decoding results, + * where each type is either a string or a ParamType object. + * The data argument should be a buffer containing the encoded data. + * Returns an array of decoded values, with each value corresponding to the provided types. + * + * @param types - An array of strings or ParamType objects representing the data types to decode. + * @param data - A Buffer containing the encoded data to be decoded. + * @returns An array of decoded values corresponding to the specified types. + */ +decode(data: Buffer, offset: number): DecodedResult { const result = _decodeDynamicBytes(data, offset, this.localName); result.value = bufferToHex(result.value); return result; } } +/** + * The CoderString class is responsible for encoding and decoding string values in the ABI format. + * It inherits from the Coder class and overrides the encode and decode methods to specifically handle + * string data types. This class enables efficient and accurate serialization and deserialization + * of string values within the context of Ethereum contract function calls and events. + */ class CoderString extends Coder { constructor(localName: string) { super('string', 'string', localName, true); } - encode(value: string): Buffer { + /** + * Encodes the given types and values into a single ABI-formatted hex string. + * The types array should contain a list of type strings or ParamType objects that describe each value's type. + * The values array should have the same length as the types array and contain the data to be encoded. + * Throws an error if the types/values length mismatch or if any invalid argument is encountered during encoding. + * + * @param types - An array of type strings or ParamType objects describing each value's type. + * @param values - An array of values corresponding to the types provided. + * @returns A hex-encoded ABI-formatted string representing the encoded values. + */ +encode(value: string): Buffer { if (typeof value !== 'string') { errors.throwError('invalid string value', errors.INVALID_ARGUMENT, { arg: this.localName, @@ -689,17 +1006,46 @@ class CoderString extends Coder { return _encodeDynamicBytes(Buffer.from(new TextEncoder().encode(value))); } - decode(data: Buffer, offset: number): DecodedResult { + /** + * Decodes the ABI-encoded data based on the specified input types. + * Takes an array of input types (strings or ParamType objects) and a buffer containing + * the ABI-encoded data. Returns an array or an object containing the decoded values, depending + * on whether the local names are available in the input types. If any error occurs during decoding, + * it throws an exception with a detailed message about the issue. + * + * @param types - An array of input types, either as strings or ParamType objects. + * @param data - A Buffer containing the ABI-encoded data to decode. + * @returns An array or an object containing the decoded values based on the input types. + */ +decode(data: Buffer, offset: number): DecodedResult { const result = _decodeDynamicBytes(data, offset, this.localName); result.value = new TextDecoder('utf-8').decode(result.value); return result; } } +/** + * Calculate the aligned size of a value, rounding up to the nearest multiple of 32. + * This function is commonly used when dealing with tightly packed data structures in + * ABI encoding and decoding where data needs to be aligned to 32-byte boundaries. + * + * @param size - The original size of a value in bytes. + * @returns The aligned size, rounded up to the nearest multiple of 32 bytes. + */ function alignSize(size: number): number { return 32 * Math.ceil(size / 32); } +/** + * Packs an array of values according to their respective coders into a single Buffer. + * The 'coders' and 'values' arrays must have the same length. Each value in the 'values' array + * will be encoded using its corresponding coder in the 'coders' array, then combined into + * a single Buffer with proper padding and dynamic content offsets. + * + * @param coders - An array of Coder instances used to encode each value. + * @param values - An array of values to be packed together into a single Buffer. + * @returns A Buffer containing the packed values according to their coders. + */ function pack(coders: Array, values: Array): Buffer { if (Array.isArray(values)) { // do nothing @@ -723,7 +1069,19 @@ function pack(coders: Array, values: Array): Buffer { }); } - const parts: Array<{ dynamic: boolean; value: any }> = []; + const parts: Array<{ /** + * Indicates if the coder has a dynamic size. + */ +/** + * Indicates if the coder has a dynamic size. + */ +dynamic: boolean; /** + * The encoded or decoded value based on the ABI data type. + */ +/** + * The encoded or decoded value based on the ABI data type. + */ +value: any }> = []; coders.forEach(function (coder, index) { parts.push({ dynamic: coder.dynamic, value: coder.encode(values[index]) }); @@ -760,6 +1118,17 @@ function pack(coders: Array, values: Array): Buffer { return data; } +/** + * Unpack the values from the provided coders and data buffer at the specified offset. + * The function iterates through each coder, decodes its corresponding value in the data buffer, + * and appends it to an array of decoded values. If the coder has a localName, the decoded value + * is also assigned to the resulting object using the localName as the key. + * + * @param coders - Array of Coder instances to decode the data buffer. + * @param data - Buffer containing the encoded data to be unpacked. + * @param offset - The starting position of the data buffer to begin decoding from. + * @returns An object with two properties: 'value', which is an array of decoded values, and 'consumed', which is the number of bytes consumed during decoding. + */ function unpack(coders: Array, data: Buffer, offset: number): DecodedResult { const baseOffset = offset; let consumed = 0; @@ -806,6 +1175,13 @@ function unpack(coders: Array, data: Buffer, offset: number): DecodedResu }; } +/** + * The CoderArray class extends the Coder class for encoding and decoding array data types in Ethereum ABI. + * It handles fixed-size arrays (e.g., uint256[5]) and dynamic-size arrays (e.g., address[]), providing + * methods to encode and decode values according to the specified element type and length. By leveraging + * the base Coder implementation and an additional coder for nested elements, CoderArray ensures proper + * handling of both simple and complex arrays within contract function signatures and event topics. + */ class CoderArray extends Coder { readonly coder: Coder; readonly length: number; @@ -818,7 +1194,19 @@ class CoderArray extends Coder { this.length = length; } - encode(value: Array): Buffer { + /** + * Encode the given input types and values into a hexadecimal string according to the ABI specification. + * The function takes an array of types and values, and encodes them into a single data string, + * which can be used for contract function calls or event encoding. The types array should contain + * strings representing Ethereum Solidity types (e.g. 'uint256', 'address', 'bytes32'), + * and the values array should contain corresponding JavaScript values to be encoded. + * Throws an error if the types and values length mismatch or if there's an issue during encoding. + * + * @param types - An array of strings or ParamType objects representing the Ethereum Solidity types. + * @param values - An array of JavaScript values corresponding to the input types. + * @returns A hex-encoded string of the encoded input types and values. + */ +encode(value: Array): Buffer { if (!Array.isArray(value)) { errors.throwError('expected array value', errors.INVALID_ARGUMENT, { arg: this.localName, @@ -845,7 +1233,16 @@ class CoderArray extends Coder { return Buffer.concat([result, pack(coders, value)]); } - decode(data: Buffer, offset: number) { + /** + * Decodes the ABI (Application Binary Interface) encoded data based on the specified types. + * The function takes an array of type descriptors and a buffer containing the ABI encoded data, + * and returns an object with decoded values. + * + * @param {Array} types - An array of type descriptors, either as strings or ParamType objects. + * @param {Buffer} data - A Buffer containing the ABI encoded data to be decoded. + * @returns {any} An object with the decoded values based on the provided types. + */ +decode(data: Buffer, offset: number) { // @TODO: //if (data.length < offset + length * 32) { throw new Error('invalid array'); } @@ -887,6 +1284,12 @@ class CoderArray extends Coder { } } +/** + * The CoderTuple class is responsible for encoding and decoding tuple data types in the ABI encoding format. + * It extends the Coder class and takes an array of coders representing each component. + * When encoding, it processes the components using the appropriate coder instances and returns the encoded data. + * When decoding, it parses the encoded data and constructs the tuple by applying each coder's decode method to their respective components. + */ class CoderTuple extends Coder { constructor(private coders: Array, localName: string) { let dynamic = false; @@ -903,11 +1306,32 @@ class CoderTuple extends Coder { this.coders = coders; } - encode(value: Array): Buffer { + /** + * Encodes the given function signature with the corresponding parameter types and values. + * This function takes an array of parameter types, such as strings or ParamType objects, + * and an array of corresponding parameter values to generate the ABI-encoded data. + * The generated encoded data is useful for interacting with smart contracts. + * Throws an error if the length of the input types and values mismatch. + * + * @param types - An array of parameter types represented as strings or ParamType objects. + * @param values - An array of corresponding values to be encoded with the parameter types. + * @returns A hex-encoded string representing the ABI-encoded data. + */ +encode(value: Array): Buffer { return pack(this.coders, value); } - decode(data: Buffer, offset: number): DecodedResult { + /** + * Decodes the provided data using the specified input types and returns an array of decoded values. + * The input 'types' is an array of either strings or ParamType objects representing the expected data types. + * The input 'data' should be a Buffer containing the encoded data to decode. + * Throws an error if the number of input types does not match the number of values in the data or if decoding fails. + * + * @param types - Array of strings or ParamType objects representing the expected data types. + * @param data - Buffer containing the encoded data to decode. + * @returns An array of decoded values. + */ +decode(data: Buffer, offset: number): DecodedResult { const result = unpack(this.coders, data, offset); return result; } @@ -950,6 +1374,15 @@ const paramTypeSimple: { [key: string]: any } = { bytes: CoderDynamicBytes, }; +/** + * Creates a CoderTuple instance from an array of components with their corresponding local names. + * The 'components' should be an array of ParamType objects, each containing the type and name of each component. + * Throws an error if the input components are invalid or any ParamType is not supported. + * + * @param components - An array of ParamType objects representing the components of the tuple. + * @param localName - The string representing the local name of the tuple. + * @returns A CoderTuple instance for encoding and decoding the tuple values. + */ function getTupleParamCoder(components: Array, localName: string): CoderTuple { if (!components) { components = []; @@ -962,6 +1395,16 @@ function getTupleParamCoder(components: Array, localName: string): CoderTup return new CoderTuple(coders, localName); } +/** + * Returns an instance of the appropriate Coder class based on the given ParamType. + * This function is responsible for selecting the correct coder to handle encoding and + * decoding of various data types specified in the ABI. It supports basic types like 'address', + * 'bool', 'string', and 'bytes', as well as more complex types like fixed-size arrays, dynamic arrays, + * and tuples with nested components. + * + * @param param - The ParamType object containing the type and name of the parameter. + * @returns An instance of a Coder subclass corresponding to the given ParamType. + */ function getParamCoder(param: ParamType): Coder { const coder = paramTypeSimple[param.type]; if (coder) { @@ -1015,10 +1458,26 @@ function getParamCoder(param: ParamType): Coder { }); } +/** + * The AbiCoder class provides an interface for encoding and decoding contract function calls and events + * using Ethereum's Application Binary Interface (ABI). It supports the conversion of Solidity data types + * to JavaScript and vice versa. This class enables encoding of function arguments for contract method calls, + * as well as decoding of event logs and return values from transactions and contract calls. + */ export class AbiCoder { constructor() {} - encode(types: Array, values: Array): string { + /** + * Encodes the given types and values into a hex-encoded ABI string. + * Takes an array of types (strings or ParamType objects) and an array of corresponding values. + * Each type in the 'types' array should have a corresponding value in the 'values' array. + * Throws an error if the length of types and values arrays do not match, or if there are any issues during encoding. + * + * @param types - An array of strings or ParamType objects representing the data types. + * @param values - An array of values corresponding to the types. + * @returns A hex-encoded string representing the encoded ABI data. + */ +encode(types: Array, values: Array): string { if (types.length !== values.length) { errors.throwError('types/values length mismatch', errors.INVALID_ARGUMENT, { count: { types: types.length, values: values.length }, @@ -1045,7 +1504,19 @@ export class AbiCoder { return bufferToHex(new CoderTuple(coders, '_').encode(values)); } - decode(types: Array, data: Buffer): any { + ``` +/** + * Decodes the ABI-encoded data using the provided array of types and returns the corresponding values. + * Each type can be a string or a ParamType object, which includes type information and an optional name. + * The input 'data' should be a valid ABI-encoded Buffer. + * Throws an error if the types and data do not match, or if any decoding issues occur. + * + * @param types - An array of strings or ParamType objects representing the expected types of the decoded data. + * @param data - A Buffer containing the ABI-encoded data to be decoded. + * @returns An array or an object containing the decoded values, with optional keys if names are provided in the types. + */ +``` +decode(types: Array, data: Buffer): any { const coders = types.map(type => { if (typeof type === 'string') { type = parseParam(type); diff --git a/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/errors.ts b/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/errors.ts index 3c4bdef4e07..d96f1fb55d3 100644 --- a/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/errors.ts +++ b/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/errors.ts @@ -18,6 +18,16 @@ export const UNEXPECTED_ARGUMENT = 'UNEXPECTED_ARGUMENT'; const _censorErrors = false; +/** + * Throws a detailed error with a custom message, code, and additional information. + * The error message can be censored by setting the '_censorErrors' variable to true. + * In that case, a generic 'unknown error' message will be thrown instead of the custom message. + * + * @param message - The custom error message to display. + * @param code - The specific error code for this error (default is UNKNOWN_ERROR). + * @param params - An object containing additional information related to the error (e.g. argument name, value, etc.). + * @returns never - This function always throws an error and does not return any value. + */ export function throwError(message: string, code: string = UNKNOWN_ERROR, params: any = {}): never { if (_censorErrors) { throw new Error('unknown error'); @@ -50,6 +60,16 @@ export function throwError(message: string, code: string = UNKNOWN_ERROR, params throw error; } +/** + * Validates the number of arguments provided against the expected count and throws an error if they do not match. + * This function is useful for checking the right number of arguments are passed to a function, especially in cases + * where optional arguments are involved. It appends a custom message suffix when provided. + * + * @param count - The actual number of arguments received by the function. + * @param expectedCount - The expected number of arguments for the function. + * @param suffix - Optional string to be appended to the error message when thrown. + * @throws {Error} If either too few or too many arguments are provided. + */ export function checkArgumentCount(count: number, expectedCount: number, suffix?: string): void { if (!suffix) { suffix = ''; diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_abi.ts b/yarn-project/ethereum.js/src/contract/abi/contract_abi.ts index 75a1855d3d7..37526ba0ff1 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_abi.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_abi.ts @@ -2,12 +2,33 @@ import { LogResponse } from '../../eth_rpc/types/log_response.js'; import { bufferToHex } from '../../hex_string/index.js'; import { ContractAbiDefinition, ContractErrorEntry, ContractEventEntry, ContractFunctionEntry } from './index.js'; +/** + * The ContractAbi class represents the ABI (Application Binary Interface) of a smart contract. + * It provides methods for decoding logs, events, and function data according to the contract's ABI definition. + * With a ContractAbi instance, you can match, decode and process logs and events generated by the smart contract, + * as well as decode input data provided when calling one of its functions. + */ export class ContractAbi { - public functions: ContractFunctionEntry[]; - public events: ContractEventEntry[]; - public errors: ContractErrorEntry[]; - public ctor: ContractFunctionEntry; - public fallback?: ContractFunctionEntry; + /** + * A list of contract functions. + */ +public functions: ContractFunctionEntry[]; + /** + * An array containing contract event entries. + */ +public events: ContractEventEntry[]; + /** + * A collection of error entries in the contract ABI. + */ +public errors: ContractErrorEntry[]; + /** + * The constructor entry for the contract. + */ +public ctor: ContractFunctionEntry; + /** + * The fallback function to be executed when no other function matches the provided signature. + */ +public fallback?: ContractFunctionEntry; constructor(definition: ContractAbiDefinition) { this.functions = definition.filter(e => e.type === 'function').map(entry => new ContractFunctionEntry(entry)); @@ -21,11 +42,27 @@ export class ContractAbi { } } - public findEntryForLog(log: LogResponse) { + /** + * Find the matching event entry for a given log response in the contract ABI. + * This function iterates through the events defined in the ABI and compares their signatures with the log's topic. + * Returns the first matching event entry, or undefined if no match is found. + * + * @param log - The LogResponse object containing the log data to be matched against event signatures. + * @returns A ContractEventEntry instance that matches the log's topic, or undefined if no match is found. + */ +public findEntryForLog(log: LogResponse) { return this.events.find(abiDef => abiDef.signature === log.topics[0]); } - public decodeEvent(log: LogResponse) { + /** + * Decodes the event log data using the Contract ABI event definitions. + * Finds the matching event signature in the ABI, then decodes the log data accordingly. + * Throws an error if no matching event signature is found for the given log. + * + * @param log - The LogResponse object containing the event log data to be decoded. + * @returns A decoded event object with event name and decoded parameters. + */ +public decodeEvent(log: LogResponse) { const event = this.findEntryForLog(log); if (!event) { throw new Error(`Unable to find matching event signature for log: ${log.id}`); @@ -33,7 +70,15 @@ export class ContractAbi { return event.decodeEvent(log); } - public decodeFunctionData(data: Buffer) { + /** + * Decodes the function data from a given buffer and returns the decoded parameters. + * The input 'data' should contain the first 4 bytes as the function signature, followed by the encoded parameters. + * Returns undefined if no matching function is found in the ABI for the provided signature. + * + * @param data - The buffer containing the function signature and encoded parameters. + * @returns An object with the decoded parameters or undefined if no matching function is found. + */ +public decodeFunctionData(data: Buffer) { const funcSig = bufferToHex(data.subarray(0, 4)); const func = this.functions.find(f => f.signature === funcSig); return func ? func.decodeParameters(data.slice(4)) : undefined; diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_abi_definition.ts b/yarn-project/ethereum.js/src/contract/abi/contract_abi_definition.ts index fb9eea55030..e9beed6f792 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_abi_definition.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_abi_definition.ts @@ -1,31 +1,109 @@ +/** + * Represents the supported data types in Ethereum ABI (Application Binary Interface) for encoding and decoding contract interactions. + */ export type AbiDataTypes = 'bool' | 'string' | 'address' | 'function' | 'uint' | 'int' | 'bytes' | string; +/** + * Type representing an individual input parameter in the ABI (Application Binary Interface) of a smart contract. + * It includes properties for the input's name, data type, and other relevant information used in encoding/decoding + * contract function calls and events. + */ export type AbiInput = { - components?: any; - name: string; - type: AbiDataTypes; - indexed?: boolean; - internalType?: string; + /** + * Represents the structure of nested tuple elements. + */ +components?: any; + /** + * The name identifier for the contract entry. + */ +name: string; + /** + * Represents the type of a Contract Entry in the ABI (Application Binary Interface) definition. + */ +type: AbiDataTypes; + /** + * Indicates if the parameter is indexed in events. + */ +indexed?: boolean; + /** + * The internal representation of the data type. + */ +internalType?: string; }; +/** + * Represents the type definition for a single output parameter in a contract's ABI. + */ export type AbiOutput = { - components?: any; - name: string; - type: AbiDataTypes; - internalType?: string; + /** + * Nested structure defining the data type components. + */ +components?: any; + /** + * The name identifier of the contract entry. + */ +name: string; + /** + * The type of contract entry, such as function, constructor, event, fallback, error, or receive. + */ +type: AbiDataTypes; + /** + * Represents the internal Solidity type of the input/output. + */ +internalType?: string; }; +/** + * Represents a single entry in a smart contract's ABI definition. + * Provides essential information about the contract's functions, events, constructors, and other elements, + * allowing effective interaction with the Ethereum blockchain. + */ export interface ContractEntryDefinition { - constant?: boolean; - payable?: boolean; - anonymous?: boolean; - inputs?: AbiInput[]; - name?: string; - outputs?: AbiOutput[]; - type: 'function' | 'constructor' | 'event' | 'fallback' | 'error' | 'receive'; - stateMutability?: 'pure' | 'view' | 'payable' | 'nonpayable'; - signature?: string; - gas?: number; + /** + * Indicates if the contract entry is constant (read-only). + */ +constant?: boolean; + /** + * Indicates whether the contract entry can receive Ether. + */ +payable?: boolean; + /** + * Indicates if the event is anonymous, omitting event signature from logs. + */ +anonymous?: boolean; + /** + * An array of input parameters for the contract function or event. + */ +inputs?: AbiInput[]; + /** + * The identifier for the contract function, event, or variable. + */ +name?: string; + /** + * An array of output parameters for the contract function or event. + */ +outputs?: AbiOutput[]; + /** + * The type of contract entry, representing its purpose and functionality. + */ +type: 'function' | 'constructor' | 'event' | 'fallback' | 'error' | 'receive'; + /** + * Represents the mutability of a contract's state during function execution. + */ +stateMutability?: 'pure' | 'view' | 'payable' | 'nonpayable'; + /** + * The unique function identifier generated from the function's name and input types. + */ +signature?: string; + /** + * The estimated gas cost for executing the function. + */ +gas?: number; } +/** + * Type representing the Application Binary Interface (ABI) definition for a smart contract, + * which consists of an array of ContractEntryDefinition objects. The ABI defines the + * structure of functions, events, and data types of a contract that can be interacted with. + */ export type ContractAbiDefinition = ContractEntryDefinition[]; diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts b/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts index 59eb87f5a9b..b22b3ee0ff0 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts @@ -1,6 +1,12 @@ import { abiCoder } from './abi-coder/index.js'; import { ContractEntryDefinition } from './contract_abi_definition.js'; +/** + * The ContractEntry class represents a single entry within an Ethereum smart contract's ABI definition. + * It provides easy access to the name of the function or event, as well as its anonymous status. + * Additionally, it offers a method to convert the entry into a human-readable string format. + * This class is primarily used for parsing and interacting with contract ABI definitions. + */ export class ContractEntry { constructor(protected entry: ContractEntryDefinition) {} @@ -12,7 +18,14 @@ export class ContractEntry { return this.entry.anonymous || false; } - public asString() { + /** + * Returns a string representation of the ContractEntry instance using ABI encoding. + * This method utilizes the 'abiCoder' module to convert the contract entry definition + * into a readable and formatted string. + * + * @returns A string representation of the ContractEntry instance with ABI encoding. + */ +public asString() { return abiCoder.abiMethodToString(this.entry); } } diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_error_entry.ts b/yarn-project/ethereum.js/src/contract/abi/contract_error_entry.ts index 367d978e4e1..3559443c3b2 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_error_entry.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_error_entry.ts @@ -3,8 +3,16 @@ import { abiCoder } from './abi-coder/index.js'; import { ContractEntryDefinition } from './contract_abi_definition.js'; import { ContractEntry } from './contract_entry.js'; +/** + * The ContractErrorEntry class extends the functionalities of the ContractEntry class for error handling in smart contracts. + * It handles encoding, decoding and managing error entries in a contract's ABI (Application Binary Interface). + * This class provides methods to encode and decode parameters, return values, and ABI for contract errors, ensuring proper communication with the blockchain. + */ export class ContractErrorEntry extends ContractEntry { - public readonly signature: Buffer; + /** + * The encoded function signature for the contract entry. + */ +public readonly signature: Buffer; constructor(entry: ContractEntryDefinition) { entry.inputs = entry.inputs || []; @@ -12,11 +20,28 @@ export class ContractErrorEntry extends ContractEntry { this.signature = hexToBuffer(abiCoder.encodeFunctionSignature(abiCoder.abiMethodToString(entry))); } - public numArgs() { + /** + * Retrieve the number of input arguments for this contract error entry. + * This function returns the length of the 'inputs' array, which represents + * the input arguments required by the entry. If no inputs are defined, + * it returns 0. + * + * @returns The number of input arguments for the contract error entry. + */ +public numArgs() { return this.entry.inputs ? this.entry.inputs.length : 0; } - public decodeReturnValue(returnValue: Buffer) { + /** + * Decodes the return value of a contract function call using the ABI output definition. + * If there is only one output, returns the decoded output value directly; otherwise, + * returns an object containing the decoded values with the output names as keys. + * If the input returnValue buffer is empty, returns null. + * + * @param returnValue - The Buffer containing the encoded return value of the contract function call. + * @returns Decoded output value(s) or null if returnValue is empty. + */ +public decodeReturnValue(returnValue: Buffer) { if (!returnValue.length) { return null; } @@ -31,15 +56,40 @@ export class ContractErrorEntry extends ContractEntry { } } - public encodeABI(args: any[]) { + /** + * Encodes the ABI (Application Binary Interface) of a function call by concatenating the function's signature + * and encoded input parameters. This resulting buffer can be used for encoding the data field of a transaction. + * The 'args' array should contain values that match the expected input types of the function. + * + * @param args - An array of arguments matching the function's input parameters. + * @returns A Buffer containing the encoded ABI for the function call. + */ +public encodeABI(args: any[]) { return Buffer.concat([this.signature, this.encodeParameters(args)]); } - public encodeParameters(args: any[]) { + /** + * Encode the input parameters according to the contract entry inputs. + * This function takes an array of arguments and encodes them into a Buffer + * following the Solidity contract's entry ABI specifications. + * + * @param args - An array of input values matching the contract entry inputs. + * @returns A Buffer containing the encoded parameters. + */ +public encodeParameters(args: any[]) { return abiCoder.encodeParameters(this.entry.inputs, args); } - public decodeParameters(bytes: Buffer) { + /** + * Decode the provided bytes buffer into parameters based on the entry inputs. + * This function helps in interpreting the raw bytes buffer received from a contract call + * or an event log, by decoding it based on the ABI input types, and returning the + * decoded values as an object with the input names as keys. + * + * @param bytes - The Buffer containing the encoded parameters to be decoded. + * @returns An object with decoded parameters, keys mapped to the input names defined in the ABI. + */ +public decodeParameters(bytes: Buffer) { return abiCoder.decodeParameters(this.entry.inputs, bytes); } } diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_event_entry.ts b/yarn-project/ethereum.js/src/contract/abi/contract_event_entry.ts index c33c0ae7e6c..c30fbecf21e 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_event_entry.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_event_entry.ts @@ -5,15 +5,35 @@ import { abiCoder } from './abi-coder/index.js'; import { ContractEntryDefinition } from './contract_abi_definition.js'; import { ContractEntry } from './contract_entry.js'; +/** + * The ContractEventEntry class represents a single event entry within a smart contract. + * It provides functionality to encode and decode event topics and logs, as well as + * handling filter parameters for indexed inputs of the event. This class extends the + * ContractEntry base class, adding specific features for event handling in Ethereum + * contracts. By utilizing this class, users can seamlessly interact with events emitted + * by a smart contract, making it easier to track and process data related to those events. + */ export class ContractEventEntry extends ContractEntry { - public readonly signature: string; + /** + * The unique event identifier derived from ABI. + */ +public readonly signature: string; constructor(entry: ContractEntryDefinition) { super(entry); this.signature = abiCoder.encodeEventSignature(abiCoder.abiMethodToString(entry)); } - public getEventTopics(filter: object = {}) { + /** + * Generate an array of event topics by encoding the filter values provided for indexed inputs. + * For events which are not anonymous, the first topic will be the event's signature. + * Each subsequent topic corresponds to an indexed input, with null values for missing filters. + * Supports array values for indexed inputs, which will generate multiple topics for that input. + * + * @param filter - An object containing the filter values to encode as event topics. + * @returns An array of encoded event topics (Buffer or Buffer[]), including the event signature if not anonymous. + */ +public getEventTopics(filter: object = {}) { const topics: (Buffer | Buffer[])[] = []; if (!this.entry.anonymous && this.signature) { @@ -41,7 +61,15 @@ export class ContractEventEntry extends ContractEntry { return [...topics, ...indexedTopics]; } - public decodeEvent(log: LogResponse): EventLog { + /** + * Decodes an event log response from a contract execution. + * The input 'log' is an object containing data and topics received from the Ethereum transaction receipt. + * This method returns an EventLog object containing the decoded event along with its metadata. + * + * @param log - The LogResponse object containing data and topics from the contract execution. + * @returns An EventLog object with the decoded event, signature, arguments, and raw data. + */ +public decodeEvent(log: LogResponse): EventLog { const { data = '', topics = [], ...formattedLog } = log; const { anonymous, inputs = [], name = '' } = this.entry; diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts b/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts index 0b23842ae4c..6515e60729b 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts @@ -3,8 +3,16 @@ import { abiCoder } from './abi-coder/index.js'; import { ContractEntryDefinition } from './contract_abi_definition.js'; import { ContractEntry } from './contract_entry.js'; +/** + * The ContractFunctionEntry class represents a function entry within a smart contract ABI definition. + * It provides methods for encoding and decoding parameters, as well as determining the function's constant and payable properties. + * This class extends the ContractEntry base class and adds functionality specific to smart contract functions such as constructors and regular methods. + */ export class ContractFunctionEntry extends ContractEntry { - public readonly signature: string; + /** + * The unique identifier of the contract function. + */ +public readonly signature: string; constructor(entry: ContractEntryDefinition) { entry.inputs = entry.inputs || []; @@ -23,11 +31,28 @@ export class ContractFunctionEntry extends ContractEntry { return this.entry.stateMutability === 'payable' || this.entry.payable; } - public numArgs() { + /** + * Returns the number of input arguments required for the contract function. + * This value is derived from the 'inputs' property of the contract entry definition. + * + * @returns The number of input arguments required for the function. + */ +public numArgs() { return this.entry.inputs ? this.entry.inputs.length : 0; } - public decodeReturnValue(returnValue: Buffer) { + /** + * Decodes the return value of a contract function call. + * This method takes a Buffer containing the raw return value from a contract function call + * and decodes it according to the output parameters defined in the ABI. + * If the decoded result contains only one value, it returns that value directly; + * otherwise, an object with named properties is returned, excluding the '__length__' property. + * + * @param returnValue - The raw return value from a contract function call as a Buffer. + * @returns The decoded value(s) according to the output parameters defined in the ABI, + * either as a single value or an object with named properties. + */ +public decodeReturnValue(returnValue: Buffer) { if (!returnValue.length) { return null; } @@ -42,15 +67,38 @@ export class ContractFunctionEntry extends ContractEntry { } } - public encodeABI(args: any[]) { + /** + * Encodes the function call and its arguments into ABI format (Application Binary Interface). + * This representation is used for interacting with the Ethereum blockchain. + * The encoded result is a Buffer that can be sent as data in a transaction or used to invoke contract functions. + * + * @param args - An array of values representing the arguments to pass in the function call. + * @returns A Buffer containing the encoded function signature and parameters in ABI format. + */ +public encodeABI(args: any[]) { return Buffer.concat([hexToBuffer(this.signature), this.encodeParameters(args)]); } - public encodeParameters(args: any[]) { + /** + * Encode the provided arguments based on the contract function's input parameters. + * This is useful when preparing ABI-encoded data to interact with a smart contract function. + * Throws an error if the provided arguments don't match the expected input parameters. + * + * @param args - An array of values representing the arguments for the contract function. + * @returns A Buffer containing the ABI-encoded parameters. + */ +public encodeParameters(args: any[]) { return abiCoder.encodeParameters(this.entry.inputs, args); } - public decodeParameters(bytes: Buffer) { + /** + * Decode the parameters from a given buffer using the input types defined in the contract entry. + * This function is useful for unpacking parameters from encoded data or transaction payloads. + * + * @param bytes - The buffer containing the encoded parameters. + * @returns An object with the decoded parameters mapped to their respective names as defined in the contract entry. + */ +public decodeParameters(bytes: Buffer) { return abiCoder.decodeParameters(this.entry.inputs, bytes); } } diff --git a/yarn-project/ethereum.js/src/contract/bytes.ts b/yarn-project/ethereum.js/src/contract/bytes.ts index b26bcee1bf3..ebce21459e6 100644 --- a/yarn-project/ethereum.js/src/contract/bytes.ts +++ b/yarn-project/ethereum.js/src/contract/bytes.ts @@ -1,33 +1,236 @@ +/** + * The Bytes class extends the built-in Buffer class in Node.js, providing a convenient and efficient way + * to work with binary data. It is designed for use in various scenarios such as reading/writing files, + * network communication, and cryptographic operations. Each Bytes subclass (Bytes1 to Bytes32) represents + * a specific fixed-length byte array, allowing for optimized memory management and type safety. + */ export class Bytes extends Buffer {} +/** + * Bytes1 is a class extending the Buffer, representing a binary data container with a fixed size of 1 byte. + * It provides utility methods to easily manipulate, read, and write single-byte data in a memory-efficient manner. + * Instances of Bytes1 can be used in various applications where precise control over single-byte data is required, + * such as low-level networking, binary file handling or encoding/decoding tasks. + */ export class Bytes1 extends Buffer {} +/** + * Represents a Bytes2 class that extends the Buffer class, specifically designed to handle fixed-length byte arrays + * of size 2. This class can be used for various operations related to manipulating and processing binary data. + * Use this class when you need a compact and efficient way of storing and working with 2-byte sequences. + */ export class Bytes2 extends Buffer {} +/** + * The Bytes3 class extends the Buffer class, representing a fixed-length binary data container of size 3 bytes. + * This class enables efficient manipulation and storage of 3-byte sequences, commonly used in various data encoding + * and communication protocols. It provides all the functionalities of the Buffer class with a predefined size constraint. + */ export class Bytes3 extends Buffer {} +/** + * The Bytes4 class extends the Buffer class to represent a 4-byte (32-bit) sequence of data. + * It is designed to facilitate manipulation and handling of fixed-sized byte arrays, + * commonly used in various data encoding, hashing, and serialization processes. + */ export class Bytes4 extends Buffer {} +/** + * Represents a Bytes5 class that extends the functionality of the Buffer class. + * This class can be used to store and manipulate 5-byte binary data, providing + * a convenient way to work with fixed-length byte arrays in various applications. + * The class inherits all methods and properties from the Buffer class, allowing for + * easy manipulation, comparison, and encoding/decoding of the binary data. + */ export class Bytes5 extends Buffer {} +/** + * Bytes6 class represents a fixed-length binary data buffer with a length of 6 bytes, extending the functionality + * of the native Buffer class. This can be used for handling data structures that require precise byte lengths. + * The class provides efficient memory allocation and operations for working with 6-byte sequences. + */ export class Bytes6 extends Buffer {} +/** + * The Bytes7 class represents a specialized Buffer with a fixed length of 7 bytes. + * This class can be used to handle binary data of specifically 7 bytes length, providing + * an efficient and convenient way to manipulate and manage such data structures. + */ export class Bytes7 extends Buffer {} +/** + * The Bytes8 class is a specialized extension of the Buffer class designed to specifically handle + * byte arrays of length 8. It inherits all the properties and methods of the Buffer class, allowing + * for efficient management, manipulation, and encoding/decoding of 8-byte data sequences. + * This class can be particularly helpful when working with fixed-length binary data structures, + * such as 64-bit integers, IPv6 addresses or other 8-byte long data representations. + */ export class Bytes8 extends Buffer {} +/** + * Bytes9 represents a fixed-size byte array of length 9, extending the Buffer class. + * It can be used to store and manipulate binary data efficiently in various scenarios, + * such as encoding/decoding, file handling, and networking. The class guarantees that + * the number of bytes will always be exactly 9, ensuring consistency and preventing + * accidental resizing or overflow issues. + */ export class Bytes9 extends Buffer {} +/** + * The Bytes10 class is a specialized extension of the Buffer class, specifically designed to handle + * fixed-length byte arrays of size 10. This class provides all the functionality and methods of the + * Buffer class but ensures that the data being managed is always exactly 10 bytes in length. + * It can be useful for scenarios where precise control over byte array sizes is required, + * such as cryptography, hashing, or working with fixed-size data structures. + */ export class Bytes10 extends Buffer {} +/** + * The Bytes11 class is an extension of the Buffer class, specifically designed to handle + * fixed binary data with a size of 11 bytes. It provides all the functionality of the Buffer + * class, while enforcing the constraint that the length of the binary data should be exactly 11 bytes. + * This can be useful in scenarios where precise byte-length data is required, such as working with + * certain cryptographic algorithms or data serialization formats. + */ export class Bytes11 extends Buffer {} +/** + * Represents a Bytes12 class that extends the Buffer class, specifically designed to handle and manipulate + * 12-byte data sequences. This class provides an efficient way of dealing with binary data of fixed length, + * being especially useful in scenarios like cryptographic hashes, keys, and unique identifiers. + */ export class Bytes12 extends Buffer {} +/** + * Represents a Bytes13 class that extends the Buffer class to handle 13-byte binary data. + * This class provides a convenient way to work with fixed-length byte arrays, specifically for + * use cases that require exactly 13 bytes of data. It inherits all methods and properties from + * the Buffer class, allowing easy manipulation and handling of binary data. + */ export class Bytes13 extends Buffer {} +/** + * Represents a Bytes14 class that extends the Buffer class, specifically designed + * to handle and manipulate fixed-length 14-byte binary data efficiently. + * Offers built-in functionality via the Buffer class to read and write various + * data types, encode/decode strings, and perform optimized operations on the + * underlying bytes. This class can be used in various applications where + * fixed-sized 14-byte data structures are required, such as cryptographic keys, + * unique identifiers, and other encoding/decoding scenarios. + */ export class Bytes14 extends Buffer {} +/** + * The Bytes15 class extends the Buffer class and represents a binary data container with a fixed length of 15 bytes. + * This specific byte array size is useful for handling data structures that require exactly 15-byte long entries, ensuring consistent storage and processing. + * Inherits all methods and properties from the Buffer class, providing additional functionality for manipulation and conversion of binary data. + */ export class Bytes15 extends Buffer {} +/** + * Bytes16 represents a fixed-length byte buffer of 16 bytes, extending the native Buffer class. + * This class can be used to store and manipulate binary data efficiently, while maintaining + * the consistency of the fixed-length requirement. Common use cases include handling cryptographic + * hashes, UUIDs, and other fixed-size data structures. + */ export class Bytes16 extends Buffer {} +/** + * The Bytes17 class extends the Buffer class and represents a fixed-size binary data container of 17 bytes. + * This class can be used to store and manipulate raw byte sequences efficiently in various applications, + * such as encryption algorithms, file handling, or data transmission processes that require specific byte lengths. + */ export class Bytes17 extends Buffer {} +/** + * Bytes18 represents a fixed-sized, 18-byte buffer class that extends the native Node.js Buffer class. + * It is useful in scenarios where precise byte-length data structures are required, + * such as when working with binary protocols or cryptographic algorithms that need + * specific sized inputs. The Bytes18 class ensures proper management and manipulation + * of 18-byte data chunks, providing consistent and efficient handling throughout your application. + */ export class Bytes18 extends Buffer {} +/** + * Represents a Bytes19 class, which is a custom extension of the Buffer class. + * This class is specifically designed to handle an array of 19 bytes in length, + * providing additional functionality and constraints related to the management + * of byte arrays with a fixed size of 19. + * + * It can be used for situations where precisely 19 bytes are required, such as + * data storage, cryptographic operations, or communication protocols that have + * specific size requirements. + */ export class Bytes19 extends Buffer {} +/** + * The Bytes20 class represents a fixed-length byte array (Buffer) with a length of 20 bytes. + * It is designed to be used for data structures and operations requiring fixed-size byte arrays, + * such as storing Ethereum addresses, which are exactly 20 bytes long. + * Extending the native Buffer class, this class provides all its functionalities while enforcing the specific byte length. + */ export class Bytes20 extends Buffer {} +/** + * Represents the Bytes21 class, which is an extension of the Buffer class, specifically designed to handle byte arrays of fixed length 21. + * This class can be used for efficiently storing and manipulating data that requires exactly 21 bytes, such as certain cryptographic keys or hashes. + */ export class Bytes21 extends Buffer {} +/** + * Represents the Bytes22 class, which provides a specialized extension of the Buffer class. + * This class is designed for handling byte arrays of length 22 efficiently and conveniently. + * It offers all the functionality provided by the Buffer class while ensuring the fixed size constraint for better optimization. + */ export class Bytes22 extends Buffer {} +/** + * The Bytes23 class represents a specialized buffer designed specifically for handling + * 23-byte binary data sequences. It extends the native Node.js Buffer API to provide + * functionality tailored to efficiently store, manipulate, and process fixed-size + * data elements of 23 bytes in length. This class can be particularly useful in applications + * where working with precise byte lengths is vital, such as cryptographic operations, + * network protocols or file systems. + */ export class Bytes23 extends Buffer {} +/** + * Represents the Bytes24 class, a fixed-length binary data buffer that extends from Buffer. + * This class provides a 24-byte container for handling binary data in various scenarios, + * such as working with encryption, encoding, compression, or other data manipulation tasks. + * Using fixed-length byte arrays can be useful for efficient memory management and predictable performance. + */ export class Bytes24 extends Buffer {} +/** + * The Bytes25 class extends the Buffer class, representing a fixed-length binary data container + * with a size of 25 bytes. It is ideal for storing and manipulating unique data structures that require + * a constant byte size, such as specific cryptographic hashes or addresses. + * The class inherits all methods and properties from the Buffer class to provide an efficient way + * to work with raw binary data while ensuring a maximum length constraint. + */ export class Bytes25 extends Buffer {} +/** + * The Bytes26 class extends the Buffer class and represents a fixed-size binary data container with a length of 26 bytes. + * This class can be used for efficient storage, manipulation, and serialization of 26-byte long byte arrays in various applications, + * such as working with cryptographic keys, unique identifiers, or other data structures that require a fixed-length binary representation. + */ export class Bytes26 extends Buffer {} +/** + * The Bytes27 class represents a fixed-size 27-byte Buffer, which can be used for handling binary data of specific length. + * It extends the Node.js Buffer class and provides an efficient way to manage raw bytes within a fixed-sized container. + * Common use cases include cryptographic operations, encoding/decoding tasks, and working with structured binary data formats. + */ export class Bytes27 extends Buffer {} +/** + * The Bytes28 class represents a fixed-length binary data buffer of 28 bytes, + * extending the built-in Buffer class. It provides efficient and safe manipulation + * of binary data, while ensuring that the size remains constant throughout the lifetime + * of the instance. This can be particularly useful in scenarios where there's a need to + * represent and handle fixed-length byte arrays, such as encoding/decoding operations, + * cryptographic hashing, or data serialization. + */ export class Bytes28 extends Buffer {} +/** + * Represents a specialized Bytes class with a fixed buffer size of 29 bytes, extending the native Buffer object. + * This Bytes29 class can be used for handling binary data that requires precisely 29 bytes in length, + * ensuring consistent memory allocation and simplifying data manipulation across different use cases. + */ export class Bytes29 extends Buffer {} +/** + * The Bytes30 class extends the Buffer class and represents a fixed-size byte array of length 30. + * It is particularly useful for storing, manipulating, and transmitting various forms of data + * while maintaining a consistent size. This can aid in ensuring compatibility and efficient storage + * within applications that require fixed-length byte arrays, such as cryptographic algorithms, + * encoding schemes, or communication protocols. + */ export class Bytes30 extends Buffer {} +/** + * Bytes31 represents a fixed length 31-byte Buffer class that can be used for managing and manipulating binary data. + * This class extends the built-in Node.js Buffer, providing all its functionalities while ensuring a constant byte size + * of 31 throughout the application. This can be especially useful in scenarios where fixed-length data structures are required, + * such as cryptography, hashing algorithms, or serialization protocols. + */ export class Bytes31 extends Buffer {} +/** + * The Bytes32 class extends the Buffer class in Node.js and represents a fixed-size byte array of 32 bytes. + * This can be particularly useful for handling data structures that require a fixed-length input, such as cryptographic + * hash functions, digital signatures or keys. By using a dedicated class like Bytes32, it ensures proper handling, + * validation, and manipulation of these crucial data elements within various applications. + */ export class Bytes32 extends Buffer {} diff --git a/yarn-project/ethereum.js/src/contract/constructor_interaction.ts b/yarn-project/ethereum.js/src/contract/constructor_interaction.ts index 67810bed801..a34873399aa 100644 --- a/yarn-project/ethereum.js/src/contract/constructor_interaction.ts +++ b/yarn-project/ethereum.js/src/contract/constructor_interaction.ts @@ -20,7 +20,15 @@ export class ConstructorInteraction extends FunctionInteraction { super(eth, contractEntry, contractAbi, undefined, args, defaultOptions); } - public send(options: SendOptions): SentTx { + /** + * Sends a transaction with the encoded contract bytecode and constructor arguments, creating a new deployment of the contract. + * Returns a SentDeployContractTx instance that can be used to track the transaction status and retrieve the deployed contract address. + * The 'options' parameter can be used to customize the transaction, such as specifying gas price, gas limit, or value to send. + * + * @param options - An object containing optional parameters for customizing the transaction. + * @returns A SentDeployContractTx instance representing the sent transaction. + */ +public send(options: SendOptions): SentTx { const sentTx = super.send(options); return new SentDeployContractTx(this.eth, this.contractAbi, sentTx.getTxHash(), this.onDeployed); } diff --git a/yarn-project/ethereum.js/src/contract/contract.test.ts b/yarn-project/ethereum.js/src/contract/contract.test.ts index c8c4a93f352..17de0047956 100644 --- a/yarn-project/ethereum.js/src/contract/contract.test.ts +++ b/yarn-project/ethereum.js/src/contract/contract.test.ts @@ -561,7 +561,13 @@ describe('contract', () => { describe('send', () => { const signature = sha3('mySend(address,uint256)').slice(0, 10); - function bootstrap() { + /** + * Sets up the initial state for the mock Ethereum provider by resolving the required RPC calls. + * This function helps prepare the test environment before executing test cases related to contract methods. + * The bootstrap function configures the responses for eth_sendTransaction, eth_blockNumber, + * and eth_getTransactionReceipt in the mock Ethereum provider. + */ +function bootstrap() { // eth_sendTransaction mockEthereumProvider.request.mockResolvedValueOnce( '0x1234000000000000000000000000000000000000000000000000000000056789', diff --git a/yarn-project/ethereum.js/src/contract/contract.ts b/yarn-project/ethereum.js/src/contract/contract.ts index 3e1e9a31bda..94f8d5b2b19 100644 --- a/yarn-project/ethereum.js/src/contract/contract.ts +++ b/yarn-project/ethereum.js/src/contract/contract.ts @@ -5,32 +5,81 @@ import { EventLog } from './contract_tx_receipt.js'; import { FunctionInteraction } from './function_interaction.js'; import { ConstructorInteraction } from './constructor_interaction.js'; +/** + * Represents configuration options for interacting with an Ethereum contract. + * Provides optional settings for specifying the sender address, gas price, and gas limit when creating contract transactions. + */ export interface ContractOptions { - from?: EthAddress; - gasPrice?: string | number; - gas?: number; + /** + * The Ethereum address initiating the contract interaction. + */ +from?: EthAddress; + /** + * Gas price for executing contract transactions. + */ +gasPrice?: string | number; + /** + * The maximum amount of gas units allowed for the contract execution. + */ +gas?: number; } +/** + * Represents a contract definition for interacting with Ethereum smart contracts. + * Provides a structure to define methods, events, and event logs associated with a specific contract. + * Enables type safety when calling contract methods, accessing event logs, and return values. + */ interface ContractDefinition { - methods: any; - events?: any; - eventLogs?: any; + /** + * Collection of named functions to interact with the contract methods. + */ +methods: any; + /** + * Collection of contract event definitions for ease of interaction. + */ +events?: any; + /** + * A collection of event logs for the contract. + */ +eventLogs?: any; } +/** + * TxFactory is a type representing a factory function that produces FunctionInteraction instances. + * It takes any number of arguments and returns a FunctionInteraction instance for interacting with + * the smart contract methods based on the provided arguments. + */ type TxFactory = (...args: any[]) => FunctionInteraction; +/** + * Type representing the names of the events present in a given contract definition. + * Used for accessing event logs and interacting with specific events on the contract. + */ type Events = T extends ContractDefinition ? Extract : string; +/** + * Type representing the event log for a specific event in a contract definition. + * Extracts the event log type based on the given contract definition and event name. + */ type GetEventLog> = T extends ContractDefinition ? T['eventLogs'][P] : EventLog; +/** + * GetEvent type represents a contract event type from the given ContractDefinition. + * Used to extract appropriate event information for a specific event within the contract. + */ type GetEvent> = T extends ContractDefinition ? T['events'][P] : any; +/** + * Type representing the contract methods available for interaction. + * It extracts the 'methods' property from the given ContractDefinition type parameter, + * providing a mapping of method names to their respective FunctionInteraction instances. + */ type GetContractMethods = T extends ContractDefinition ? T['methods'] : { [key: string]: (...args: any[]) => FunctionInteraction }; @@ -48,14 +97,20 @@ type GetContractMethods = T extends ContractDefinition * Default options can be provided, these can be used to save having on to specify e.g. `from` and `gas` on every call. */ export class Contract { - public readonly methods: GetContractMethods; + /** + * Collection of named functions for interacting with the contract methods. + */ +public readonly methods: GetContractMethods; // public readonly events: GetContractEvents; private linkTable: { [name: string]: EthAddress } = {}; constructor( private eth: EthereumRpc, private contractAbi: ContractAbi, - public address = EthAddress.ZERO, + /** + * Ethereum contract address for interaction. + */ +public address = EthAddress.ZERO, private defaultOptions: ContractOptions = {}, ) { this.methods = this.buildMethods(); @@ -98,18 +153,61 @@ export class Contract { ); } - public async getLogs>( + /** + * Retrieves event logs from the contract based on the specified event and options. + * If 'allevents' is passed as the event, it will return logs for all events in the contract. + * Otherwise, it returns logs for the specific event name or signature provided. + * The LogRequest options allow filtering, such as setting a block range or topics to search for logs. + * + * @param event - The event name, signature, or 'allevents' to retrieve logs for. + * @param options - Optional LogRequest object to filter the log results. + * @returns An array of EventLog objects for the specified event(s) and filtered based on the provided options. + */ +public async getLogs>( event: Event, options: LogRequest>, ): Promise[]>; - public async getLogs(event: 'allevents', options: LogRequest): Promise[]>; - public async getLogs(event: Events & 'allevents', options: LogRequest = {}): Promise[]> { + /** + * Retrieves event logs for the specified event or all events emitted by the contract. + * This function takes an event name and optional log request options as parameters, then + * fetches the matching event logs from the Ethereum blockchain. If the event name is 'allevents', + * it will retrieve logs for all events emitted by the contract. The resulting event logs are + * decoded according to the contract's ABI before being returned as an array. + * + * @param event - The name of the event or 'allevents' to retrieve logs for all events. + * @param options - Optional log request options such as filter, address, and topics. + * @returns An array of decoded event logs matching the specified event name and options. + */ +public async getLogs(event: 'allevents', options: LogRequest): Promise[]>; + /** + * Fetches event logs from the blockchain based on the given event and options. + * This function can either retrieve logs for a specific event or all events in a contract. + * It returns an array of decoded event logs based on the ContractDefinition type parameter. + * The `eventName` parameter should be the name or signature of the event, or 'allevents' to fetch + * logs for all events in a contract. The `options` parameter allows filtering logs by block range, + * address, and other criteria. + * + * @param eventName - The name, signature, or 'allevents' string representing the event(s) to fetch logs for. + * @param options - A LogRequest object with optional properties to filter event logs. + * @returns A Promise that resolves to an array of decoded event logs. + */ +public async getLogs(event: Events & 'allevents', options: LogRequest = {}): Promise[]> { const logOptions = this.getLogOptions(event, options); const result = await this.eth.getLogs(logOptions); return result.map(log => this.contractAbi.decodeEvent(log)); } - public getMethod(name: string, inputTypes: AbiDataTypes[], outputTypes: AbiDataTypes[]) { + /** + * Retrieves a contract method by name and input/output types as an executor factory. + * The method can be called with the specified arguments to create a FunctionInteraction instance. + * Throws an error if no contract address is available or if there is no matching method with the provided arguments length. + * + * @param name - The name of the contract method. + * @param inputTypes - An array of input data types for the method. + * @param outputTypes - An array of output data types for the method. + * @returns A TxFactory instance representing the contract method. + */ +public getMethod(name: string, inputTypes: AbiDataTypes[], outputTypes: AbiDataTypes[]) { const abiEntry: ContractEntryDefinition = { inputs: inputTypes.map((type, i) => ({ name: `a${i}`, type })), name, @@ -145,7 +243,15 @@ export class Contract { }; } - private buildMethods() { + /** + * Generates a collection of named functions on the public `methods` property based on the contract ABI. + * It groups and assigns contract functions to their respective method names. + * In case of function overloads, it will create an executor factory for all matching functions. + * + * @private + * @returns An object containing the generated methods mapped to their respective names. + */ +private buildMethods() { const methods: any = {}; this.contractAbi.functions.forEach(f => { @@ -166,7 +272,16 @@ export class Contract { return methods; } - private getLogOptions(eventName = 'allevents', options: LogRequest): LogRequest { + /** + * Generates a LogRequest object for the specified event and request options. + * This is used to filter and retrieve logs related to a contract event. + * Throws an error if no contract address is available or the specified event is not found in the ABI. + * + * @param eventName - The name or signature of the contract event. + * @param options - A LogRequest object containing filter and topic options for the log query. + * @returns A LogRequest object with the specified event and request options combined. + */ +private getLogOptions(eventName = 'allevents', options: LogRequest): LogRequest { if (!this.address) { throw new Error('No contract address.'); } diff --git a/yarn-project/ethereum.js/src/contract/contract_tx_receipt.ts b/yarn-project/ethereum.js/src/contract/contract_tx_receipt.ts index 7be73b8143e..34e80f4c0fd 100644 --- a/yarn-project/ethereum.js/src/contract/contract_tx_receipt.ts +++ b/yarn-project/ethereum.js/src/contract/contract_tx_receipt.ts @@ -2,23 +2,90 @@ import { EthAddress } from '@aztec/foundation'; import { LogResponse, TransactionReceipt, TxHash } from '../eth_rpc/index.js'; import { DecodedError } from './decode_error.js'; +/** + * Represents a parsed Ethereum event log specific to Aztec contracts. + * Contains information about the event, such as its name, address, arguments, block data, and signature. + * Useful for tracking contract interactions and state changes on the blockchain. + */ export interface EventLog { - id: string | null; - removed?: boolean; - event: Name; - address: EthAddress; - args: Args; - logIndex: number | null; - transactionIndex: number | null; - transactionHash: TxHash | null; - blockHash: string | null; - blockNumber: number | null; - raw: { data: string; topics: string[] }; - signature: string | null; + /** + * A unique identifier for the event log. + */ +id: string | null; + /** + * Indicates whether the event log has been removed due to a chain reorganization. + */ +removed?: boolean; + /** + * The name of the emitted event. + */ +event: Name; + /** + * The Ethereum address of the contract emitting the event. + */ +address: EthAddress; + /** + * Arguments associated with the emitted event. + */ +args: Args; + /** + * The index position of the log entry in the block. + */ +logIndex: number | null; + /** + * The index of the transaction within the block containing it. + */ +transactionIndex: number | null; + /** + * The unique identifier of the transaction. + */ +transactionHash: TxHash | null; + /** + * The hash of the block containing this event. + */ +blockHash: string | null; + /** + * The block number containing the event. + */ +blockNumber: number | null; + /** + * Raw event data and topics emitted by the contract. + */ +raw: { /** + * The raw hexadecimal representation of the event data. + */ +data: string; /** + * An array of indexed event arguments encoded as hexadecimal strings. + */ +topics: string[] }; + /** + * The unique identifier of the event signature. + */ +signature: string | null; } +/** + * Represents a contract transaction receipt in the Aztec network. + * Extends the standard transaction receipt with additional information about anonymous logs and + * decoded events specific to the contract. It also includes optional error details in case of a failed transaction. + */ export interface ContractTxReceipt extends TransactionReceipt { - anonymousLogs: LogResponse[]; - events: Events extends void ? { [eventName: string]: EventLog[] } : Events; - error?: { message: string; decodedError?: DecodedError }; + /** + * An array of logs without specific event signatures. + */ +anonymousLogs: LogResponse[]; + /** + * An object containing arrays of various event logs, keyed by their respective event names. + */ +events: Events extends void ? { [eventName: string]: EventLog[] } : Events; + /** + * An optional field containing error information, including a message and decodedError if available. + */ +error?: { /** + * The human-readable error message. + */ +message: string; /** + * Decoded information from a failing transaction error. + */ +decodedError?: DecodedError }; } diff --git a/yarn-project/ethereum.js/src/contract/decode_error.ts b/yarn-project/ethereum.js/src/contract/decode_error.ts index 9df0b260769..c12d28e747d 100644 --- a/yarn-project/ethereum.js/src/contract/decode_error.ts +++ b/yarn-project/ethereum.js/src/contract/decode_error.ts @@ -2,10 +2,26 @@ import { CallRequest, EthereumRpc, TxHash } from '../eth_rpc/index.js'; import { hexToBuffer } from '../hex_string/index.js'; import { ContractAbi } from './abi/contract_abi.js'; +/** + * Represents a decoded error from a contract execution. + * Contains optional name and params properties, as well as a mandatory message property + * providing a human-readable description of the error. + */ export interface DecodedError { - name?: string; - params?: any[]; - message: string; + /** + * The name of the decoded error. + */ +name?: string; + ``` +/** + * An array of decoded error parameters. + */ +``` +params?: any[]; + /** + * A human-readable description of the error. + */ +message: string; } /** diff --git a/yarn-project/ethereum.js/src/contract/fixtures/TestContract.ts b/yarn-project/ethereum.js/src/contract/fixtures/TestContract.ts index ab83b98c33a..9e0051d40f7 100644 --- a/yarn-project/ethereum.js/src/contract/fixtures/TestContract.ts +++ b/yarn-project/ethereum.js/src/contract/fixtures/TestContract.ts @@ -5,41 +5,123 @@ import { EthereumRpc } from "../../eth_rpc/index.js"; import { Contract, ContractTxReceipt, EventLog, Options, TxCall, TxSend } from "../../contract/index.js"; import * as Bytes from "../../contract/bytes.js"; import abi from "./TestContractAbi.js"; +/** + * Type representing the 'ChangedEvent' that contains details about the change in balance, + * such as the sender's address, the amount changed, and two timestamps for tracking. + */ export type ChangedEvent = { - from: EthAddress; - amount: bigint; - t1: bigint; - t2: bigint; + /** + * The Ethereum address initiating the event. + */ +from: EthAddress; + /** + * The amount involved in the transaction. + */ +amount: bigint; + /** + * Timestamp of the first event occurrence. + */ +t1: bigint; + /** + * Timestamp indicating the end time of an event. + */ +t2: bigint; }; +/** + * Type representing the 'UnchangedEvent', which is emitted when a specific condition in the contract remains unchanged. + */ export type UnchangedEvent = { - value: bigint; - addressFrom: EthAddress; - t1: bigint; + /** + * The monetary amount associated with the transaction. + */ +value: bigint; + /** + * The originating Ethereum address. + */ +addressFrom: EthAddress; + /** + * The timestamp of the first event. + */ +t1: bigint; }; +/** + * Represents the ChangedEventLog interface for the TestContract. + * Contains all the properties of a Changed event log, including event name and payload. + */ export interface ChangedEventLog extends EventLog { } +/** + * Represents the log interface for UnchangedEvent in the TestContract. + * Provides event details such as value, addressFrom, and t1 from the emitted Unchanged event. + */ export interface UnchangedEventLog extends EventLog { } +/** + * Represents the event types for the TestContract. + * Provides a mapped definition of each event with its respective data structure. + */ interface TestContractEvents { - Changed: ChangedEvent; - Unchanged: UnchangedEvent; + /** + * Event emitted when a change occurs in the contract state. + */ +Changed: ChangedEvent; + /** + * An event indicating no change in the value. + */ +Unchanged: UnchangedEvent; } +/** + * Represents the event logs for the TestContract interface. + * Contains the mapping of event names to their corresponding event log interfaces for easy access and organization. + */ interface TestContractEventLogs { - Changed: ChangedEventLog; - Unchanged: UnchangedEventLog; + /** + * Represents an event triggered when a change occurs in the contract state. + */ +Changed: ChangedEventLog; + /** + * Event triggered when a value remains unchanged. + */ +Unchanged: UnchangedEventLog; } +/** + * Represents the event logs for all transactions involving the TestContract. + * Contains an organized collection of event logs for each specific event in the contract, allowing easy access to relevant transaction information. + */ interface TestContractTxEventLogs { - Changed: ChangedEventLog[]; - Unchanged: UnchangedEventLog[]; + /** + * Triggered when a state change occurs in the contract. + */ +Changed: ChangedEventLog[]; + /** + * An event representing unaltered data. + */ +Unchanged: UnchangedEventLog[]; } +/** + * Represents a TestContract transaction receipt. + * Provides details about the transaction events, status, and other relevant information after executing a method call on the TestContract. + */ export interface TestContractTransactionReceipt extends ContractTxReceipt { } +/** + * Represents the methods available in the TestContract. + * Provides functionality for interacting with and invoking smart contract functions, + * handling various use cases such as adding structs, managing balances, performing transactions, + * and working with event logs. + */ interface TestContractMethods { addStruct(nestedStruct: { - status: boolean; + /** + * Represents the active state of a specific object or process. + */ +status: boolean; }): TxSend; listOfNestedStructs(a0: EthAddress): TxCall<{ - status: boolean; + /** + * Represents the active state of an entity. + */ +status: boolean; }>; balance(who: EthAddress): TxCall; hasALotOfParams(_var1: number, _var2: string, _var3: Bytes.Bytes32[]): TxSend; @@ -51,16 +133,47 @@ interface TestContractMethods { overloadedFunction(a: bigint): TxCall; overloadedFunction(): TxCall; } +/** + * Represents a TestContract definition interface. + * Contains methods, events, and eventLogs related to the TestContract. + * Provides functionality for interacting with the TestContract on the Ethereum network. + */ export interface TestContractDefinition { - methods: TestContractMethods; - events: TestContractEvents; - eventLogs: TestContractEventLogs; + /** + * Collection of smart contract methods. + */ +methods: TestContractMethods; + /** + * A collection of event definitions for the TestContract. + */ +events: TestContractEvents; + /** + * Collection of logs for emitted events. + */ +eventLogs: TestContractEventLogs; } +/** + * The TestContract class represents a smart contract deployed on the Ethereum blockchain. + * This class provides methods to interact with the contract, including invoking its functions, + * querying its state, and listening for events. It extends the Contract base class and implements + * the TestContractDefinition interface, which defines the structure of the contract's ABI. + * Instances of this class can be created with an optional address and options, allowing the user + * to easily connect to existing contracts or deploy new ones. + */ export class TestContract extends Contract { constructor(eth: EthereumRpc, address?: EthAddress, options?: Options) { super(eth, abi, address, options); } - deploy(who: EthAddress, myValue: bigint): TxSend { + /** + * Deploy a new instance of the TestContract smart contract to the Ethereum network. + * The 'deploy' function takes the initial 'who' address and 'myValue' as arguments for the constructor of the TestContract. + * Returns a transaction receipt containing the contract address, gas used, and other details on successful deployment. + * + * @param who - The Ethereum address that will be set as the 'owner' of the newly deployed contract. + * @param myValue - The initial value (in bigint) to be set in the smart contract's internal state. + * @returns A promise that resolves to a TestContractTransactionReceipt with information about the deployed contract. + */ +deploy(who: EthAddress, myValue: bigint): TxSend { return super.deployBytecode("0x01234567", who, myValue) as any; } } diff --git a/yarn-project/ethereum.js/src/contract/fixtures/TestNoCtorContract.ts b/yarn-project/ethereum.js/src/contract/fixtures/TestNoCtorContract.ts index 2128975bc3f..0248b90d44b 100644 --- a/yarn-project/ethereum.js/src/contract/fixtures/TestNoCtorContract.ts +++ b/yarn-project/ethereum.js/src/contract/fixtures/TestNoCtorContract.ts @@ -5,29 +5,78 @@ import { EthereumRpc } from "../../eth_rpc/index.js"; import { Contract, ContractTxReceipt, EventLog, Options, TxCall, TxSend } from "../../contract/index.js"; import * as Bytes from "../../contract/bytes.js"; import abi from "./TestNoCtorContractAbi.js"; +/** + * Represents the events emitted by the TestNoCtorContract. + * Provides an interface for accessing the event log data associated with the contract. + */ interface TestNoCtorContractEvents { } +/** + * Represents the event logs for the TestNoCtorContract. + * Provides an interface for accessing and managing the emitted events in the contract. + */ interface TestNoCtorContractEventLogs { } +/** + * Represents the transaction event logs for the TestNoCtorContract. + * Provides a structured interface for accessing event logs emitted during contract transactions. + */ interface TestNoCtorContractTxEventLogs { } +/** + * Represents the transaction receipt for a TestNoCtorContract operation. + * Contains detailed information about the transaction status and event logs specific to the TestNoCtorContract instance. + */ export interface TestNoCtorContractTransactionReceipt extends ContractTxReceipt { } +/** + * Represents the TestNoCtorContract methods interface. + * Provides a collection of methods for interacting with and executing transactions on the TestNoCtorContract smart contract. + */ interface TestNoCtorContractMethods { addStruct(nestedStruct: { - status: boolean; + /** + * Indicates the active state of an element. + */ +status: boolean; }): TxSend; } +/** + * Represents a TestNoCtorContract definition. + * Provides functionality for interacting with methods and events specific to the TestNoCtorContract smart contract. + */ export interface TestNoCtorContractDefinition { - methods: TestNoCtorContractMethods; - events: TestNoCtorContractEvents; - eventLogs: TestNoCtorContractEventLogs; + /** + * Collection of smart contract methods. + */ +methods: TestNoCtorContractMethods; + /** + * Collection of contract event definitions. + */ +events: TestNoCtorContractEvents; + /** + * Holds the event logs data for the contract. + */ +eventLogs: TestNoCtorContractEventLogs; } +/** + * The TestNoCtorContract class represents a smart contract on the Ethereum blockchain. + * It provides methods to interact with the contract both for reading data and sending transactions. + * The class also defines the structure of events emitted by the contract and facilitates listening to those events. + * This class is particularly useful when working with contracts that do not have a constructor function. + */ export class TestNoCtorContract extends Contract { constructor(eth: EthereumRpc, address?: EthAddress, options?: Options) { super(eth, abi, address, options); } - deploy(): TxSend { + /** + * Deploy the TestNoCtorContract smart contract to the Ethereum blockchain. + * Uses a fixed bytecode "0x01234567" as the deployment data. + * Returns a transaction object with the contract deployment details and receipt. + * + * @returns {TxSend} A transaction object for the deployment of TestNoCtorContract. + */ +deploy(): TxSend { return super.deployBytecode("0x01234567") as any; } } diff --git a/yarn-project/ethereum.js/src/contract/function_interaction.ts b/yarn-project/ethereum.js/src/contract/function_interaction.ts index a2d93d4ca6a..a7167f33a30 100644 --- a/yarn-project/ethereum.js/src/contract/function_interaction.ts +++ b/yarn-project/ethereum.js/src/contract/function_interaction.ts @@ -12,19 +12,50 @@ import { ContractAbi, ContractFunctionEntry } from './abi/index.js'; import { decodeErrorFromContract } from './decode_error.js'; import { SentContractTx } from './sent_contract_tx.js'; +/** + * Represents the optional parameters for interacting with a contract. + * Provides customization options like sender address, maximum gas fees, and gas limit. + */ export interface Options { - from?: EthAddress; - maxFeePerGas?: bigint; - maxPriorityFeePerGas?: bigint; - gas?: number; + /** + * The Ethereum address initiating the transaction. + */ +from?: EthAddress; + /** + * The maximum fee per gas unit for the transaction. + */ +maxFeePerGas?: bigint; + /** + * The maximum priority fee per gas unit for the transaction. + */ +maxPriorityFeePerGas?: bigint; + /** + * The maximum amount of gas units to be used for the transaction. + */ +gas?: number; } +/** + * Represents the call options for a contract function interaction. + * These options include the sender address (from), maximum fee per gas (maxFeePerGas), + * maximum priority fee per gas (maxPriorityFeePerGas), gas limit (gas), and value. + */ export interface CallOptions extends Options { - value?: bigint; + /** + * The amount of ether (in wei) to transfer during the transaction. + */ +value?: bigint; } +/** + * Represents the options for sending a transaction in the Ethereum network. + * Provides optional parameters to control the execution of a transaction, such as gas limits, value, and nonce. + */ export interface SendOptions extends CallOptions { - nonce?: number; + /** + * The nonce value representing the number of transactions sent from the sender's address. + */ +nonce?: number; } /** @@ -64,7 +95,16 @@ export class FunctionInteraction implements TxCall, TxSend { protected defaultOptions: Options = {}, ) {} - public async estimateGas(options: CallOptions = {}) { + /** + * Estimate the amount of gas required to perform a transaction for the function interaction. + * The gas estimation is based on the provided 'options' object, which can include parameters such as 'from', 'maxFeePerGas', 'maxPriorityFeePerGas', and 'gas'. + * If the transaction execution fails or there's an error in the call, it attempts to handle the error gracefully by providing a meaningful message. + * + * @param options - An optional object containing transaction parameters and overrides for the function interaction. + * @returns A Promise that resolves to the estimated gas amount required for the transaction. + * @throws Will throw an error if the call fails with a decoded error message, or a generic error message if decoding fails. + */ +public async estimateGas(options: CallOptions = {}) { try { return await this.eth.estimateGas(this.getCallRequest(options)); } catch (err: any) { @@ -72,7 +112,17 @@ export class FunctionInteraction implements TxCall, TxSend { } } - public async call(options: CallOptions = {}, block?: NumberOrTag) { + /** + * Executes a read-only contract function call, returning the decoded result. + * This interaction does not require a transaction on the blockchain and is thus gas-free. + * If the call encounters an error, it attempts to decode the error message from the contract + * and throws an error with a meaningful message. Otherwise, it throws the original error. + * + * @param options - Optional settings specifying "from", "value", "maxFeePerGas", "maxPriorityFeePerGas" and "gas". + * @param block - Optional specification of the block number or tag at which the call must be executed. + * @returns The return value of the contract function call after successful decoding. + */ +public async call(options: CallOptions = {}, block?: NumberOrTag) { try { const result = await this.eth.call(this.getCallRequest(options), block); return this.contractEntry.decodeReturnValue(result); @@ -81,7 +131,15 @@ export class FunctionInteraction implements TxCall, TxSend { } } - public send(options: SendOptions): SentTx { + /** + * Sends a transaction to the specified contract method with given options. + * It returns a SentTx instance containing the transaction receipt and decoded return value (if any). + * Throws an error if the from address is not specified or attempting to send value to a non-payable method. + * + * @param options - An object containing optional parameters: from, nonce, value, maxFeePerGas, maxPriorityFeePerGas, and gas. + * @returns A SentTx instance representing the sent transaction. + */ +public send(options: SendOptions): SentTx { const tx = this.getTxRequest(options); if (!this.contractEntry.payable && tx.value !== undefined && tx.value > 0) { @@ -93,11 +151,27 @@ export class FunctionInteraction implements TxCall, TxSend { return new SentContractTx(this.eth, this.contractAbi, promise); } - public encodeABI() { + /** + * Encodes the ABI (Application Binary Interface) for the function interaction with the provided arguments. + * The encoded ABI is a serialized representation of the function's signature and its arguments, which can be used + * by the Ethereum client to process the method call or transaction. This is useful for encoding contract function + * calls when interacting with the Ethereum blockchain. + * + * @returns A Buffer containing the encoded ABI for the function interaction. + */ +public encodeABI() { return this.contractEntry.encodeABI(this.args); } - private getTxRequest(options: SendOptions = {}): TransactionRequest { + /** + * Construct a transaction request object by merging the provided send options with the default options, `from` address, contract address, and encoded ABI data. + * This transaction request object is used for sending transactions to the Ethereum network. + * Throws an error if the `from` address is not specified. + * + * @param options - The send options containing information required for constructing the transaction request object. + * @returns A TransactionRequest instance with all necessary data for sending the transaction. + */ +private getTxRequest(options: SendOptions = {}): TransactionRequest { const from = options.from || this.defaultOptions.from; if (!from) { throw new Error('You must specify a from address to send a tx.'); @@ -111,7 +185,17 @@ export class FunctionInteraction implements TxCall, TxSend { }; } - private getCallRequest(options: CallOptions = {}): CallRequest { + /** + * Constructs and returns a CallRequest object for the current contract function interaction. + * The CallRequest object combines the provided options with the default options and includes + * the encoded ABI data of the function call. This object can be used to perform various + * interactions such as estimating gas, making calls, or sending transactions. + * + * @param options - An optional CallOptions object containing values such as from address, + * maxFeePerGas, maxPriorityFeePerGas, gas, and value. + * @returns A CallRequest object with the necessary information for further interactions. + */ +private getCallRequest(options: CallOptions = {}): CallRequest { return { ...this.defaultOptions, ...options, @@ -120,7 +204,15 @@ export class FunctionInteraction implements TxCall, TxSend { }; } - private handleError(err: any): never { + /** + * Handles errors occurring during the execution of a contract function call. + * If the error data contains a decodable error message, throws an error with a decoded message. + * Otherwise, throws the original error with its message. + * + * @param err - The error object caught during the contract function call execution. + * @throws {Error} An error with either the decoded error message or the original error message. + */ +private handleError(err: any): never { if (err.data && err.data.length > 2) { const decoded = decodeErrorFromContract(this.contractAbi, hexToBuffer(err.data)); if (decoded) { diff --git a/yarn-project/ethereum.js/src/contract/gen_def/index.ts b/yarn-project/ethereum.js/src/contract/gen_def/index.ts index 5cd5a5f5c49..dee077f761f 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/index.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/index.ts @@ -17,6 +17,14 @@ const printer = ts.createPrinter({ const getImport = (importPath: string, module: string) => importPath[0] === '.' ? `${importPath}/${module}/index.js` : `${importPath}/${module}`; +/** + * Generate an array of import declarations for the necessary modules and types used in the generated contract file. + * This function handles relative or absolute import paths, and appends the appropriate module names. + * + * @param name - The name of the contract. + * @param importPath - The base path for importing necessary modules. + * @returns An array of TypeScript import declarations. + */ function makeImports(name: string, importPath: string) { return [ ts.factory.createImportDeclaration( @@ -71,6 +79,15 @@ function makeImports(name: string, importPath: string) { ]; } +/** + * Generate a TypeScript type alias for an Ethereum contract event. + * The resulting type alias represents the structure of the event arguments as an object, + * with each property having the appropriate TypeScript type based on the Solidity type + * of the corresponding event input. + * + * @param definition - The ContractEntryDefinition representing the Ethereum contract event. + * @returns A TypeScript TypeAliasDeclaration representing the event structure. + */ function makeEventType(definition: ContractEntryDefinition) { const props = ts.factory.createTypeLiteralNode( definition.inputs!.map(input => @@ -86,10 +103,26 @@ function makeEventType(definition: ContractEntryDefinition) { ); } +/** + * Generate TypeScript type aliases for the event types specified in the given Contract ABI definition. + * Each event type alias is created by mapping the corresponding inputs of the event to their appropriate + * TypeScript types based on their Solidity data types. + * + * @param abi - The ContractAbiDefinition containing the events for which type aliases will be generated. + * @returns An array of TypeScript type alias declarations for the event types. + */ function makeEventTypes(abi: ContractAbiDefinition) { return abi.filter(def => def.type === 'event').map(makeEventType); } +/** + * Create an interface for event logs of a given ContractEntryDefinition. + * The generated interface extends 'EventLog' with the name and structure of the specific event log in the given definition. + * This helps in creating type-safe event logs for Ethereum smart contracts using the ABI. + * + * @param definition - The ContractEntryDefinition representing an event from the ABI. + * @returns A TypeScript interface declaration for the event log based on the given definition. + */ function makeEventLogInterface(definition: ContractEntryDefinition) { const eventName = `${definition.name!}Event`; return ts.factory.createInterfaceDeclaration( @@ -108,10 +141,26 @@ function makeEventLogInterface(definition: ContractEntryDefinition) { ); } +/** + * Generate TypeScript interface declarations for event logs of a contract. + * For each event in the ABI, it creates an exported interface extending 'EventLog' with event-specific properties. + * + * @param abi - The ContractAbiDefinition object representing the contract's ABI. + * @returns An array of TypeScript InterfaceDeclaration nodes representing the event log interfaces. + */ function makeEventLogInterfaces(abi: ContractAbiDefinition) { return abi.filter(def => def.type === 'event').map(makeEventLogInterface); } +/** + * Generate TypeScript interface for events in a given contract ABI. + * The interface contains typed definitions of each event present in the ABI, + * allowing them to be accessed and used effectively when working with the contract. + * + * @param name - The name of the contract. + * @param abi - The ContractAbiDefinition array from the contract's ABI JSON. + * @returns A TypeScript InterfaceDeclaration representing the events in the contract. + */ function makeEventsInterface(name: string, abi: ContractAbiDefinition) { const events = abi.filter(def => def.type === 'event').map(event => event.name!); return ts.factory.createInterfaceDeclaration( @@ -133,6 +182,16 @@ function makeEventsInterface(name: string, abi: ContractAbiDefinition) { ); } +/** + * Generates an interface for Event Logs of the given name and Contract ABI definition. + * The generated interface consists of property signatures with each property representing + * an event log type for a specific event in the contract. It provides a way to access event logs + * based on the event names. + * + * @param name - The name of the contract. + * @param abi - The Contract ABI definition object containing event definitions. + * @returns A TypeScript InterfaceDeclaration for the contract's event logs. + */ function makeEventLogsInterface(name: string, abi: ContractAbiDefinition) { const events = abi.filter(def => def.type === 'event').map(event => event.name!); return ts.factory.createInterfaceDeclaration( @@ -151,6 +210,16 @@ function makeEventLogsInterface(name: string, abi: ContractAbiDefinition) { ); } +/** + * Generates a TypeScript interface for the given contract's transaction event logs. + * The generated interface includes properties for each event in the ABI, with their respective + * log types as array values. This allows easier interaction and validation with contract events + * during transaction execution. + * + * @param name - The name of the contract. + * @param abi - The Contract ABI definition. + * @returns A TypeScript InterfaceDeclaration for the contract's transaction event logs. + */ function makeTxEventLogsInterface(name: string, abi: ContractAbiDefinition) { const events = abi.filter(def => def.type === 'event').map(event => event.name!); return ts.factory.createInterfaceDeclaration( @@ -169,6 +238,13 @@ function makeTxEventLogsInterface(name: string, abi: ContractAbiDefinition) { ); } +/** + * Generate a TypeScript interface for the transaction receipt of the given contract name. + * The generated interface extends the 'ContractTxReceipt' type with the contract's specific event log types. + * + * @param name - The name of the contract. + * @returns A TypeScript interface node representing the contract's transaction receipt. + */ function makeTransactionReceiptInterface(name: string) { return ts.factory.createInterfaceDeclaration( [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], @@ -185,6 +261,14 @@ function makeTransactionReceiptInterface(name: string) { ); } +/** + * Get the TypeScript base type from a given Solidity type string. + * Handles cases for unsigned and signed integer types, fixed types, byte arrays, + * boolean, and Ethereum address types. For other types, it defaults to string. + * + * @param type - The Solidity type string to be converted. + * @returns A TypeScript TypeNode representing the corresponding TypeScript type. + */ function getBaseType(type: string /*, returnValue: boolean*/) { let m: RegExpMatchArray | null; if ((m = type.match(/u?int(\d*)/) || type.match(/u?fixed([0-9x]*)/))) { @@ -217,6 +301,14 @@ function getBaseType(type: string /*, returnValue: boolean*/) { return ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword); } +/** + * Generate a TypeScript TypeLiteralNode representing a tuple type from an array of ABI inputs. + * The resulting tuple type will have the corresponding TypeScript types based on the Solidity types + * in the input components. + * + * @param components - An array of AbiInput objects that make up the tuple type. + * @returns A TypeLiteralNode representing the generated tuple type in TypeScript. + */ function getTupleType(components: AbiInput[]): ts.TypeLiteralNode { return ts.factory.createTypeLiteralNode( components!.map(prop => @@ -225,6 +317,15 @@ function getTupleType(components: AbiInput[]): ts.TypeLiteralNode { ); } +/** + * Generates the TypeScript type corresponding to a given Solidity type. + * Handles base types, tuples and arrays, including nested arrays. + * For tuple types, generates a TypeLiteralNode with the components as properties. + * + * @param input - The AbiInput object containing information about the Solidity type. + * @param type - An optional string representing the Solidity type (defaults to input.type). + * @returns A TypeScript TypeNode representing the corresponding TypeScript type. + */ function getTsTypeFromSolidityType(input: AbiInput, type?: string) { type = type || input.type; const arrayMatched = type.match(/(.+)\[\d*\]$/); @@ -237,6 +338,16 @@ function getTsTypeFromSolidityType(input: AbiInput, type?: string) { } } +/** + * Create a TypeScript parameter declaration from an ABI input. + * This function is used to generate TypeScript method signatures for smart contract methods based on their inputs. + * It takes an AbiInput object, which contains information about the name and type of the input, + * and its index in the inputs array, to generate a matching TypeScript parameter with the appropriate type. + * + * @param input - The AbiInput object containing the name and type of the input parameter. + * @param index - The index of the input parameter in the inputs array. + * @returns A TypeScript ParameterDeclaration for the given input. + */ function makeParameter(input: AbiInput, index: number) { return ts.factory.createParameterDeclaration( undefined, @@ -247,6 +358,14 @@ function makeParameter(input: AbiInput, index: number) { ); } +/** + * Generate TypeScript return type nodes for a given array of ABI outputs. + * Handles multiple return values by creating an object with properties corresponding to the output names and indices. + * Supports base types, tuple types, and array types based on the provided ABI outputs. + * + * @param outputs - Array of ABI outputs from a contract function. + * @returns An array of TypeScript TypeNodes representing the return types. + */ function generateReturnTypes(outputs: AbiOutput[]): ReadonlyArray { if (outputs.length === 0) { return []; @@ -282,6 +401,15 @@ function generateReturnTypes(outputs: AbiOutput[]): ReadonlyArray { } } +/** + * Determine the TypeScript type representing the output of a given contract function based on its definition. + * The output type is either 'TxCall' for view or pure functions, or 'TxSend' for functions that mutate state. + * For multiple return values, the output type will be an object containing each of them. + * + * @param name - The name of the smart contract. + * @param definition - The ContractEntryDefinition object representing the contract function. + * @returns A TypeScript TypeNode representing the output type of the contract function. + */ function getOutputType(name: string, definition: ContractEntryDefinition) { if (!definition.stateMutability) { if (definition.constant && definition.constant === true) { @@ -309,6 +437,16 @@ function getOutputType(name: string, definition: ContractEntryDefinition) { } } +/** + * Generates a method signature for a contract function based on its ABI definition. + * This method takes the name of the contract and the entry definition from the ABI, + * creates TypeScript parameter declarations for the inputs of the function, and + * sets the appropriate return type based on the stateMutability and outputs of the function. + * + * @param name - The name of the contract. + * @param definition - The ABI entry definition for the contract function. + * @returns A TypeScript methodSignature with the proper input parameters and output type. + */ function makeMethodSignature(name: string, definition: ContractEntryDefinition) { return ts.factory.createMethodSignature( undefined, @@ -320,11 +458,30 @@ function makeMethodSignature(name: string, definition: ContractEntryDefinition) ); } +/** + * Generate a TypeScript interface for the contract methods based on the ABI definition. + * The generated interface includes method signatures with input parameters and return types + * according to the contract's ABI, which can be used for type checking and code generation. + * + * @param name - The name of the contract. + * @param abi - The ContractAbiDefinition object containing the contract's ABI information. + * @returns A TypeScript InterfaceDeclaration for the contract methods. + */ function makeMethodsInterface(name: string, abi: ContractAbiDefinition) { const methods = abi.filter(def => def.type === 'function').map(def => makeMethodSignature(name, def)); return ts.factory.createInterfaceDeclaration(undefined, `${name}Methods`, undefined, undefined, methods); } +/** + * Generate TypeScript code for a contract class which extends the Contract class. + * The generated contract class includes methods, events, and event logs from the ABI. + * If initData is provided, it also creates a deployment method. + * + * @param name - The name of the generated contract. + * @param initData - The initialization data (constructor bytecode) for deploying the contract. Optional. + * @param abi - The contract's ABI definition. + * @returns A TypeScript ClassDeclaration node for the contract class. + */ function makeContract(name: string, initData: string | undefined, abi: ContractAbiDefinition) { const members: ClassElement[] = []; @@ -420,6 +577,15 @@ function makeContract(name: string, initData: string | undefined, abi: ContractA ); } +/** + * Creates and returns a TypeScript interface declaration for the contract definition. + * The generated interface contains property signatures for 'methods', 'events', and 'eventLogs'. + * This interface serves as a type definition for the contract instance, providing type information + * for its methods, events, and event logs, making it easier to interact with the contract in a type-safe manner. + * + * @param name - The name of the contract. + * @returns A TypeScript InterfaceDeclaration representing the contract definition. + */ function makeDefinitionInterface(name: string) { const props = [ ts.factory.createPropertySignature( @@ -451,6 +617,13 @@ function makeDefinitionInterface(name: string) { ); } +/** + * Generate a TypeScript export statement for the given ABI name. + * The exported variable is named '${name}Abi' and its value is the 'abi' identifier. + * + * @param name - The name of the contract ABI to be exported. + * @returns A TypeScript export statement node. + */ function makeAbiExport(name: string) { return ts.factory.createVariableStatement( [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], @@ -458,6 +631,17 @@ function makeAbiExport(name: string) { ); } +/** + * Generate TypeScript source code as AST nodes for a Contract based on the provided ABI and initialization data. + * The generated code includes imports, event types, event log interfaces, events interface, transaction receipt interface, + * methods interface, definition interface, contract class, and ABI export. + * + * @param name - The name of the Contract. + * @param abi - The Contract ABI Definition. + * @param initData - The initialization data (bytecode) of the Contract. + * @param importPath - Path to '@aztec/ethereum.js' package used for generating import statements. + * @returns An array of TypeScript Nodes representing the generated source code. + */ function makeFile(name: string, abi: ContractAbiDefinition, initData: string | undefined, importPath: string) { const imports = makeImports(name, importPath); const eventTypes = makeEventTypes(abi); @@ -486,6 +670,17 @@ function makeFile(name: string, abi: ContractAbiDefinition, initData: string | u ]); } +/** + * Generate the ABI (Application Binary Interface) for a contract and write it to a file. + * The output file will be named as '{name}Abi.ts' in the specified 'outputPath'. + * The generated file contains an exported default instance of ContractAbi class created + * with the provided ABI definition. The import path for the required modules is also generated. + * + * @param outputPath - The path where the generated ABI file will be saved. + * @param name - The name of the contract for which the ABI file is being generated. + * @param abi - The ContractAbiDefinition object containing the ABI details of the contract. + * @param importPath - The import path for the required modules in the generated file. + */ function makeAndWriteAbi(outputPath: string, name: string, abi: ContractAbiDefinition, importPath: string) { const abiOutputFile = `${outputPath}/${name}Abi.ts`; const output = `import { ContractAbi } from '${getImport( @@ -495,6 +690,17 @@ function makeAndWriteAbi(outputPath: string, name: string, abi: ContractAbiDefin fs.writeFileSync(abiOutputFile, output); } +/** + * Generate and write TypeScript interface and ABI files for a contract, based on the ABI + * and other data from the build artifact. The generated files will be written to the specified + * outputPath with the provided name. + * + * @param outputPath - The path where the output files will be created. + * @param name - The name of the contract used as a prefix for the generated files. + * @param buildData - An object containing the ABI and initData of the contract. + * @param importPath - The import path for the '@aztec/ethereum.js' module. + * @returns A Promise that resolves when all files have been written. + */ export async function makeAndWriteFiles( outputPath: string, name: string, @@ -517,6 +723,14 @@ export async function makeAndWriteFiles( makeAndWriteAbi(outputPath, name, abi, importPath); } +/** + * Execute the main function to generate and write contract files. + * It reads the configuration from the provided JSON file or a default 'contracts.json'. + * The function will output generated contract files into the specified outputPath, + * and use the importPath for resolving imports in the generated code. + * + * @throws If an error occurs while reading the config file, creating directories, or generating output files. + */ async function main() { const configFile = process.argv[2] || 'contracts.json'; const config = JSON.parse(fs.readFileSync(configFile).toString()) as Config; diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/config.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/config.ts index 2cc8cdfb5bc..32dbce789e8 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/config.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/config.ts @@ -7,43 +7,135 @@ import { ContractAbiDefinition } from '../../abi/index.js'; +/** + * Represents a file-based source for contract ABI and initialization data. + * Provides a convenient way to specify the contract name, ABI file location, + * and optional initialization data file location when generating contract interfaces. + */ interface FileSource { - source: 'files'; - name: string; - abiFile: string; - initDataFile?: string; + /** + * The origin of contract configuration data. + */ +source: 'files'; + /** + * The unique identifier for the contract configuration. + */ +name: string; + /** + * Path to the contract's ABI file. + */ +abiFile: string; + /** + * Optional file containing initialization data for the contract. + */ +initDataFile?: string; } +/** + * Represents an Etherscan source configuration for a smart contract. + * Provides necessary information to fetch the ABI and contract details from the Etherscan API. + */ interface EtherscanSource { - source: 'etherscan'; - name: string; - net: string; - address: string; + /** + * The source from which the contract definition is obtained. + */ +source: 'etherscan'; + /** + * The unique identifier for the contract. + */ +name: string; + /** + * The Ethereum network identifier. + */ +net: string; + /** + * The Ethereum contract address. + */ +address: string; } +/** + * Represents a Truffle-based source configuration for contract information. + * Provides properties to identify the contract name and associated build file + * in order to extract ABI and other necessary data for further web3x usage. + */ interface TruffleSource { - source: 'truffle'; - name: string; - buildFile: string; + /** + * The origin of contract information. + */ +source: 'truffle'; + /** + * The unique identifier for the contract. + */ +name: string; + /** + * The path to the build file containing contract information. + */ +buildFile: string; } +/** + * Represents a Foundry build file source for contract configuration. + * Provides necessary details to locate and use the Foundry generated build files for smart contracts. + */ interface FoundrySource { - source: 'foundry'; - name: string; - buildFile: string; + /** + * The origin of the contract configuration data. + */ +source: 'foundry'; + /** + * The unique identifier for a contract. + */ +name: string; + /** + * The path to the build file containing contract information. + */ +buildFile: string; } +/** + * Represents an inline contract source configuration. + * Provides a convenient way to directly specify the contract ABI and optional initialization data in the configuration object. + */ interface InlineSource { - source: 'inline'; - name: string; - abi: ContractAbiDefinition; - initData?: string; + /** + * The origin of contract ABI and initialization data. + */ +source: 'inline'; + /** + * The name identifier for the contract. + */ +name: string; + /** + * The contract's Application Binary Interface (ABI) definition. + */ +abi: ContractAbiDefinition; + /** + * Initialization data for contract deployment. + */ +initData?: string; } +/** + * Union type representing various contract configuration sources including file, Etherscan, Truffle, Foundry, and inline. + */ export type ContractConfig = FileSource | EtherscanSource | TruffleSource | InlineSource | FoundrySource; +/** + * Represents a configuration object for web3x contract generation. + * Provides options to specify import paths, output paths, and various contract source types for generating contract interfaces. + */ export interface Config { - importPath?: string; - outputPath?: string; - contracts: ContractConfig[]; + /** + * The path to import contracts from. + */ +importPath?: string; + /** + * The destination path for generated output files. + */ +outputPath?: string; + /** + * An array of contract configurations for various sources. + */ +contracts: ContractConfig[]; } diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/index.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/index.ts index 33d8749a910..6c7db0d6372 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/index.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/index.ts @@ -12,13 +12,31 @@ import { getFromFiles } from './source-files.js'; import { getFromFoundry } from './source-foundry.js'; import { getFromTruffle } from './source-truffle.js'; +/** + * Represents contract build data for a smart contract. + * Contains the ABI definition and optional initialization data required for deploying and interacting with the contract. + */ export interface ContractBuildData { - abi: ContractAbiDefinition; - initData?: string; + /** + * The Application Binary Interface (ABI) for a smart contract. + */ +abi: ContractAbiDefinition; + /** + * Initial deployment data for the contract. + */ +initData?: string; } const { ETHERSCAN_API_KEY = '', ETHEREUM_HOST = '' } = process.env; +/** + * Loads contract build data (ABI and initialization data) from the provided configuration object. + * Supports various sources such as Etherscan, files, Truffle, Foundry, and inline configuration. + * Throws an error if the source is not supported or if there's an issue with loading the data. + * + * @param contract - The ContractConfig object containing source and other required details. + * @returns A Promise that resolves to a ContractBuildData object containing ABI and optional initData. + */ export async function loadDataFromConfig(contract: ContractConfig): Promise { switch (contract.source) { case 'etherscan': diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-etherscan.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-etherscan.ts index 52f3fde41b1..1fb88dc7b45 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-etherscan.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-etherscan.ts @@ -11,6 +11,14 @@ import { bufferToHex } from '../../../hex_string/index.js'; import { JsonRpcProvider } from '../../../provider/json_rpc_provider.js'; import { ContractAbiDefinition } from '../../abi/index.js'; +/** + * Get the API host for a given Ethereum network. + * The function maps an input network string to its corresponding etherscan.io API host URL. + * Supported networks are 'mainnet', 'kovan', and 'ropsten'. Throws an error if an unknown network is provided. + * + * @param net - The Ethereum network string (e.g., 'mainnet', 'kovan', or 'ropsten'). + * @returns The etherscan.io API host URL for the specified network. + */ function getApiHost(net: string) { switch (net) { case 'mainnet': @@ -24,6 +32,16 @@ function getApiHost(net: string) { } } +/** + * Fetches the Contract Application Binary Interface (ABI) for a given Ethereum contract address from Etherscan API. + * The ABI is essential for interacting with smart contracts and decoding transactions in Ethereum. + * + * @param net - The Ethereum network identifier, such as 'mainnet', 'kovan', or 'ropsten'. + * @param address - The Ethereum contract address to fetch the ABI for. + * @param apiKey - The Etherscan API key for accessing their services. + * @returns A Promise that resolves to the ContractAbiDefinition containing the fetched ABI. + * @throws An Error if the network is unknown, or fetching the ABI fails. + */ async function getAbi(net: string, address: string, apiKey: string): Promise { const host = getApiHost(net); const abiUrl = `http://${host}/api?module=contract&action=getabi&address=${address}&format=raw&apikey=${apiKey}`; diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-files.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-files.ts index 7b3391a84d1..bb34564aa71 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-files.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-files.ts @@ -8,6 +8,14 @@ import fs from 'fs'; import { ContractAbiDefinition } from '../../abi/index.js'; +/** + * Reads ABI and initData from specified files, and returns an object containing ContractAbiDefinition and initData as properties. + * This function is used to load necessary data for a smart contract from local JSON files. + * + * @param abiFile - The file path to the JSON file containing the ABI (Application Binary Interface) of the smart contract. + * @param initDataFile - Optional. The file path to the JSON file containing the initialization data for the smart contract. + * @returns An object with properties 'abi' containing the ContractAbiDefinition and optional 'initData' containing the initialization data. + */ export function getFromFiles(abiFile: string, initDataFile?: string) { const abi: ContractAbiDefinition = JSON.parse(fs.readFileSync(abiFile).toString()); diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-foundry.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-foundry.ts index 9547d8de0be..5963173c67d 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-foundry.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-foundry.ts @@ -8,7 +8,21 @@ import fs from 'fs'; import { ContractAbiDefinition } from '../../abi/index.js'; -export function getFromFoundry(buildFile: string): { abi: ContractAbiDefinition; initData?: string } { +/** + * Extracts the contract ABI (Application Binary Interface) definition and initialization data from a foundry build file. + * The returned object contains both 'abi' and optional 'initData' properties as parsed from the provided JSON build file. + * This function is useful for obtaining contract information from compiled sources, like Solidity smart contracts. + * + * @param buildFile - The path to the foundry build file containing the ABI and bytecode information. + * @returns An object containing the contract ABI definition and optional initialization data as properties. + */ +export function getFromFoundry(buildFile: string): { /** + * The contract's Application Binary Interface. + */ +abi: ContractAbiDefinition; /** + * The bytecode object representing the contract's initial state. + */ +initData?: string } { const { abi, bytecode: { object: initData }, diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-truffle.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-truffle.ts index 2f5eb9226d2..240d283cc9d 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-truffle.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-truffle.ts @@ -8,7 +8,21 @@ import fs from 'fs'; import { ContractAbiDefinition } from '../../abi/index.js'; -export function getFromTruffle(buildFile: string): { abi: ContractAbiDefinition; initData?: string } { +/** + * Extracts Contract ABI (Application Binary Interface) and initialization data from a Truffle build file. + * The function reads the specified JSON build file and returns an object containing the ABI and initData. + * This can be utilized for deploying and interacting with smart contracts through web3x library. + * + * @param buildFile - The path to the Truffle build file in JSON format. + * @returns An object containing the contract ABI and optional initData (bytecode). + */ +export function getFromTruffle(buildFile: string): { /** + * The JSON representation of a smart contract's interface. + */ +abi: ContractAbiDefinition; /** + * The initialization bytecode for contract deployment. + */ +initData?: string } { const { abi, bytecode: initData } = JSON.parse(fs.readFileSync(buildFile).toString()); return { abi, initData }; } diff --git a/yarn-project/ethereum.js/src/contract/sent_contract_tx.ts b/yarn-project/ethereum.js/src/contract/sent_contract_tx.ts index a5a96580dba..e5af9aacb64 100644 --- a/yarn-project/ethereum.js/src/contract/sent_contract_tx.ts +++ b/yarn-project/ethereum.js/src/contract/sent_contract_tx.ts @@ -16,7 +16,20 @@ export class SentContractTx extends SentTransaction { super(ethRpc, promise); } - protected async handleReceipt(throwOnError = true, receipt: TransactionReceipt) { + /** + * Processes the transaction receipt by decoding events, handling errors, and populating anonymous logs. + * The function takes a TransactionReceipt, a ContractAbi, and an EthereumRpc as its input parameters, + * and returns a Promise that resolves to a ContractTxReceipt containing the processed data. + * It separates logs into anonymousLogs (emitted by external contract calls) and decodes events + * according to the contract's ABI. If the transaction status is falsy, it attempts to decode + * the error using the provided ABI and includes it in the resulting ContractTxReceipt. + * + * @param receipt - The TransactionReceipt to be processed. + * @param contractAbi - The ContractAbi instance used for event decoding and error handling. + * @param ethRpc - The EthereumRpc instance used for interacting with the Ethereum network. + * @returns A Promise that resolves to a ContractTxReceipt object containing anonymousLogs, decoded events, and optional error information. + */ +protected async handleReceipt(throwOnError = true, receipt: TransactionReceipt) { const result = await handleReceipt(receipt, this.contractAbi, this.ethRpc); if (result.error && throwOnError) { throw new Error(`Receipt indicates transaction failed: ${result.error.message}`); @@ -25,6 +38,18 @@ export class SentContractTx extends SentTransaction { } } +/** + * Handle and process a contract transaction receipt by decoding the events and extending + * the original receipt with additional properties (anonymousLogs, events, error) related + * to the contract function call. This function filters out anonymous logs that were emitted + * as part of external contract calls and decodes known events based on the provided ABI. + * If the receipt indicates a failure, it also attempts to decode the error message. + * + * @param receipt - The TransactionReceipt object for the contract function call. + * @param contractAbi - The ContractAbi instance representing the contract's ABI. + * @param ethRpc - The EthereumRpc instance for making RPC calls. + * @returns A Promise resolving to a ContractTxReceipt object with decoded events and extended properties. + */ export async function handleReceipt( receipt: TransactionReceipt, contractAbi: ContractAbi, diff --git a/yarn-project/ethereum.js/src/contract/sent_deploy_contract_tx.ts b/yarn-project/ethereum.js/src/contract/sent_deploy_contract_tx.ts index cb02c2f902b..90b61ed51e2 100644 --- a/yarn-project/ethereum.js/src/contract/sent_deploy_contract_tx.ts +++ b/yarn-project/ethereum.js/src/contract/sent_deploy_contract_tx.ts @@ -18,7 +18,16 @@ export class SentDeployContractTx extends SentContractTx { super(eth, contractAbi, promise); } - protected async handleReceipt(throwOnError = true, receipt: TransactionReceipt): Promise { + /** + * Handles the transaction receipt for a contract deployment, executing a callback + * with the deployed contract address when it is available in the receipt. + * Extends the base class method to include the onDeployed callback execution. + * + * @param throwOnError - A boolean flag indicating whether to throw an error on non-zero exit status. + * @param receipt - The transaction receipt object containing the contract address and other details. + * @returns A Promise resolving to a ContractTxReceipt instance containing transaction receipt data. + */ +protected async handleReceipt(throwOnError = true, receipt: TransactionReceipt): Promise { if (receipt.contractAddress) { this.onDeployed(receipt.contractAddress); } diff --git a/yarn-project/ethereum.js/src/crypto/keccak256/index.ts b/yarn-project/ethereum.js/src/crypto/keccak256/index.ts index 025c104618e..932ae901e39 100644 --- a/yarn-project/ethereum.js/src/crypto/keccak256/index.ts +++ b/yarn-project/ethereum.js/src/crypto/keccak256/index.ts @@ -1,5 +1,13 @@ import { Keccak } from 'sha3'; +/** + * Generate a Keccak-256 hash of the given input Buffer. + * The function takes a Buffer as an input and returns a Buffer containing the hash result. + * It is commonly used for hashing data in Ethereum and other blockchain applications. + * + * @param input - The input data to be hashed, provided as a Buffer. + * @returns A Buffer representing the Keccak-256 hash of the input data. + */ export function keccak256(input: Buffer) { const hash = new Keccak(256); return hash.update(input).digest(); @@ -15,6 +23,14 @@ export function keccak256String(input: string) { return hash.digest('hex'); } +/** + * Generates a sha3 hash by applying the keccak256 hashing algorithm to a given input string. + * The resulting hash is then prefixed with '0x' to indicate that it's a hex-encoded value. + * This function is commonly used for Ethereum address hashing and smart contract function signatures. + * + * @param input - The input string to be hashed using the keccak256 algorithm. + * @returns A hex-encoded sha3 hash string, prefixed with '0x'. + */ export function sha3(input: string) { return '0x' + keccak256String(input); } diff --git a/yarn-project/ethereum.js/src/crypto/pbkdf2/index.ts b/yarn-project/ethereum.js/src/crypto/pbkdf2/index.ts index 6c43728e44a..1817cfbe8fb 100644 --- a/yarn-project/ethereum.js/src/crypto/pbkdf2/index.ts +++ b/yarn-project/ethereum.js/src/crypto/pbkdf2/index.ts @@ -1,5 +1,16 @@ import pbkdf2Lib from 'pbkdf2'; +/** + * Derives a cryptographic key from a password using the PBKDF2 (Password-Based Key Derivation Function 2) algorithm. + * This function returns a Promise that resolves to a Buffer containing the derived key. + * It uses the 'sha256' hash algorithm as the underlying pseudorandom function. + * + * @param password - The input password as a Buffer. + * @param salt - A unique and random salt value as a Buffer to protect against rainbow table attacks. + * @param iterations - The number of iterations to perform, which determines the computational cost of the key derivation. + * @param dklen - The desired length of the derived key in bytes. + * @returns A Promise that resolves to a Buffer containing the derived key. + */ export function pbkdf2(password: Buffer, salt: Buffer, iterations: number, dklen: number): Promise { return new Promise((resolve, reject) => { pbkdf2Lib.pbkdf2(password, salt, iterations, dklen, 'sha256', (err, result) => { @@ -12,6 +23,16 @@ export function pbkdf2(password: Buffer, salt: Buffer, iterations: number, dklen }); } +/** + * Synchronously generates a derived key from the given password and salt using the PBKDF2 algorithm with SHA-256. + * This function is useful when a non-blocking, synchronous operation is required for key derivation. + * + * @param password - The input password as a Buffer. + * @param salt - The salt value as a Buffer. + * @param iterations - The number of iterations to perform in the PBKDF2 algorithm. + * @param dklen - The length of the derived key to generate, in bytes. + * @returns A Buffer containing the derived key. + */ export function pbkdf2Sync(password: Buffer, salt: Buffer, iterations: number, dklen: number) { return pbkdf2Lib.pbkdf2Sync(password, salt, iterations, dklen, 'sha256'); } diff --git a/yarn-project/ethereum.js/src/crypto/scrypt/index.ts b/yarn-project/ethereum.js/src/crypto/scrypt/index.ts index 9741eae6b80..e8632127ef3 100644 --- a/yarn-project/ethereum.js/src/crypto/scrypt/index.ts +++ b/yarn-project/ethereum.js/src/crypto/scrypt/index.ts @@ -23,10 +23,28 @@ function blockmixSalsa8(BY, Yi, r, x, _X) { } } +/** + * Perform a bitwise rotation operation on the given input values. + * The value 'a' is left-shifted by 'b' bits, while the remaining rightmost bits are rotated to the left side. + * This operation is useful in cryptographic algorithms and hash functions. + * + * @param a - The initial integer value to be rotated. + * @param b - The number of bits to perform the rotation operation. + * @returns The resulting integer value after the bitwise rotation. + */ function R(a, b) { return (a << b) | (a >>> (32 - b)); } +/** + * Perform the Salsa20/8 core hashing operation on a given input block. + * This function modifies the provided 512-bit 'B' array in place, applying + * the Salsa20/8 hash function. The '_X' parameter is used as temporary storage + * during the computation to avoid additional memory allocations. + * + * @param B - The 16-element Uint32Array containing the input block to be hashed. + * @param _X - A 16-element Uint32Array used as scratch space during computation. + */ function salsa208(B, x) { arraycopy(B, 0, x, 0, 16); @@ -77,12 +95,32 @@ function blockxor(S, Si, D, len) { } } +/** + * Copies elements from the source array to the destination array. + * Starts copying elements from 'srcPos' index in the source array to 'destPos' index in the destination array, until the given length is reached. + * + * @param src - The source array to copy elements from. + * @param srcPos - The starting position in the source array to begin copying from. + * @param dest - The destination array to copy elements to. + * @param destPos - The starting position in the destination array to begin copying to. + * @param length - The number of elements to be copied from the source to destination array. + */ function arraycopy(src, srcPos, dest, destPos, length) { while (length--) { dest[destPos++] = src[srcPos++]; } } +/** + * Ensures the provided value is an integer. + * Parses the given value to an integer and checks if it's equal to the original value. + * Throws an error if the parsed and the original values are not equal, indicating that the value is not an integer. + * + * @param value - The value to be checked as an integer. + * @param name - A string representing the name of the parameter, used in the error message if the value is not an integer. + * @returns The integer value if the value is a valid integer. + * @throws {Error} If the provided value is not an integer. + */ function ensureInteger(value, name) { const intValue = parseInt(value, 10); if (value !== intValue) { diff --git a/yarn-project/ethereum.js/src/eth_account/eth_account.ts b/yarn-project/ethereum.js/src/eth_account/eth_account.ts index bd0743955ca..454faa2dc85 100644 --- a/yarn-project/ethereum.js/src/eth_account/eth_account.ts +++ b/yarn-project/ethereum.js/src/eth_account/eth_account.ts @@ -11,11 +11,26 @@ import { getTypedDataHash } from '../eth_typed_data/index.js'; const secp256k1 = new elliptic.ec('secp256k1'); +/** + * The EthAccount class represents an Ethereum account with associated private and public keys + * and provides methods for creating accounts, signing transactions, messages, and typed data. + * It also supports operations like validating signatures, generating KeyStore JSON, and creating + * accounts from mnemonics or seeds using HD wallet derivation paths. + */ export class EthAccount { - public readonly address: EthAddress; - public readonly publicKey: Buffer; + /** + * The Ethereum address associated with the account. + */ +public readonly address: EthAddress; + /** + * The public key associated with the Ethereum account. + */ +public readonly publicKey: Buffer; - constructor(public readonly privateKey: Buffer) { + constructor(/** + * The private key of the Ethereum account. + */ +public readonly privateKey: Buffer) { const ecKey = secp256k1.keyFromPrivate(privateKey); this.publicKey = Buffer.from(ecKey.getPublic(false, 'hex'), 'hex'); // Why discarding first byte? @@ -23,34 +38,92 @@ export class EthAccount { this.address = new EthAddress(publicHash.slice(-20)); } - public static create(entropy: Buffer = randomBytes(32)) { + /** + * Create a new EthAccount instance using optional entropy. + * This function generates a random private key, optionally combined with the provided entropy, + * and creates an EthAccount instance with the corresponding address and public key. + * Throws an error if the generated private key is invalid. + * + * @param entropy - Optional buffer containing entropy to be combined with the randomly generated private key. Default is a 32-byte random buffer. + * @returns A new EthAccount instance with the generated private key, address, and public key. + */ +public static create(entropy: Buffer = randomBytes(32)) { const innerHex = keccak256(Buffer.concat([randomBytes(32), entropy])); const middleHex = Buffer.concat([randomBytes(32), innerHex, randomBytes(32)]); const outerHex = keccak256(middleHex); return new EthAccount(outerHex); } - public static fromMnemonicAndPath(mnemonic: string, derivationPath: string) { + /** + * Creates an EthAccount instance from a mnemonic phrase and a derivation path. + * The mnemonic is used to generate the seed, which is then used with the provided derivation path + * to derive the private key for the account. This function is useful when working with + * Hierarchical Deterministic (HD) wallets. + * + * @param mnemonic - The mnemonic phrase representing the seed for the HD wallet. + * @param derivationPath - The derivation path to generate the EthAccount's private key. + * @returns An EthAccount instance with the derived private key. + */ +public static fromMnemonicAndPath(mnemonic: string, derivationPath: string) { const seed = mnemonicToSeedSync(mnemonic); return EthAccount.fromSeedAndPath(seed, derivationPath); } - public static fromSeedAndPath(seed: Buffer, derivationPath: string) { + /** + * Create an EthAccount instance from a seed and derivation path. + * The function takes a Buffer containing the seed and a string with the derivation path, + * and generates the corresponding private key by following the BIP32 HD wallet standard. + * It then creates and returns an EthAccount object using the derived private key. + * + * @param seed - A Buffer containing the seed for the HD wallet. + * @param derivationPath - A string representing the BIP32 derivation path. + * @returns An EthAccount instance with the derived private key. + */ +public static fromSeedAndPath(seed: Buffer, derivationPath: string) { const root = hdkey.fromMasterSeed(seed); const addrNode = root.derive(derivationPath); const privateKey = addrNode.privateKey; return new EthAccount(privateKey); } - public static async fromKeyStoreJson(v3Keystore: KeyStoreJson, password: string) { + /** + * Create an EthAccount instance from a KeyStoreJson object. + * This method decrypts the encrypted private key in the v3 keystore with the provided password, + * and initializes the EthAccount instance with the decrypted private key. + * Throws an error if the password is incorrect or the decryption process fails. + * + * @param v3Keystore - The KeyStoreJson object representing the Ethereum keystore (v3 format). + * @param password - The password used to encrypt the private key in the keystore. + * @returns A Promise that resolves to an EthAccount instance. + */ +public static async fromKeyStoreJson(v3Keystore: KeyStoreJson, password: string) { return new EthAccount(await decryptFromKeyStoreJson(v3Keystore, password)); } - public signTransaction(tx: EthTransaction) { + /** + * Sign an Ethereum transaction using the account's private key. + * This method generates a digital signature for the provided transaction object + * by leveraging the private key of the account instance. The signed transaction can then + * be broadcasted to the Ethereum network for execution. + * + * @param tx - The EthTransaction object representing the details of the transaction to be signed. + * @returns An EthSignature object containing the generated signature for the transaction. + */ +public signTransaction(tx: EthTransaction) { return signTransaction(tx, this.privateKey); } - public signedTransaction(tx: EthTransaction, signature: EthSignature) { + /** + * Checks if a signed Ethereum transaction matches the expected address. + * The function takes an unsigned Ethereum transaction and its corresponding signature, + * then recovers the signer's Ethereum address from the signature and compares it + * to the current EthAccount instance's address. + * + * @param tx - The unsigned Ethereum transaction object. + * @param signature - The Ethereum signature object for the given transaction. + * @returns A boolean indicating whether the recovered address matches the EthAccount's address. + */ +public signedTransaction(tx: EthTransaction, signature: EthSignature) { return signedTransaction(tx, signature).equals(this.address); } @@ -71,15 +144,41 @@ export class EthAccount { return signMessage(digest, this.privateKey); } - public signTypedData(data: TypedData) { + /** + * Sign the typed data by first getting its hashed digest using the provided 'data' parameter, + * and then signing the resulting 32-byte digest with the account's private key. + * This function is useful for signing structured data according to EIP-712 standard. + * + * @param data - A TypedData object containing the type information and values to be signed. + * @returns An EthSignature representing the signature of the hashed typed data. + */ +public signTypedData(data: TypedData) { return this.signDigest(getTypedDataHash(data)); } - public signedMessage(message: Buffer, signature: EthSignature) { + /** + * Verifies if the given signature corresponds to the message signed by this EthAccount instance. + * It hashes the input message with the Ethereum Signed Message preamble, recovers the signer's address + * from the signature, and compares it against the EthAccount's address. + * + * @param message - The Buffer containing the message to be verified. + * @param signature - The EthSignature instance representing the signature of the message. + * @returns A boolean value indicating whether the signature corresponds to the message signed by this EthAccount. + */ +public signedMessage(message: Buffer, signature: EthSignature) { return recoverFromSignature(hashMessage(message), signature).equals(this.address); } - public toKeyStoreJson(password: string, options?: any) { + /** + * Encrypts the EthAccount's private key into a KeyStore JSON format using the provided password. + * The KeyStore JSON can be stored securely and used later to recreate the EthAccount instance. + * The optional 'options' parameter can be used to customize the encryption process. + * + * @param password - The password used for encrypting the private key. + * @param options - Optional configuration object for the encryption process. + * @returns A KeyStoreJson instance representing the encrypted private key. + */ +public toKeyStoreJson(password: string, options?: any) { return encryptToKeyStoreJson(this.privateKey, this.address, password, options); } } diff --git a/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts b/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts index a33b5030e43..0cd3e868e8d 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts @@ -35,12 +35,27 @@ import { LogRequest, toRawLogRequest } from './types/log_request.js'; export class EthereumRpc { constructor(private provider: EthereumProvider) {} - public async protocolVersion() { + /** + * Retrieves the currently implemented Ethereum protocol version. + * The returned value follows the semantic versioning specification (semver). + * This may be useful for determining compatibility between client and server implementations. + * + * @returns A Promise that resolves to a number representing the Ethereum protocol version. + */ +public async protocolVersion() { const result = await this.provider.request({ method: 'eth_protocolVersion' }); return Number(result); } - public async syncing() { + /** + * Retrieves the syncing status of the connected Ethereum node. + * When the node is not syncing, returns false. If syncing, returns an object containing + * startingBlock, currentBlock, and highestBlock which represent the block numbers of + * the syncing process's start point, current progress, and end point respectively. + * + * @returns A Promise that resolves to either false or an object with syncing status data. + */ +public async syncing() { const result = await this.provider.request({ method: 'eth_syncing' }); return { startingBlock: Number(result.startingBlock), @@ -49,12 +64,28 @@ export class EthereumRpc { }; } - public async getChainId() { + /** + * Retrieve the currently configured chain ID of the Ethereum network. + * The chain ID is a unique identifier for each Ethereum network, allowing clients to distinguish + * between multiple networks and ensuring transaction replay protection. + * + * @returns A number representing the current chain ID. + */ +public async getChainId() { const result = await this.provider.request({ method: 'eth_chainId' }); return Number(result); } - public async getCode(address: EthAddress, numberOrTag: NumberOrTag = 'latest') { + /** + * Retrieve the contract code of a given `address` at a specific block number or block tag. + * The function allows querying the Ethereum blockchain for smart contract bytecode. + * Results are returned as a Buffer containing the bytecode in hexadecimal format. + * + * @param address - The EthAddress instance representing the Ethereum address of the smart contract. + * @param numberOrTag - Optional parameter specifying the block number or block tag (default is 'latest'). + * @returns A Promise that resolves to a Buffer containing the contract code in hexadecimal format. + */ +public async getCode(address: EthAddress, numberOrTag: NumberOrTag = 'latest') { const result = await this.provider.request({ method: 'eth_getCode', params: [address.toString(), numberOrTagToHex(numberOrTag)], @@ -62,14 +93,29 @@ export class EthereumRpc { return hexToBuffer(result); } - public async getAccounts() { + /** + * Retrieves a list of Ethereum accounts available on the connected node. + * Each account is represented by an EthAddress instance. Useful for + * querying and interacting with accounts managed by the connected Ethereum node. + * + * @returns An array of EthAddress instances representing the available accounts. + */ +public async getAccounts() { const result: string[] = await this.provider.request({ method: 'eth_accounts', }); return result.map(EthAddress.fromString); } - public async getTransactionCount(addr: EthAddress) { + /** + * Retrieves the number of transactions sent from the specified Ethereum address. + * This function sends a request to the 'eth_getTransactionCount' method with the address and 'latest' as parameters. + * The response is then converted to a Number before being returned. + * + * @param addr - The EthAddress instance representing the Ethereum address. + * @returns The number of transactions sent from the given address. + */ +public async getTransactionCount(addr: EthAddress) { const result = await this.provider.request({ method: 'eth_getTransactionCount', params: [addr.toString(), 'latest'], @@ -77,7 +123,14 @@ export class EthereumRpc { return Number(result); } - public async getBalance(addr: EthAddress) { + /** + * Retrieves the current balance of the given Ethereum address. + * The balance is returned as a BigInt representing the amount of wei held by the address. + * + * @param addr - The EthAddress instance representing the Ethereum address to fetch the balance for. + * @returns A BigInt representing the balance of the given address in wei. + */ +public async getBalance(addr: EthAddress) { const result = await this.provider.request({ method: 'eth_getBalance', params: [addr.toString(), 'latest'], @@ -85,7 +138,14 @@ export class EthereumRpc { return BigInt(result); } - public async getTransactionByHash(txHash: TxHash) { + /** + * Retrieves a transaction by its hash. + * The function returns the transaction details such as block hash, block number, from/to addresses, etc., by querying the Ethereum blockchain. + * + * @param txHash - The transaction hash of the target transaction. + * @returns A Promise that resolves to the transaction details in a human-readable format. + */ +public async getTransactionByHash(txHash: TxHash) { const result = await this.provider.request({ method: 'eth_getTransactionByHash', params: [txHash.toString()], @@ -93,7 +153,16 @@ export class EthereumRpc { return fromRawTransactionResponse(result); } - public async getTransactionReceipt(txHash: TxHash) { + /** + * Retrieves the transaction receipt for the given transaction hash. + * The transaction receipt contains information about the execution of a transaction, + * such as the status, gas used, and logs generated by the transaction. + * Returns undefined if the transaction hash is not found or the transaction is pending. + * + * @param txHash - The TxHash object representing the transaction hash. + * @returns A Promise that resolves to an object containing transaction receipt details or undefined if not found. + */ +public async getTransactionReceipt(txHash: TxHash) { const result = await this.provider.request({ method: 'eth_getTransactionReceipt', params: [txHash.toString()], @@ -101,7 +170,13 @@ export class EthereumRpc { return fromRawTransactionReceipt(result); } - public async blockNumber() { + /** + * Retrieves the current block number from the Ethereum blockchain. + * The result is a decimal representation of the latest mined block number. + * + * @returns A Promise that resolves to the current block number as a Number. + */ +public async blockNumber() { const result = await this.provider.request({ method: 'eth_blockNumber', params: [], @@ -109,7 +184,16 @@ export class EthereumRpc { return Number(result); } - public async getBlockByNumber(numberOrTag: NumberOrTag, fullTxs = false) { + /** + * Retrieve the block information by its block number or block tag. + * The block information includes data such as block hash, parent hash, miner, difficulty, etc. + * The transactions in the block can be optionally fetched in full detail by setting 'fullTxs' to true. + * + * @param numberOrTag - The block number or block tag ('earliest', 'latest', 'pending') to fetch the block information for. + * @param fullTxs - If set to true, the block information will include full transaction details. Defaults to false. + * @returns An object containing the detailed block information or undefined if the block is not found. + */ +public async getBlockByNumber(numberOrTag: NumberOrTag, fullTxs = false) { const result = await this.provider.request({ method: 'eth_getBlockByNumber', params: [numberOrTagToHex(numberOrTag), fullTxs], @@ -117,7 +201,15 @@ export class EthereumRpc { return result ? fromRawBlockResponse(result) : undefined; } - public async sign(address: EthAddress, message: Buffer) { + /** + * Sign a message with the specified Ethereum address using the 'eth_sign' JSON-RPC method. + * The resulting signature can be used to verify that the message was signed by the owner of the provided address. + * + * @param address - The EthAddress instance representing the Ethereum address to sign the message with. + * @param message - The Buffer instance representing the message to be signed. + * @returns A Promise that resolves to an EthSignature instance representing the signed message. + */ +public async sign(address: EthAddress, message: Buffer) { const result = await this.provider.request({ method: 'eth_sign', params: [address.toString(), `0x${message.toString('hex')}`], @@ -125,7 +217,16 @@ export class EthereumRpc { return EthSignature.fromString(result); } - public async personalSign(message: Buffer, address: EthAddress) { + /** + * Sign a message using the 'personal_sign' Ethereum JSON-RPC method with a specified Ethereum address. + * The provided message should be a Buffer, and the Ethereum address should be an EthAddress instance. + * This method is commonly used for signing messages to verify the ownership of an Ethereum account. + * + * @param message - The message to be signed as a Buffer. + * @param address - The EthAddress instance representing the Ethereum account used to sign the message. + * @returns An EthSignature instance containing the signed message from the provided Ethereum address. + */ +public async personalSign(message: Buffer, address: EthAddress) { const result = await this.provider.request({ method: 'personal_sign', params: [`0x${message.toString('hex')}`, address.toString()], @@ -133,7 +234,17 @@ export class EthereumRpc { return EthSignature.fromString(result); } - public async signTypedDataV4(address: EthAddress, data: TypedData) { + /** + * Sign typed data using the EIP-712 Typed Data v4 standard. + * This function sends an 'eth_signTypedData_v4' JSON-RPC request to the Ethereum provider + * with the given address and data. The result is a signature in hex format which can be + * used to verify the signer of the typed data. + * + * @param address - The EthAddress of the signer. + * @param data - The TypedData object representing the structured data to be signed. + * @returns An EthSignature instance representing the signed message. + */ +public async signTypedDataV4(address: EthAddress, data: TypedData) { const result = await this.provider.request({ method: 'eth_signTypedData_v4', params: [address.toString(), data], @@ -141,7 +252,18 @@ export class EthereumRpc { return EthSignature.fromString(result); } - public async estimateGas(tx: CallRequest) { + /** + * Estimate the amount of gas needed for a given transaction to succeed. + * The 'estimateGas' function sends a simulated call request to the Ethereum network + * and returns the estimated gas required for the transaction to be executed. + * This is useful for determining the gas limit to set when sending a real transaction, + * helping to ensure that transactions are executed successfully and avoiding + * unnecessary gas consumption. + * + * @param tx - The CallRequest object containing transaction details. + * @returns A number representing the estimated gas required for the transaction. + */ +public async estimateGas(tx: CallRequest) { const result = await this.provider.request({ method: 'eth_estimateGas', params: [toRawEstimateRequest(tx)], @@ -149,7 +271,16 @@ export class EthereumRpc { return Number(result); } - public async call(tx: CallRequest, numberOrTag: NumberOrTag = 'latest') { + /** + * Executes a call to a smart contract function without modifying the blockchain state. + * The 'call' function returns the result of the executed code, and any gas used during execution is not deducted from the account. + * Useful for querying information from the blockchain or testing if a transaction would succeed without actually sending it. + * + * @param tx - The transaction request object containing information such as 'from', 'to', 'gas', 'gasPrice', 'value', and 'data'. + * @param numberOrTag - (Optional) A block number or one of the string tags "latest", "earliest", or "pending". Default is "latest". + * @returns A Buffer containing the return value of the executed function, if any. + */ +public async call(tx: CallRequest, numberOrTag: NumberOrTag = 'latest') { const data = await this.provider.request({ method: 'eth_call', params: [toRawCallRequest(tx), numberOrTagToHex(numberOrTag)], @@ -157,7 +288,16 @@ export class EthereumRpc { return Buffer.from(data.slice(2), 'hex'); } - public sendTransaction(tx: TransactionRequest): SentTx { + /** + * Sends a signed transaction to the Ethereum network and returns a SentTx instance. + * The 'sendTransaction' method takes a TransactionRequest object as input, converts it to a raw transaction, + * and sends it to the network using the 'eth_sendTransaction' JSON-RPC method. It then returns a SentTx instance + * which can be used to track the status of the submitted transaction, such as fetching the transaction receipt. + * + * @param tx - The TransactionRequest object containing the details of the transaction to be sent. + * @returns A SentTx instance for tracking the submitted transaction's status. + */ +public sendTransaction(tx: TransactionRequest): SentTx { const txHashPromise = this.provider.request({ method: 'eth_sendTransaction', params: [toRawTransactionRequest(tx)], @@ -165,7 +305,15 @@ export class EthereumRpc { return new SentTransaction(this, txHashPromise); } - public async signTransaction(tx: TransactionRequest) { + /** + * Sign a given Ethereum transaction using the specified private key. + * The 'TransactionRequest' object contains necessary information to sign the transaction such as nonce, gas price, gas limit, etc. + * Returns a Promise that resolves with a Buffer containing the signed transaction in raw bytes format. + * + * @param tx - The TransactionRequest object containing information required to sign the transaction. + * @returns A Promise that resolves with a raw signed transaction in buffer format. + */ +public async signTransaction(tx: TransactionRequest) { const result = await this.provider.request({ method: 'eth_signTransaction', params: [toRawTransactionRequest(tx)], @@ -173,7 +321,15 @@ export class EthereumRpc { return hexToBuffer(result); } - public async getLogs(logRequest: LogRequest) { + /** + * Retrieve logs from Ethereum nodes based on the log request provided. + * This function queries the Ethereum node using JSON-RPC and returns an array of logs matching + * the given filters specified in the logRequest object. + * + * @param logRequest - An object containing the filter parameters for the logs to be retrieved. + * @returns An array of log objects matching the filter parameters. + */ +public async getLogs(logRequest: LogRequest) { const result: RawLogResponse[] = await this.provider.request({ method: 'eth_getLogs', params: [toRawLogRequest(logRequest)], diff --git a/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts b/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts index 91ed4a2ca66..3030871d92c 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts @@ -28,11 +28,30 @@ export class SentTransaction implements SentTx { constructor(protected ethRpc: EthereumRpc, protected txHashPromise: Promise) {} - public async getTxHash(): Promise { + /** + * Retrieve the transaction hash of the sent transaction. + * This function returns a promise that resolves with the TxHash of the transaction. + * Useful in tracking the status or obtaining the receipt of the transaction on the blockchain. + * + * @returns A Promise that resolves with the TxHash of the sent transaction. + */ +public async getTxHash(): Promise { return await this.txHashPromise; } - public async getReceipt( + /** + * Retrieve the transaction receipt for a given SentTx instance. + * This function will wait until the transaction has at least 'numConfirmations' confirmations before + * returning the receipt. If 'throwOnError' is set to true, it will throw an error if the receipt + * indicates that the transaction failed. Allows setting a 'timeout' and custom polling 'interval'. + * + * @param {boolean} throwOnError - Whether to throw an error if the receipt status indicates failure. + * @param {number} numConfirmations - The minimum number of confirmations required before returning the receipt. + * @param {number} timeout - The maximum time in seconds to wait for the receipt before giving up. A value of 0 disables the timeout. + * @param {number} interval - The time in seconds between polling attempts to fetch the receipt. + * @returns {Promise} A promise that resolves to the fetched transaction receipt. + */ +public async getReceipt( throwOnError = true, numConfirmations = 1, timeout = 0, @@ -47,7 +66,16 @@ export class SentTransaction implements SentTx { return await this.handleReceipt(throwOnError, receipt); } - protected handleReceipt(throwOnError = true, receipt: TransactionReceipt) { + /** + * Handles the transaction receipt based on the provided parameters. + * If throwOnError is true and the receipt status is false, an error will be thrown. + * Otherwise, returns the received transaction receipt as a resolved promise. + * + * @param throwOnError - A boolean flag indicating whether to throw an error if receipt status is false. + * @param receipt - The TransactionReceipt object received from the Ethereum network. + * @returns A Promise resolving to the given TransactionReceipt. + */ +protected handleReceipt(throwOnError = true, receipt: TransactionReceipt) { if (throwOnError && !receipt.status) { throw new Error('Receipt indicates transaction failed. Try a call() to determine cause of failure.'); } diff --git a/yarn-project/ethereum.js/src/eth_rpc/tx_hash.ts b/yarn-project/ethereum.js/src/eth_rpc/tx_hash.ts index f5d07c8ab1b..4d06c92d0ce 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/tx_hash.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/tx_hash.ts @@ -1,5 +1,11 @@ import { randomBytes } from '../crypto/random/index.js'; +/** + * The TxHash class represents a transaction hash in the form of a 32-byte buffer. + * It provides methods to create a TxHash instance from different input formats such as Buffer, string, or random bytes, + * as well as methods to compare, convert, and serialize the hash value. + * This class ensures that the transaction hash is valid and properly formatted. + */ export class TxHash { constructor(private buffer: Buffer) { if (buffer.length !== 32) { @@ -7,31 +13,85 @@ export class TxHash { } } - static fromBuffer(buffer: Buffer) { + /** + * Create a TxHash instance from a given buffer. + * The input 'buffer' should be a Buffer with exactly 32 bytes length. + * Throws an error if the input buffer length is invalid. + * + * @param buffer - The Buffer representing the transaction hash. + * @returns A TxHash instance. + */ +static fromBuffer(buffer: Buffer) { return new TxHash(buffer); } - static deserialize(buffer: Buffer, offset: number) { + /** + * Deserialize a Buffer into a TxHash instance starting at the specified offset. + * The function takes a buffer and an optional offset as input, slices the buffer + * from the offset to offset + 32 bytes, and creates a new TxHash object using this slice. + * Returns an object containing the created TxHash instance ('elem') and the number + * of bytes advanced in the buffer ('adv'), which is always 32 for a valid deserialization. + * + * @param buffer - The input Buffer containing the serialized TxHash data. + * @param offset - The optional starting position within the buffer to begin deserialization. Defaults to 0. + * @returns An object with properties 'elem' (TxHash instance) and 'adv' (number of bytes advanced). + */ +static deserialize(buffer: Buffer, offset: number) { return { elem: new TxHash(buffer.slice(offset, offset + 32)), adv: 32 }; } - public static fromString(hash: string) { + /** + * Create a TxHash instance from a hex-encoded string. + * The input 'hash' should be prefixed with '0x' or not, and have exactly 64 hex characters. + * Throws an error if the input length is invalid or the hash value is out of range. + * + * @param hash - The hex-encoded string representing the transaction hash. + * @returns A TxHash instance. + */ +public static fromString(hash: string) { return new TxHash(Buffer.from(hash.replace(/^0x/i, ''), 'hex')); } - public static random() { + /** + * Generate a random TxHash instance with a buffer of 32 random bytes. + * This function utilizes the 'randomBytes' function from the crypto library to generate + * a buffer filled with cryptographically secure random bytes, which is then used to create + * the new TxHash instance. + * + * @returns A random TxHash instance. + */ +public static random() { return new TxHash(randomBytes(32)); } - equals(rhs: TxHash) { + /** + * Compares the current TxHash instance with the provided TxHash instance. + * Returns true if their buffer contents are equal, otherwise returns false. + * + * @param rhs - The TxHash instance to compare with the current instance. + * @returns A boolean indicating whether the two TxHash instances have identical buffer contents. + */ +equals(rhs: TxHash) { return this.toBuffer().equals(rhs.toBuffer()); } - toBuffer() { + /** + * Converts the current TxHash instance to a Buffer. + * The resulting buffer will have a length of 32 bytes. + * + * @returns A Buffer representation of the transaction hash. + */ +toBuffer() { return this.buffer; } - toString() { + /** + * Converts the TxHash instance to a hex-encoded string representation. + * The resulting string is prefixed with '0x' and contains exactly 64 hex characters. + * + * @returns A string representing the TxHash in hex format. + */ +toString() { return `0x${this.toBuffer().toString('hex')}`; } } diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/block_response.ts b/yarn-project/ethereum.js/src/eth_rpc/types/block_response.ts index 43499e2ea1d..324fc03604f 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/block_response.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/block_response.ts @@ -14,58 +14,203 @@ import { TransactionResponse, } from './transaction_response.js'; +/** + * Represents a raw block header response in Ethereum. + * Contains all the essential information of a block, such as hash, parentHash, miner, and other details + * fetched from an Ethereum node, with values encoded as hexadecimal strings. + */ export interface RawBlockHeaderResponse { - hash: string | null; - parentHash: string; - sha3Uncles: string; - miner: string; - stateRoot: string; - transactionsRoot: string; - receiptsRoot: string; - logsBloom: string | null; - difficulty: string; - number: string | null; - gasLimit: string; - gasUsed: string; - timestamp: string; - extraData: string; - nonce: string | null; - baseFeePerGas: string | null; + /** + * The unique identifier of a block. + */ +hash: string | null; + /** + * The parent block's hash value. + */ +parentHash: string; + /** + * The Keccak-256 hash of the uncles data in the block. + */ +sha3Uncles: string; + /** + * The Ethereum address of the block miner. + */ +miner: string; + /** + * The root hash of the Ethereum state trie. + */ +stateRoot: string; + /** + * The root hash of the merkle tree representing all transactions in the block. + */ +transactionsRoot: string; + /** + * The root hash of the trie structure containing all transaction receipts in the block. + */ +receiptsRoot: string; + /** + * Bloom filter containing logs for all transactions in the block. + */ +logsBloom: string | null; + /** + * The computational effort required to mine a new block. + */ +difficulty: string; + /** + * The block number in the blockchain. + */ +number: string | null; + /** + * The maximum amount of gas allowed in the block. + */ +gasLimit: string; + /** + * The total amount of gas consumed by all transactions in the block. + */ +gasUsed: string; + /** + * Unix timestamp representing the block creation time. + */ +timestamp: string; + /** + * Extra arbitrary metadata included in the block. + */ +extraData: string; + /** + * A unique number used to prevent double-spending and ensure the validity of a transaction. + */ +nonce: string | null; + /** + * The base fee per gas for each block, used in EIP-1559. + */ +baseFeePerGas: string | null; } +/** + * Represents a raw block response in the Ethereum blockchain. + * Contains information pertaining to the block header, transactions, and uncles in their raw hexadecimal format. + */ export interface RawBlockResponse extends RawBlockHeaderResponse { - totalDifficulty: string; - size: string; - transactions: (RawTransactionResponse | string)[]; - uncles: string[]; + /** + * The total accumulated difficulty of the blockchain up to this block. + */ +totalDifficulty: string; + /** + * Size of the block in bytes. + */ +size: string; + /** + * A list of transactions included within the block. + */ +transactions: (RawTransactionResponse | string)[]; + /** + * An array of uncle blocks in the blockchain. + */ +uncles: string[]; } +/** + * Represents a block header response in the Ethereum blockchain. + * Provides essential information about a specific block, including its hash, parent hash, miner address, and other properties. + */ export interface BlockHeaderResponse { - hash: Buffer | null; - parentHash: Buffer; - sha3Uncles: Buffer; - miner: EthAddress; - stateRoot: Buffer; - transactionsRoot: Buffer; - receiptsRoot: Buffer; - logsBloom: Buffer | null; - difficulty: bigint; - number: number | null; - gasLimit: number; - gasUsed: number; - timestamp: number; - extraData: Buffer; - nonce: Buffer | null; - baseFeePerGas: bigint | null; + /** + * The hash representing the unique identifier of a block. + */ +hash: Buffer | null; + /** + * The hash of the parent block in the blockchain. + */ +parentHash: Buffer; + /** + * The Keccak-256 hash of the uncle blocks included in the block. + */ +sha3Uncles: Buffer; + /** + * The Ethereum address of the miner who successfully mined the block. + */ +miner: EthAddress; + /** + * The root hash of the state trie after applying transactions. + */ +stateRoot: Buffer; + /** + * The root hash of the Merkle tree containing all transaction hashes in the block. + */ +transactionsRoot: Buffer; + /** + * The root hash of the Merkle tree containing transaction receipts. + */ +receiptsRoot: Buffer; + /** + * A compressed representation of logs' topics and data for efficient filtering. + */ +logsBloom: Buffer | null; + /** + * The computational effort required to mine a new block. + */ +difficulty: bigint; + /** + * The block number within the blockchain. + */ +number: number | null; + /** + * The maximum amount of gas allowed in a block. + */ +gasLimit: number; + /** + * The total amount of gas consumed by all transactions in the block. + */ +gasUsed: number; + /** + * The UNIX timestamp when the block was mined. + */ +timestamp: number; + /** + * Arbitrary data included by the block miner. + */ +extraData: Buffer; + /** + * A unique value used to prevent duplicate transactions and secure block mining. + */ +nonce: Buffer | null; + /** + * The base fee per gas for the block, used in EIP-1559 transactions. + */ +baseFeePerGas: bigint | null; } +/** + * Represents a block on the Ethereum blockchain. + * Contains information about the block header, transactions, and other metadata. + */ export interface BlockResponse extends BlockHeaderResponse { - totalDifficulty: bigint; - size: number; - transactions: T[]; - uncles: string[]; + /** + * The cumulative proof-of-work difficulty of the blockchain up to this block. + */ +totalDifficulty: bigint; + /** + * The byte size of the block. + */ +size: number; + /** + * Array of transactions included in the block. + */ +transactions: T[]; + /** + * Uncles are stale blocks included in the main chain to provide a reward for partially mined blocks. + */ +uncles: string[]; } +/** + * Convert a BlockHeaderResponse object to its raw representation (RawBlockHeaderResponse). + * The function takes a BlockHeaderResponse containing Buffers and BigInts and converts + * them to appropriate hex strings, preserving the structure of the original object. + * + * @param block - The BlockHeaderResponse object to be converted to RawBlockHeaderResponse. + * @returns A RawBlockHeaderResponse object with hex-encoded values. + */ export function toRawBlockHeaderResponse(block: BlockHeaderResponse): RawBlockHeaderResponse { return { hash: block.hash ? bufferToHex(block.hash) : null, @@ -87,6 +232,14 @@ export function toRawBlockHeaderResponse(block: BlockHeaderResponse): RawBlockHe }; } +/** + * Converts a BlockResponse object into its corresponding RawBlockResponse representation. + * The function maps the properties in the input BlockResponse object to their respective hex-encoded string (where applicable) or appropriate raw format. + * It handles the conversion of transaction objects as well, invoking 'toRawTransactionResponse' for each entry. + * + * @param block - The BlockResponse object to be converted into a RawBlockResponse. + * @returns A RawBlockResponse object with the same data as the input BlockResponse, but in raw form. + */ export function toRawBlockResponse(block: BlockResponse): RawBlockResponse { return { ...toRawBlockHeaderResponse(block), @@ -97,6 +250,15 @@ export function toRawBlockResponse(block: BlockResponse): RawBlockResponse { }; } +/** + * Convert a raw block header response object to a formatted block header response object. + * The function takes a raw block header response object with hex-encoded values and converts + * them into appropriate data types such as Buffer, BigInt, or Number. It also converts the miner address + * from a string to an EthAddress instance. + * + * @param block - The raw block header response object with hex-encoded values. + * @returns A formatted block header response object with appropriate data types. + */ export function fromRawBlockHeaderResponse(block: RawBlockHeaderResponse): BlockHeaderResponse { return { hash: block.hash ? hexToBuffer(block.hash) : null, @@ -118,6 +280,14 @@ export function fromRawBlockHeaderResponse(block: RawBlockHeaderResponse): Block }; } +/** + * Converts a RawBlockResponse object into a BlockResponse object by parsing hex-encoded strings to their corresponding types. + * This function is useful for converting raw block responses received from external sources into a more manageable format + * with proper data types like Buffer, EthAddress, and bigint. + * + * @param block - The RawBlockResponse object containing hex-encoded strings and other raw values. + * @returns A BlockResponse object with parsed values and proper data types. + */ export function fromRawBlockResponse(block: RawBlockResponse): BlockResponse { return { ...fromRawBlockHeaderResponse(block), diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/call_request.ts b/yarn-project/ethereum.js/src/eth_rpc/types/call_request.ts index f0dbc47c187..1aef5005db5 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/call_request.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/call_request.ts @@ -8,26 +8,86 @@ import { numberToHex, } from '../../hex_string/index.js'; +/** + * Represents a call request object for Ethereum transactions. + * Contains optional parameters such as 'from', 'to', 'gas', 'maxFeePerGas', 'maxPriorityFeePerGas', 'value', and 'data'. + * Used to define the structure of the transaction details when making a function call or sending Ether between addresses. + */ export interface CallRequest { - from?: EthAddress; - to?: EthAddress; - gas?: number; - maxFeePerGas?: bigint; - maxPriorityFeePerGas?: bigint; - value?: bigint; - data?: Buffer; + /** + * The sender's Ethereum address. + */ +from?: EthAddress; + /** + * The destination Ethereum address for the call request. + */ +to?: EthAddress; + /** + * The maximum amount of gas units to be used for the transaction execution. + */ +gas?: number; + /** + * Maximum fee per gas unit for transaction processing. + */ +maxFeePerGas?: bigint; + /** + * Maximum fee per gas for transaction priority. + */ +maxPriorityFeePerGas?: bigint; + /** + * The amount of Ether (in wei) to be transferred with the call. + */ +value?: bigint; + /** + * The input data to be executed by the called contract. + */ +data?: Buffer; } +/** + * Represents a raw Ethereum call request object with fields in hexadecimal string format. + * This interface is used to convert and interact with the CallRequest object, which uses + * more specific data types like bigint and Buffer for better type safety and readability. + */ export interface RawCallRequest { - from?: string; - to?: string; - gas?: string; - maxFeePerGas?: string; - maxPriorityFeePerGas?: string; - value?: string; - data?: string; + /** + * The Ethereum address initiating the call. + */ +from?: string; + /** + * The destination Ethereum address for the call request. + */ +to?: string; + /** + * The maximum amount of gas allowed for executing the transaction. + */ +gas?: string; + /** + * Maximum fee per gas unit for transaction processing. + */ +maxFeePerGas?: string; + /** + * The maximum fee per gas unit prioritized for transaction inclusion. + */ +maxPriorityFeePerGas?: string; + /** + * The amount of Ether to be transferred in the transaction, represented as a bigint. + */ +value?: string; + /** + * The encoded function call data for the contract method. + */ +data?: string; } +/** + * Convert a CallRequest object to its RawCallRequest representation. + * This function takes a CallRequest object with typed properties (EthAddress, bigint, Buffer) + * and returns a RawCallRequest object with the corresponding hex string representations. + * + * @param tx - The CallRequest object containing Ethereum transaction data in typed format. + * @returns A RawCallRequest object with the same transaction data in hex string format. + */ export function toRawCallRequest(tx: CallRequest): RawCallRequest { const { from, to, gas, maxFeePerGas, maxPriorityFeePerGas, value, data } = tx; return { @@ -41,6 +101,16 @@ export function toRawCallRequest(tx: CallRequest): RawCallRequest { }; } +/** + * Convert a RawCallRequest object into a CallRequest object by parsing and converting + * its properties from hex-encoded strings to their respective data types. + * This function handles 'from', 'to', 'gas', 'maxFeePerGas', 'maxPriorityFeePerGas', + * 'value', and 'data' properties. It also creates EthAddress instances for 'from' and 'to'. + * If any property is not present in the input, it will remain undefined in the output. + * + * @param tx - The RawCallRequest object with hex-encoded string properties. + * @returns A CallRequest object with parsed and converted properties. + */ export function fromRawCallRequest(tx: RawCallRequest): CallRequest { const { from, to, gas, maxFeePerGas, maxPriorityFeePerGas, value, data } = tx; return { diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/estimate_gas_request.ts b/yarn-project/ethereum.js/src/eth_rpc/types/estimate_gas_request.ts index bdd7f7ee984..d08f7ee325f 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/estimate_gas_request.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/estimate_gas_request.ts @@ -8,26 +8,86 @@ import { numberToHex, } from '../../hex_string/index.js'; +/** + * Represents an Ethereum transaction estimate request. + * Contains information about the sender, receiver, gas limit, and other transaction-related details + * necessary for estimating the gas cost of a transaction on the Ethereum network. + */ export interface EstimateRequest { - from?: EthAddress; - to?: EthAddress; - gas?: number; - maxFeePerGas?: bigint; - maxPriorityFeePerGas?: bigint; - value?: bigint; - data?: Buffer; + /** + * The Ethereum address of the transaction sender. + */ +from?: EthAddress; + /** + * The destination Ethereum address for the transaction. + */ +to?: EthAddress; + /** + * The maximum amount of gas units allowed for the transaction execution. + */ +gas?: number; + /** + * The maximum fee per gas unit for the transaction. + */ +maxFeePerGas?: bigint; + /** + * The maximum fee per gas unit for transaction prioritization. + */ +maxPriorityFeePerGas?: bigint; + /** + * The amount of Ether to be sent in the transaction, represented as a bigint. + */ +value?: bigint; + /** + * The byte array of the transaction's input data. + */ +data?: Buffer; } +/** + * Represents a raw estimate request object for Ethereum transactions. + * Contains essential transaction parameters in hexadecimal string format. + * This format is commonly used when interacting with Ethereum nodes or web3.js library. + */ export interface RawEstimateRequest { - from?: string; - to?: string; - gas?: string; - maxFeePerGas?: string; - maxPriorityFeePerGas?: string; - value?: string; - data?: string; + /** + * The Ethereum address initiating the transaction. + */ +from?: string; + /** + * The destination Ethereum address for the transaction. + */ +to?: string; + /** + * The maximum amount of gas units to be used for the transaction. + */ +gas?: string; + /** + * Maximum fee per gas unit for the transaction. + */ +maxFeePerGas?: string; + /** + * The maximum fee per gas unit to prioritize transaction processing. + */ +maxPriorityFeePerGas?: string; + /** + * The amount of Ether to be transferred in the transaction, represented as a BigInt. + */ +value?: string; + /** + * The transaction's input data as a Buffer. + */ +data?: string; } +/** + * Converts an EstimateRequest object into a RawEstimateRequest object by transforming its properties. + * This function is useful for preparing an EstimateRequest to be sent over RPC or other serialization protocols. + * It converts EthAddress instances to strings, BigInt values to hex-encoded strings, and Buffers to hex-encoded strings. + * + * @param tx - The EstimateRequest object containing transaction properties. + * @returns A RawEstimateRequest object with transformed properties. + */ export function toRawEstimateRequest(tx: EstimateRequest): RawEstimateRequest { const { from, to, gas, maxFeePerGas, maxPriorityFeePerGas, value, data } = tx; return { @@ -41,6 +101,14 @@ export function toRawEstimateRequest(tx: EstimateRequest): RawEstimateRequest { }; } +/** + * Converts a RawEstimateRequest object with hex-encoded strings to an EstimateRequest object + * with appropriate data types, such as BigInt and Buffer. This is useful when working with + * Ethereum transaction estimates received from external sources in a raw format. + * + * @param tx - The RawEstimateRequest object with hex-encoded string values. + * @returns An EstimateRequest object with appropriate data types. + */ export function fromRawEstimateRequest(tx: RawEstimateRequest): EstimateRequest { const { from, to, gas, maxFeePerGas, maxPriorityFeePerGas, value, data } = tx; return { diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/log_request.ts b/yarn-project/ethereum.js/src/eth_rpc/types/log_request.ts index 790afc94a9c..8d65c0cfb5d 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/log_request.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/log_request.ts @@ -2,21 +2,63 @@ import { EthAddress } from '@aztec/foundation'; import { bufferToHex } from '../../hex_string/index.js'; import { NumberOrTag, numberOrTagToHex } from './number_or_tag.js'; +/** + * Represents a log request configuration for Ethereum events. + * Contains optional filter criteria, block range, contract addresses, and topics to refine the log search. + */ export interface LogRequest { - filter?: Partial; - toBlock?: NumberOrTag; - fromBlock?: NumberOrTag; - address?: EthAddress | EthAddress[]; - topics?: (Buffer | Buffer[] | null)[]; + /** + * Filter object for specifying event fields to be matched in logs. + */ +filter?: Partial; + /** + * The block number or block tag to end the log search. + */ +toBlock?: NumberOrTag; + /** + * The starting block number or identifier to fetch logs from. + */ +fromBlock?: NumberOrTag; + /** + * Ethereum address or array of addresses to filter logs by. + */ +address?: EthAddress | EthAddress[]; + /** + * An array of topic filters for log events, allowing the selection of specific events or a combination thereof. + */ +topics?: (Buffer | Buffer[] | null)[]; } +/** + * Represents a raw log request object for querying logs from Ethereum nodes. + * Contains optional parameters to filter and format the logs based on block range, address, and topics. + */ export interface RawLogRequest { - toBlock?: string; - fromBlock?: string; - address?: string | string[]; - topics?: ((string | null) | (string | null)[])[]; + /** + * The block number or tag until which logs should be fetched, inclusive. + */ +toBlock?: string; + /** + * The starting block for the log search, inclusive. + */ +fromBlock?: string; + /** + * Ethereum address or an array of addresses, used as a filter for the logs. + */ +address?: string | string[]; + /** + * An array of topics used for filtering specific event logs. + */ +topics?: ((string | null) | (string | null)[])[]; } +/** + * Converts a LogRequest object into a RawLogRequest object with hex string values. + * This function is useful for preparing log requests to be sent to Ethereum nodes. + * + * @param logRequest - A LogRequest object containing the filter, block range, address, and topics for events. + * @returns A RawLogRequest object with converted hex string values for block numbers and topics. + */ export function toRawLogRequest(logRequest: LogRequest = {}): RawLogRequest { const rawLogRequest: RawLogRequest = {}; diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/log_response.ts b/yarn-project/ethereum.js/src/eth_rpc/types/log_response.ts index 7731ce31856..386987c2e30 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/log_response.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/log_response.ts @@ -3,32 +3,110 @@ import { EthAddress } from '@aztec/foundation'; import { numberToHex } from '../../hex_string/index.js'; import { TxHash } from '../tx_hash.js'; +/** + * Represents the raw log response data structure from an Ethereum node. + * Contains information about events emitted during the execution of a smart contract transaction. + */ export interface RawLogResponse { - id?: string; - removed?: boolean; - logIndex: string | null; - blockNumber: string | null; - blockHash: string | null; - transactionHash: string | null; - transactionIndex: string | null; - address: string; - data: string; - topics: string[]; + /** + * Unique identifier for a log event. + */ +id?: string; + /** + * Indicates if the log entry has been removed due to a chain reorganization. + */ +removed?: boolean; + /** + * The index of the log entry within its corresponding block. + */ +logIndex: string | null; + /** + * The block number where the log was generated. + */ +blockNumber: string | null; + /** + * The unique identifier (hash) of the block containing the log event. + */ +blockHash: string | null; + /** + * The unique hash identifying a specific transaction. + */ +transactionHash: string | null; + /** + * The index position of the transaction within a block. + */ +transactionIndex: string | null; + /** + * The Ethereum address associated with the log event. + */ +address: string; + /** + * The hexadecimal encoded data associated with the log event. + */ +data: string; + /** + * An array of indexed event parameters. + */ +topics: string[]; } +/** + * Represents a log response from the Ethereum network. + * Contains information about events emitted by smart contracts during transaction execution, + * such as event signatures, topics, and data associated with the event. + */ export interface LogResponse { - id: string | null; - removed?: boolean; - logIndex: number | null; - blockNumber: number | null; - blockHash: string | null; - transactionHash: TxHash | null; - transactionIndex: number | null; - address: EthAddress; - data: string; - topics: string[]; + /** + * Unique identifier for the log event. + */ +id: string | null; + /** + * Indicates whether the log entry has been removed due to a chain reorganization. + */ +removed?: boolean; + /** + * The index position of the log entry within the block. + */ +logIndex: number | null; + /** + * The block number in which the log was generated. + */ +blockNumber: number | null; + /** + * The unique hash identifier of the block containing the log entry. + */ +blockHash: string | null; + /** + * The unique identifier of the transaction in the blockchain. + */ +transactionHash: TxHash | null; + /** + * The index position of the transaction within the block. + */ +transactionIndex: number | null; + /** + * The Ethereum address associated with the log event. + */ +address: EthAddress; + /** + * The data field of a logged event in the Ethereum contract. + */ +data: string; + /** + * An array of indexed event arguments. + */ +topics: string[]; } +/** + * Converts a RawLogResponse object into a LogResponse object. + * The function generates a custom log id, if not provided, by concatenating the blockHash, transactionHash, and logIndex values after removing the '0x' prefix. + * It also converts string representations of blockNumber, transactionIndex, and logIndex to their corresponding numeric values. + * Additionally, it creates EthAddress and TxHash instances for address and transactionHash fields, respectively. + * + * @param log - The RawLogResponse object to be converted. + * @returns A LogResponse object with proper data types and structure. + */ export function fromRawLogResponse(log: RawLogResponse): LogResponse { let id: string | null = log.id || null; @@ -53,6 +131,16 @@ export function fromRawLogResponse(log: RawLogResponse): LogResponse { return { ...log, id, blockNumber, transactionIndex, transactionHash, logIndex, address }; } +/** + * Converts a LogResponse object to its corresponding RawLogResponse format. + * This function is used to revert the processed LogResponse back to its raw format, + * primarily for compatibility with Ethereum JSON-RPC API or other libraries that + * expect raw log data. The output will have all number properties converted to hex-strings + * and addresses in lowercase representation where applicable. + * + * @param log - The LogResponse object to be converted to RawLogResponse format. + * @returns A RawLogResponse object containing original raw log data. + */ export function toRawLogResponse(log: LogResponse): RawLogResponse { const { id, blockNumber, transactionIndex, logIndex, address, transactionHash } = log; return { diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/number_or_tag.ts b/yarn-project/ethereum.js/src/eth_rpc/types/number_or_tag.ts index e4e9ada5632..366bf37edb1 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/number_or_tag.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/number_or_tag.ts @@ -1,5 +1,8 @@ import { numberToHex } from '../../hex_string/index.js'; +/** + * Type representing Ethereum block numbers or tags, used to specify a particular block when querying blockchain data. + */ export type NumberOrTag = number | 'latest' | 'earliest' | 'pending'; export const numberOrTagToHex = (numberOrTag: NumberOrTag) => diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_receipt.ts b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_receipt.ts index 32de02598e2..4b85dd5c076 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_receipt.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_receipt.ts @@ -3,34 +3,120 @@ import { fromRawLogResponse, LogResponse, RawLogResponse, toRawLogResponse } fro import { numberToHex } from '../../hex_string/index.js'; import { TxHash } from '../tx_hash.js'; +/** + * Represents a raw Ethereum transaction receipt object. + * Contains essential information about the transaction, including its hash, index, block number, and gas usage. + * Also includes details about the sender, recipient, contract address, logs, and the transaction's status. + */ export interface RawTransactionReceipt { - transactionHash: string; - transactionIndex: string; - blockHash: string; - blockNumber: string; - from: string; - to: string | null; - cumulativeGasUsed: string; - gasUsed: string; - contractAddress: string | null; - logs: RawLogResponse[]; - status: string; + /** + * The unique identifier of the transaction. + */ +transactionHash: string; + /** + * The index of the transaction within the block. + */ +transactionIndex: string; + /** + * The hash identifier of the block containing the transaction. + */ +blockHash: string; + /** + * The block number in which the transaction was included. + */ +blockNumber: string; + /** + * The Ethereum address of the transaction sender. + */ +from: string; + /** + * The destination Ethereum address involved in the transaction. + */ +to: string | null; + /** + * The total amount of gas used by all transactions in the block up to and including this transaction. + */ +cumulativeGasUsed: string; + /** + * The amount of gas consumed by the transaction. + */ +gasUsed: string; + /** + * Address of the deployed contract, if applicable. + */ +contractAddress: string | null; + /** + * An array of event logs emitted by the smart contract during the transaction execution. + */ +logs: RawLogResponse[]; + /** + * The transaction success status, where 'true' indicates success and 'false' indicates failure. + */ +status: string; } +/** + * Represents a transaction receipt on the Ethereum blockchain. + * Contains detailed information about a processed transaction, including its status, gas usage, and associated logs. + */ export interface TransactionReceipt { - transactionHash: TxHash; - transactionIndex: number; - blockHash: string; - blockNumber: number; - from: EthAddress; - to?: EthAddress; - cumulativeGasUsed: number; - gasUsed: number; - contractAddress?: EthAddress; - logs: LogResponse[]; - status: boolean; + /** + * The unique hash identifier of the transaction. + */ +transactionHash: TxHash; + /** + * The index of the transaction within its containing block. + */ +transactionIndex: number; + /** + * The unique identifier of the block containing the transaction. + */ +blockHash: string; + /** + * The block number containing the transaction. + */ +blockNumber: number; + /** + * The Ethereum address of the transaction sender. + */ +from: EthAddress; + /** + * The destination Ethereum address involved in the transaction. + */ +to?: EthAddress; + /** + * The total amount of gas used by all transactions up to and including this one in the block. + */ +cumulativeGasUsed: number; + /** + * The amount of gas utilized during the transaction execution. + */ +gasUsed: number; + /** + * The Ethereum address of the deployed smart contract, if applicable. + */ +contractAddress?: EthAddress; + /** + * An array of log events emitted by the transaction. + */ +logs: LogResponse[]; + /** + * The transaction execution status; true if successful, false otherwise. + */ +status: boolean; } +/** + * Converts a RawTransactionReceipt object to a TransactionReceipt object. + * Transforms string representations of properties such as transaction index, block number, + * cumulative gas used, and gas used into their respective numeric types. Additionally, + * it converts the 'from', 'to', and 'contractAddress' properties to EthAddress instances, + * and the 'logs' property to LogResponse objects. The function also converts the 'status' + * property to a boolean value, indicating the success or failure of the transaction. + * + * @param receipt - The RawTransactionReceipt object to be converted. + * @returns A TransactionReceipt object with transformed properties or undefined if the input receipt is invalid or missing. + */ export function fromRawTransactionReceipt(receipt?: RawTransactionReceipt): TransactionReceipt | undefined { if (!receipt || !receipt.blockHash) { return; @@ -51,6 +137,14 @@ export function fromRawTransactionReceipt(receipt?: RawTransactionReceipt): Tran }; } +/** + * Converts a TransactionReceipt object to its raw form, which is an object containing string representations of all properties. + * The function takes care of converting the properties such as EthAddress objects, numbers, and booleans to their corresponding + * string forms. Useful for serialization or converting the data back to a format that can be sent over the network or stored. + * + * @param receipt - The TransactionReceipt object to be converted to its raw form. + * @returns A RawTransactionReceipt object containing string representations of all properties from the input TransactionReceipt. + */ export function toRawTransactionReceipt(receipt: TransactionReceipt): RawTransactionReceipt { return { ...receipt, diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts index d261e654807..6b606c56e98 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts @@ -8,19 +8,59 @@ import { numberToHex, } from '../../hex_string/index.js'; +/** + * Represents an Ethereum transaction request. + * Provides a structured format for specifying the required parameters when sending a new transaction on the Ethereum network. + */ export interface TransactionRequest { - from: EthAddress; - to?: EthAddress; - gas?: number; - maxFeePerGas?: bigint; - maxPriorityFeePerGas?: bigint; - value?: bigint; - data?: Buffer; - nonce?: number; + /** + * The Ethereum address initiating the transaction. + */ +from: EthAddress; + /** + * The destination Ethereum address for the transaction. + */ +to?: EthAddress; + /** + * The maximum amount of gas units allowed for the transaction execution. + */ +gas?: number; + /** + * The maximum fee per gas unit for the transaction. + */ +maxFeePerGas?: bigint; + /** + * The maximum fee per gas unit that the sender is willing to pay for transaction priority. + */ +maxPriorityFeePerGas?: bigint; + /** + * The amount of Ether to be transferred in the transaction. + */ +value?: bigint; + /** + * The encoded contract function call data. + */ +data?: Buffer; + /** + * A unique number that prevents double-spending in transactions. + */ +nonce?: number; } +/** + * Type representing a raw Ethereum transaction request, where all properties are encoded as hexadecimal strings. + * Useful for serialization and deserialization of transaction data to and from external systems or storage. + */ export type RawTransactionRequest = { [k in keyof TransactionRequest]: string }; +/** + * Converts a TransactionRequest object into a RawTransactionRequest object by converting all properties to string format. + * The function ensures that the 'from' and 'to' addresses are in lowercase, and bigint, number, and Buffer values are converted to hexadecimal strings. + * If a property is not present in the input TransactionRequest object, it will be set to 'undefined' in the output RawTransactionRequest object. + * + * @param tx - The TransactionRequest object to be converted. + * @returns A RawTransactionRequest object with all properties in string format. + */ export function toRawTransactionRequest(tx: TransactionRequest): RawTransactionRequest { const { from, to, gas, maxFeePerGas, maxPriorityFeePerGas, value, nonce, data } = tx; return { @@ -35,6 +75,14 @@ export function toRawTransactionRequest(tx: TransactionRequest): RawTransactionR }; } +/** + * Convert a raw transaction request object with its properties as hex-encoded strings into a TransactionRequest object + * with the corresponding native JavaScript types. This function is useful for decoding raw transaction requests received + * from external sources, such as APIs or user inputs, and converting them into a format suitable for further processing. + * + * @param tx - The raw transaction request object with its properties as hex-encoded strings. + * @returns A TransactionRequest object with the corresponding native JavaScript types. + */ export function fromRawTransactionRequest(tx: RawTransactionRequest): TransactionRequest { const { from, to, gas, maxFeePerGas, maxPriorityFeePerGas, value, nonce, data } = tx; return { diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_response.ts b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_response.ts index 3bce75f93b6..2598ef6d48d 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_response.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_response.ts @@ -8,46 +8,164 @@ import { numberToHex, } from '../../hex_string/index.js'; +/** + * Represents a raw Ethereum transaction response. + * Contains unprocessed data fields in hexadecimal string format, typically received from an Ethereum node API. + */ export interface RawTransactionResponse { - blockHash: string | null; - blockNumber: string | null; - from: string; - gas: string; - gasPrice: string; - maxFeePerGas?: string; - maxPriorityFeePerGas?: string; - hash: string; - input: string; - nonce: string; - to: string | null; - transactionIndex: string | null; - type: string; - value: string; - v: string; - r: string; - s: string; + /** + * The hash of the block containing the transaction. + */ +blockHash: string | null; + /** + * The block number in which the transaction is included. + */ +blockNumber: string | null; + /** + * The originating Ethereum address of the transaction. + */ +from: string; + /** + * The amount of gas required for the transaction execution. + */ +gas: string; + /** + * The price per unit of gas in the transaction. + */ +gasPrice: string; + /** + * Maximum fee per gas unit for a transaction. + */ +maxFeePerGas?: string; + /** + * The maximum fee per gas unit for transaction prioritization. + */ +maxPriorityFeePerGas?: string; + /** + * The unique identifier of the transaction. + */ +hash: string; + /** + * Raw input data of the transaction. + */ +input: string; + /** + * A unique transaction counter for the sender. + */ +nonce: string; + /** + * The destination Ethereum address involved in the transaction. + */ +to: string | null; + /** + * The index of the transaction within its containing block. + */ +transactionIndex: string | null; + /** + * The Ethereum transaction type identifier. + */ +type: string; + /** + * The amount of Ether transferred in the transaction. + */ +value: string; + /** + * The recovery identifier of the transaction signature. + */ +v: string; + /** + * The 'r' value of the transaction's ECDSA signature. + */ +r: string; + /** + * Signature component for transaction verification. + */ +s: string; } +/** + * Represents an Ethereum transaction response with decoded data types. + * Provides a structured interface for working with transaction responses returned from the Ethereum network. + */ export interface TransactionResponse { - blockHash: string | null; - blockNumber: number | null; - from: EthAddress; - gas: number; - gasPrice: bigint; - maxFeePerGas?: bigint; - maxPriorityFeePerGas?: bigint; - hash: string; - input: Buffer; - nonce: number; - to: EthAddress | null; - transactionIndex: number | null; - type: number; - value: bigint; - v: string; - r: string; - s: string; + /** + * The hash of the block containing the transaction. + */ +blockHash: string | null; + /** + * The block number containing the transaction, or null if not yet mined. + */ +blockNumber: number | null; + /** + * The originating Ethereum address of the transaction. + */ +from: EthAddress; + /** + * Amount of gas units required for executing the transaction. + */ +gas: number; + /** + * The amount of Ether paid per unit of gas for the transaction. + */ +gasPrice: bigint; + /** + * The maximum fee per gas unit for the transaction. + */ +maxFeePerGas?: bigint; + /** + * The maximum fee per gas a user is willing to pay for transaction priority. + */ +maxPriorityFeePerGas?: bigint; + /** + * The unique identifier of the transaction. + */ +hash: string; + /** + * Raw binary data representing smart contract method calls and parameters. + */ +input: Buffer; + /** + * An integer value representing the number of transactions sent by the sender. + */ +nonce: number; + /** + * The destination Ethereum address for the transaction. + */ +to: EthAddress | null; + /** + * The position of the transaction within the block. + */ +transactionIndex: number | null; + /** + * Transaction type identifier. + */ +type: number; + /** + * The value transferred in the transaction, represented as a bigint. + */ +value: bigint; + /** + * The recovery identifier of the ECDSA signature. + */ +v: string; + /** + * The 'r' value of the ECDSA signature. + */ +r: string; + /** + * Signature recovery value for ECDSA. + */ +s: string; } +/** + * Converts a raw transaction response object into a more structured and typed TransactionResponse object. + * This function decodes hex-encoded strings, converts number values to their respective types (BigInt or Number), + * and represents Ethereum addresses as EthAddress instances. It can handle both EIP-1559 and legacy transactions. + * + * @param tx - The raw transaction response object, typically retrieved from an Ethereum node API. + * @returns A structured and typed TransactionResponse object with decoded values for easier handling and manipulation. + */ export function fromRawTransactionResponse(tx: RawTransactionResponse): TransactionResponse { return { ...tx, @@ -66,6 +184,13 @@ export function fromRawTransactionResponse(tx: RawTransactionResponse): Transact }; } +/** + * Converts a TransactionResponse object into a RawTransactionResponse object by transforming its field values to their raw string or number format. + * This function is useful when dealing with APIs or systems that expect transaction data in raw string or number format. + * + * @param tx - The TransactionResponse object containing the transaction data in bigint, Buffer, or EthAddress format. + * @returns A RawTransactionResponse object containing the transaction data in raw string or number format. + */ export function toRawTransactionResponse(tx: TransactionResponse): RawTransactionResponse { return { ...tx, diff --git a/yarn-project/ethereum.js/src/eth_sign/hash_message.ts b/yarn-project/ethereum.js/src/eth_sign/hash_message.ts index dae31c0fddf..1ec74fb0cd7 100644 --- a/yarn-project/ethereum.js/src/eth_sign/hash_message.ts +++ b/yarn-project/ethereum.js/src/eth_sign/hash_message.ts @@ -1,5 +1,13 @@ import { keccak256 } from '../crypto/index.js'; +/** + * Generate a keccak256 hash of the given Ethereum message following its signed message format. + * The function adds the Ethereum Signed Message preamble and message length before hashing the data. + * This helps ensure that the data being signed cannot be misinterpreted as a transaction or other data. + * + * @param data - a Buffer containing the data to be hashed. + * @returns A Buffer containing the keccak256 hashed Ethereum message. + */ export function hashMessage(data: Buffer) { const preamble = '\x19Ethereum Signed Message:\n' + data.length; const preambleBuffer = Buffer.from(preamble); diff --git a/yarn-project/ethereum.js/src/eth_sign/sign.ts b/yarn-project/ethereum.js/src/eth_sign/sign.ts index 1326bd5e869..d105aff6790 100644 --- a/yarn-project/ethereum.js/src/eth_sign/sign.ts +++ b/yarn-project/ethereum.js/src/eth_sign/sign.ts @@ -6,30 +6,95 @@ import { hexToBuffer } from '../hex_string/index.js'; const secp256k1 = new elliptic.ec('secp256k1'); +/** + * The EthSignature class represents an Ethereum signature consisting of 'r', 's', and 'v' components. + * It provides methods to convert signatures between string, buffer, and object formats for easy manipulation + * and usage in signing and recovering operations. This class is particularly useful when working with + * Ethereum transactions that require signing and validation processes. + */ export class EthSignature { - constructor(public r: Buffer, public s: Buffer, public v: number) {} + constructor(/** + * The 'r' value of an ECDSA signature. + */ +public r: Buffer, /** + * The 's' value of the ECDSA signature. + */ +public s: Buffer, /** + * The recovery parameter used in ECDSA signatures. + */ +public v: number) {} - static fromBuffer(buf: Buffer) { + /** + * Create an EthSignature instance from a given buffer. + * The input 'buf' should be a Buffer containing the 'r', 's', and 'v' values of the signature. + * 'r' and 's' values are each 32 bytes long, while 'v' is a single byte. + * Throws an error if the input buffer length is not exactly 65 bytes. + * + * @param buf - The Buffer containing the 'r', 's', and 'v' values of the signature. + * @returns An EthSignature instance. + */ +static fromBuffer(buf: Buffer) { return new EthSignature(buf.subarray(0, 32), buf.subarray(32, 64), buf[64]); } - static fromString(hex: string) { + /** + * Create an EthSignature instance from a hex-encoded string. + * The input 'hex' should be prefixed with '0x', followed by 128 hex characters (for r, s) and 2 hex characters for the `v` value. + * Throws an error if the input length is invalid or any of the r, s, v values are out of range. + * + * @param hex - The hex-encoded string representing the Ethereum signature. + * @returns An EthSignature instance. + */ +static fromString(hex: string) { return EthSignature.fromBuffer(hexToBuffer(hex)); } - toBuffer() { + /** + * Converts the EthSignature instance to a Buffer representation. + * The resulting buffer contains the concatenated 'r', 's', and 'v' values of the signature. + * This function is useful when working with raw binary data or when storing the signature. + * + * @returns A Buffer containing the concatenated 'r', 's', and 'v' values of the EthSignature instance. + */ +toBuffer() { return Buffer.concat([this.r, this.s, numToUInt8(this.v)]); } - toString() { + /** + * Convert the EthSignature instance into a hex-encoded string. + * The resulting string is prefixed with '0x' and represents the concatenated r, s, and v values of the signature. + * + * @returns A hex-encoded string representing the EthSignature instance. + */ +toString() { return '0x' + this.toBuffer().toString('hex'); } } +/** + * Sign a message hash using the provided private key and add 27 to the recovery value. + * This function produces an Ethereum-compatible signature, which can be used for verifying + * the signer's address. It returns an EthSignature object containing the 'r', 's', and 'v' values. + * + * @param messageHash - The Buffer containing the hashed message to be signed. + * @param privateKey - The Buffer containing the private key used for signing the message hash. + * @returns An EthSignature instance with the signature components (r, s, v). + */ export function signMessage(messageHash: Buffer, privateKey: Buffer) { return sign(messageHash, privateKey, 27); } +/** + * Generate an Ethereum signature for a given message hash and private key. + * The 'sign' function takes a message hash (Buffer), a private key (Buffer), and an optional addToV parameter, + * and returns an EthSignature object containing the r, s, and v components of the signature. + * The 'addToV' parameter can be used to adjust the recovery ID of the signature (default is 0). + * + * @param messageHash - The message hash to be signed, as a Buffer. + * @param privateKey - The signer's private key, as a Buffer. + * @param addToV - Optional value to add to the recovery ID of the signature (default is 0). + * @returns An instance of EthSignature containing the r, s, and v components of the signed message. + */ export function sign(messageHash: Buffer, privateKey: Buffer, addToV = 0): EthSignature { const signature = secp256k1.keyFromPrivate(privateKey).sign(messageHash, { canonical: true }); const v = signature.recoveryParam! + addToV; @@ -38,10 +103,31 @@ export function sign(messageHash: Buffer, privateKey: Buffer, addToV = 0): EthSi return new EthSignature(r, s, v); } +/** + * Recover the Ethereum address from a signature and message hash. + * This function takes the message hash and an EthSignature object, which contains r, s, and v values, + * and returns the corresponding Ethereum address that signed the message. + * The recovered address is returned as an EthAddress instance. + * + * @param messageHash - The hash of the message that was signed. + * @param signature - An EthSignature object containing r, s, and v values. + * @returns An EthAddress instance representing the address that signed the message. + */ export function recoverFromSignature(messageHash: Buffer, { v, r, s }: EthSignature) { return recoverFromVRS(messageHash, v, r, s); } +/** + * Recover the Ethereum address from a message hash, using the provided signature parameters (v, r, s). + * The function uses elliptic curve cryptography (secp256k1) to recover the public key and then derives + * the Ethereum address by hashing the public key with keccak256. + * + * @param messageHash - The hashed message that was signed. + * @param v - The recovery identifier value, used to determine which of the two possible keys was used for signing. + * @param r - The 'r' component of the ECDSA signature. + * @param s - The 's' component of the ECDSA signature. + * @returns An EthAddress instance representing the recovered Ethereum address. + */ export function recoverFromVRS(messageHash: Buffer, v: number, r: Buffer, s: Buffer) { const ecPublicKey = secp256k1.recoverPubKey( messageHash, @@ -56,6 +142,16 @@ export function recoverFromVRS(messageHash: Buffer, v: number, r: Buffer, s: Buf return new EthAddress(publicHash.subarray(-20)); } +/** + * Recover an Ethereum address from a given message hash and signature buffer. + * This function uses the EthSignature.fromBuffer() method to convert the signature buffer into an + * EthSignature instance, then calls the recoverFromSignature() function with the message hash and + * the EthSignature instance to recover the Ethereum address. + * + * @param messageHash - The Buffer containing the hash of the message that was signed. + * @param signature - The Buffer containing the signature generated from signing the message. + * @returns An EthAddress instance representing the recovered Ethereum address. + */ export function recoverFromSigBuffer(messageHash: Buffer, signature: Buffer) { return recoverFromSignature(messageHash, EthSignature.fromBuffer(signature)); } diff --git a/yarn-project/ethereum.js/src/eth_transaction/eth_transaction.ts b/yarn-project/ethereum.js/src/eth_transaction/eth_transaction.ts index cb96703a0b8..f229731040e 100644 --- a/yarn-project/ethereum.js/src/eth_transaction/eth_transaction.ts +++ b/yarn-project/ethereum.js/src/eth_transaction/eth_transaction.ts @@ -6,12 +6,36 @@ import { EthAddress } from '@aztec/foundation'; * It's distinct from ETH JSON RPC types, which are much less strict. */ export interface EthTransaction { - chainId: number; - to?: EthAddress; - gas: number; - maxFeePerGas: bigint; - maxPriorityFeePerGas: bigint; - value: bigint; - data?: Buffer; - nonce: number; + /** + * The unique identifier for the Ethereum network. + */ +chainId: number; + /** + * The destination Ethereum address for the transaction. + */ +to?: EthAddress; + /** + * The maximum amount of gas units allocated for the execution of the transaction. + */ +gas: number; + /** + * The maximum fee per gas unit for the transaction, expressed in Gwei. + */ +maxFeePerGas: bigint; + /** + * Maximum fee per gas unit to prioritize the transaction inclusion. + */ +maxPriorityFeePerGas: bigint; + /** + * The amount of Ether to be transferred in the transaction. + */ +value: bigint; + /** + * The input data for the transaction execution. + */ +data?: Buffer; + /** + * A unique value representing the number of transactions sent from a specific address. + */ +nonce: number; } diff --git a/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts b/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts index 3e54608deb6..146b0b9d1ac 100644 --- a/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts +++ b/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts @@ -4,12 +4,36 @@ import { sign, EthSignature, recoverFromSignature } from '../eth_sign/index.js'; import { keccak256 } from '../crypto/index.js'; import { numToUInt8 } from '../serialize/index.js'; +/** + * Represents a signed Ethereum transaction object. + * Contains the signature, message hash, and raw transaction data for a valid Ethereum transaction. + */ export interface SignedEthTransaction { - signature: EthSignature; - messageHash: Buffer; - rawTransaction: Buffer; + /** + * The cryptographic signature of the transaction. + */ +signature: EthSignature; + /** + * The Keccak-256 hash of the signed transaction message. + */ +messageHash: Buffer; + /** + * The serialized raw Ethereum transaction in RLP-encoded format. + */ +rawTransaction: Buffer; } +/** + * Recover the sender's address from a raw Ethereum transaction buffer. + * This function takes in a raw transaction buffer, extracts the signature, + * and uses it to recover the Ethereum address of the sender. It works with + * EIP-1559 transactions only (transaction type 2). Throws an error if there's + * any issue during the recovery process. + * + * @param rawTx - The raw transaction buffer containing nonce, gas, max fees, + * chainId, and signature information. + * @returns An Ethereum address as Buffer representing the transaction sender. + */ export function recoverTransaction(rawTx: Buffer) { const txType = numToUInt8(rawTx[0]); // Slice off txType. @@ -61,6 +85,16 @@ export function signTransaction(tx: EthTransaction, privateKey: Buffer): SignedE }; } +/** + * Constructs a signed Ethereum transaction object from the given EthTransaction and EthSignature objects. + * This function calculates the message hash by concatenating transaction type (EIP-1559) and RLP-encoded + * transaction data, then hashing it using keccak256. The sender's address is recovered from the signature + * and message hash using the 'recoverFromSignature' function. + * + * @param tx - An EthTransaction object containing transaction details such as nonce, gas, maxFeePerGas, etc. + * @param signature - An EthSignature object containing the signature components (r, s, and v) for the transaction. + * @returns The sender's Ethereum address recovered from the given signature and transaction data. + */ export function signedTransaction(tx: EthTransaction, signature: EthSignature) { const txType = numToUInt8(0x2); diff --git a/yarn-project/ethereum.js/src/eth_typed_data/index.ts b/yarn-project/ethereum.js/src/eth_typed_data/index.ts index 883bf7bf0cd..189a68570a6 100644 --- a/yarn-project/ethereum.js/src/eth_typed_data/index.ts +++ b/yarn-project/ethereum.js/src/eth_typed_data/index.ts @@ -3,6 +3,16 @@ import { TypedData } from './typed_data.js'; export * from './typed_data.js'; +/** + * Computes the hash of the given TypedData object according to EIP-712. + * This function helps in creating a unique representation of the typed data + * which can be used for signing or verifying signatures in Ethereum transactions. + * The input 'data' should be a valid TypedData object containing types, domain, and message information. + * Throws an error if the input is not a valid TypedData object. + * + * @param data - The TypedData object to be hashed. + * @returns A string representing the hash of the typed data. + */ export function getTypedDataHash(data: TypedData) { return getMessage(data, true); } diff --git a/yarn-project/ethereum.js/src/eth_typed_data/typed_data.ts b/yarn-project/ethereum.js/src/eth_typed_data/typed_data.ts index 95907f8dfc3..bc38fb76f3f 100644 --- a/yarn-project/ethereum.js/src/eth_typed_data/typed_data.ts +++ b/yarn-project/ethereum.js/src/eth_typed_data/typed_data.ts @@ -1,11 +1,46 @@ +/** + * Represents the typed data structure used in EIP-712 for signing messages. + * Provides a consistent format to create domain, message types and message values + * that can be encoded and signed, improving security and user experience in blockchain transactions. + */ export interface TypedData { - domain: { - name: string; - version: string; - chainId: number; - verifyingContract: string; + /** + * Represents EIP-712 domain data containing application-specific information for signing typed data. + */ +domain: { + /** + * The identifying name of the domain. + */ +name: string; + /** + * Version identifier for the domain. + */ +version: string; + /** + * The unique identifier of the blockchain network. + */ +chainId: number; + /** + * The address of the contract responsible for data verification. + */ +verifyingContract: string; }; - types: { [key: string]: { name: string; type: string }[] }; - message: any; - primaryType: string; + /** + * An object containing structured data types for EIP-712 signing. + */ +types: { [key: string]: { /** + * The name of the domain in which the TypedData is structured. + */ +name: string; /** + * A mapping of data types with their corresponding properties, including name and type. + */ +type: string }[] }; + /** + * The specific structured data to be signed and verified. + */ +message: any; + /** + * The main type used for structuring and verifying the EIP-712 typed data. + */ +primaryType: string; } diff --git a/yarn-project/ethereum.js/src/eth_wallet/eth_wallet.ts b/yarn-project/ethereum.js/src/eth_wallet/eth_wallet.ts index 09270c2ee94..7957049ccfe 100644 --- a/yarn-project/ethereum.js/src/eth_wallet/eth_wallet.ts +++ b/yarn-project/ethereum.js/src/eth_wallet/eth_wallet.ts @@ -2,15 +2,36 @@ import { EthAccount } from '../eth_account/index.js'; import { EthAddress } from '@aztec/foundation'; import { decryptFromKeyStoreJson, KeyStoreEncryptOptions, KeyStoreJson } from '../keystore/index.js'; +/** + * The EthWallet class represents an Ethereum wallet consisting of multiple Ethereum accounts. + * It provides methods for creating and managing accounts, importing wallets from mnemonics, seeds, and keystores, + * as well as encrypting and decrypting wallets. The class supports account addition, removal, retrieval, + * and management of the wallet's length and index pointers. + */ export class EthWallet { - public length = 0; - public accounts: EthAccount[] = []; + /** + * The total number of accounts stored in the wallet. + */ +public length = 0; + /** + * Array containing Ethereum accounts in the wallet. + */ +public accounts: EthAccount[] = []; constructor(numberOfAccounts = 0) { this.create(numberOfAccounts); } - public static fromMnemonic(mnemonic: string, numberOfAccounts: number) { + /** + * Create an EthWallet instance from a mnemonic string for the specified number of accounts. + * The mnemonic should be a BIP-39 compliant seed phrase containing a series of words, used for generating deterministic keys. + * This function generates EthAccounts based on the given mnemonic and adds them to the wallet. + * + * @param mnemonic - The BIP-39 compliant seed phrase as a string. + * @param numberOfAccounts - The number of accounts to generate and add to the wallet. + * @returns An EthWallet instance containing the generated accounts. + */ +public static fromMnemonic(mnemonic: string, numberOfAccounts: number) { const wallet = new EthWallet(); for (let i = 0; i < numberOfAccounts; ++i) { const path = `m/44'/60'/0'/0/${i}`; @@ -19,7 +40,16 @@ export class EthWallet { return wallet; } - public static fromSeed(seed: Buffer, numberOfAccounts: number) { + /** + * Create an EthWallet instance from a provided seed Buffer and number of accounts. + * The function generates the specified number of EthAccounts using the seed and + * BIP44 derivation path, then adds them to the newly created EthWallet. + * + * @param seed - A Buffer containing the seed for generating the HD wallet. + * @param numberOfAccounts - The number of EthAccounts to generate using the seed. + * @returns An EthWallet instance containing the generated EthAccounts. + */ +public static fromSeed(seed: Buffer, numberOfAccounts: number) { const wallet = new EthWallet(); for (let i = 0; i < numberOfAccounts; ++i) { const path = `m/44'/60'/0'/0/${i}`; @@ -28,42 +58,98 @@ export class EthWallet { return wallet; } - public static async fromKeystores(keyStores: KeyStoreJson[], password: string) { + /** + * Create an EthWallet instance from an array of KeyStoreJson objects. + * Decrypts each keystore using the provided password, adds the accounts to the wallet, + * and returns the wallet with decrypted accounts. Throws an error if decryption fails + * due to an incorrect password or other issues. + * + * @param keyStores - An array of KeyStoreJson objects representing encrypted Ethereum accounts. + * @param password - The password used for decrypting the keystores. + * @returns A Promise that resolves to an EthWallet instance with decrypted accounts. + */ +public static async fromKeystores(keyStores: KeyStoreJson[], password: string) { const wallet = new EthWallet(); await wallet.decrypt(keyStores, password); return wallet; } - public create(numberOfAccounts: number, entropy?: Buffer): EthAccount[] { + /** + * Create a specified number of Ethereum accounts and add them to the wallet. + * Generates new Ethereum accounts using an optional entropy buffer for randomness. + * Returns an array of the created EthAccount instances. + * + * @param numberOfAccounts - The number of accounts to create. + * @param entropy - Optional buffer containing entropy bytes for creating accounts. + * @returns An array of created EthAccount instances. + */ +public create(numberOfAccounts: number, entropy?: Buffer): EthAccount[] { for (let i = 0; i < numberOfAccounts; ++i) { this.add(EthAccount.create(entropy).privateKey); } return this.accounts; } - public getAccount(addressOrIndex: EthAddress | number) { + /** + * Retrieve an EthAccount instance from the wallet using either an Ethereum address or a numeric index. + * The function searches for an account based on the provided input and returns it if found. + * If multiple accounts are present, use the address or index to specify a unique account. + * + * @param addressOrIndex - An EthAddress instance or a number representing the account's index in the wallet. + * @returns The EthAccount instance corresponding to the provided address or index, or undefined if not found. + */ +public getAccount(addressOrIndex: EthAddress | number) { if (addressOrIndex instanceof EthAddress) { return this.accounts.find(a => a && a.address.equals(addressOrIndex)); } return this.accounts[addressOrIndex]; } - public getAccountIndex(addressOrIndex: EthAddress | number) { + /** + * Retrieve the index of an account in the wallet based on the provided address or index. + * If the input is an EthAddress, this function searches for an account with a matching address and returns its index. + * If the input is a number, it directly returns the input number as the index. Returns -1 if no matching account is found. + * + * @param addressOrIndex - An EthAddress object representing the Ethereum address or a number representing the account index. + * @returns The index of the account within the wallet or -1 if not found. + */ +public getAccountIndex(addressOrIndex: EthAddress | number) { if (addressOrIndex instanceof EthAddress) { return this.accounts.findIndex(a => a && a.address.equals(addressOrIndex)); } return addressOrIndex; } - public getAccountIndicies() { + /** + * Get an array of the indices of all EthAccounts stored in the wallet. + * The returned indices can be used to access EthAccount instances through the 'getAccount' function. + * + * @returns An array of integers representing the indices of the EthAccounts in the wallet. + */ +public getAccountIndicies() { return Object.keys(this.accounts).map(key => +key); } - public getAccountAddresses() { + /** + * Retrieve the Ethereum addresses of all accounts in the wallet. + * This function maps the accounts to their corresponding addresses + * and returns an array of EthAddress instances. + * + * @returns An array of EthAddress instances representing the Ethereum addresses of the accounts in the wallet. + */ +public getAccountAddresses() { return this.accounts.map(account => account.address); } - public add(accountOrKey: Buffer | EthAccount): EthAccount { + /** + * Add an EthAccount instance or a private key to the wallet. + * If an account with the same address already exists in the wallet, it returns the existing account. + * Otherwise, it adds the new account at a safe index and increments the wallet length. + * + * @param accountOrKey - An EthAccount instance or a Buffer containing the private key. + * @returns The added or existing EthAccount instance. + */ +public add(accountOrKey: Buffer | EthAccount): EthAccount { const account = Buffer.isBuffer(accountOrKey) ? new EthAccount(accountOrKey) : accountOrKey; const existing = this.getAccount(account.address); @@ -78,7 +164,15 @@ export class EthWallet { return account; } - public remove(addressOrIndex: number | EthAddress) { + /** + * Removes an account from the wallet based on the provided address or index. + * If the given address or index matches one of the existing accounts in the wallet, the account will be removed, + * and the function returns true. If the address or index is not found in the wallet, the function returns false. + * + * @param addressOrIndex - The EthAddress or index number of the account to be removed from the wallet. + * @returns A boolean value indicating whether the removal was successful. + */ +public remove(addressOrIndex: number | EthAddress) { const index = this.getAccountIndex(addressOrIndex); if (index === -1) { @@ -91,16 +185,37 @@ export class EthWallet { return true; } - public clear() { + /** + * Clears all the accounts stored in the EthWallet instance. + * The length of EthWallet will be set to 0 and the accounts array will become empty. + */ +public clear() { this.accounts = []; this.length = 0; } - public encrypt(password: string, options?: KeyStoreEncryptOptions) { + /** + * Encrypts the account private keys in the wallet using the provided password and returns an array of KeyStoreJson objects. + * The KeyStoreJson objects follow the Ethereum keystore format (UTC / JSON) standard and can be later used to decrypt the accounts. + * The optional 'options' parameter allows customizing the encryption process, such as the number of iterations or salt. + * + * @param password - The user-defined password to use for encrypting the account private keys. + * @param options - Optional KeyStoreEncryptOptions object for customizing the encryption process. + * @returns A Promise that resolves to an array of encrypted KeyStoreJson objects. + */ +public encrypt(password: string, options?: KeyStoreEncryptOptions) { return Promise.all(this.getAccountIndicies().map(index => this.accounts[index].toKeyStoreJson(password, options))); } - public async decrypt(encryptedWallet: KeyStoreJson[], password: string) { + /** + * Decrypts an array of KeyStoreJson objects using the provided password and adds the decrypted accounts to the wallet. + * If any of the accounts cannot be decrypted, it will throw an error with a message indicating that the password might be wrong. + * + * @param encryptedWallet - Array of KeyStoreJson objects representing the encrypted wallet. + * @param password - The password used to decrypt the encrypted wallet. + * @returns An array of EthAccount instances stored in the wallet after successful decryption. + */ +public async decrypt(encryptedWallet: KeyStoreJson[], password: string) { const decrypted = await Promise.all(encryptedWallet.map(keystore => decryptFromKeyStoreJson(keystore, password))); decrypted.forEach(account => { if (!account) { @@ -113,7 +228,14 @@ export class EthWallet { return this.accounts; } - private findSafeIndex(pointer = 0) { + /** + * Find an available index to safely add a new account in the accounts array. + * The method iterates through the accounts array, incrementing the pointer until it finds an empty position. + * + * @param pointer - Optional starting index for the search. Default value is 0. + * @returns The index of the first empty position in the accounts array. + */ +private findSafeIndex(pointer = 0) { while (this.accounts[pointer]) { ++pointer; } diff --git a/yarn-project/ethereum.js/src/hex_string/index.ts b/yarn-project/ethereum.js/src/hex_string/index.ts index 427291da15e..bf58b73419c 100644 --- a/yarn-project/ethereum.js/src/hex_string/index.ts +++ b/yarn-project/ethereum.js/src/hex_string/index.ts @@ -1,23 +1,70 @@ +/** + * Convert a buffer to a hex-encoded string with a '0x' prefix. + * The conversion is done by first converting the buffer data to a hexadecimal string + * and then appending the '0x' prefix to it. This function can be used to convert + * binary data into a human-readable format that can be easily manipulated or displayed. + * + * @param b - The buffer object containing the binary data to be converted. + * @returns A hex-encoded string with a '0x' prefix representing the input buffer data. + */ export function bufferToHex(b: Buffer) { return '0x' + b.toString('hex'); } +/** + * Converts a hex-encoded string to a Buffer object. + * The input 'h' can be prefixed with '0x' or not, and may have an odd or even number of hex characters. + * If the input length is odd, a leading '0' will be added before conversion. + * + * @param h - The hex-encoded string to be converted to a Buffer. + * @returns A Buffer object representing the input hex-encoded string. + */ export function hexToBuffer(h: string) { return Buffer.from((h.length % 2 ? '0' : '') + h.replace(/^0x/, ''), 'hex'); } +/** + * Convert a given number to its hexadecimal representation as a string. + * The output hex string will be prefixed with '0x'. + * + * @param n - The number to be converted to hex. + * @returns The hexadecimal representation of the input number as a string. + */ export function numberToHex(n: number) { return '0x' + n.toString(16); } +/** + * Convert a hex-encoded string to its equivalent number representation. + * The input 'h' should be prefixed with '0x' or not, and consist of valid hex characters. + * Note that the result might lose precision for large hex values due to JavaScript's number limitations. + * + * @param h - The hex-encoded string to convert to a number. + * @returns The numeric representation of the input hex string. + */ export function hexToNumber(h: string) { return Number(h); } +/** + * Converts a BigInt value to its corresponding hexadecimal representation. + * The output string will be prefixed with '0x' to indicate hexadecimal notation. + * + * @param n - The BigInt value to be converted to hexadecimal. + * @returns The hexadecimal representation of the input BigInt value as a string. + */ export function bigIntToHex(n: bigint) { return '0x' + n.toString(16); } +/** + * Convert a hex-encoded string to a BigInt. + * The input 'h' can be prefixed with '0x' or not, and it should have an even number of hex characters. + * If the input is not valid, this function will throw a RangeError. + * + * @param h - The hex-encoded string representing the input value. + * @returns A BigInt representation of the input hex value. + */ export function hexToBigInt(h: string) { return BigInt(h); } diff --git a/yarn-project/ethereum.js/src/keystore/index.test.ts b/yarn-project/ethereum.js/src/keystore/index.test.ts index 793575b38c6..e0d5a759016 100644 --- a/yarn-project/ethereum.js/src/keystore/index.test.ts +++ b/yarn-project/ethereum.js/src/keystore/index.test.ts @@ -1,7 +1,16 @@ import { decryptFromKeyStoreJson, encryptToKeyStoreJson, KeyStoreJson } from './index.js'; import { EthAddress } from '@aztec/foundation'; -const staticTests: { json: KeyStoreJson; password: string; priv: string }[] = [ +const staticTests: { /** + * A JSON representation of the encrypted key store for an Ethereum account. + */ +json: KeyStoreJson; /** + * The password used to encrypt and decrypt the keystore file. + */ +password: string; /** + * The private key associated with the Ethereum address. + */ +priv: string }[] = [ { json: { crypto: { diff --git a/yarn-project/ethereum.js/src/keystore/index.ts b/yarn-project/ethereum.js/src/keystore/index.ts index d0478057874..cfc230042bf 100644 --- a/yarn-project/ethereum.js/src/keystore/index.ts +++ b/yarn-project/ethereum.js/src/keystore/index.ts @@ -3,37 +3,119 @@ import { v4 } from 'uuid'; import { EthAddress } from '@aztec/foundation'; import { pbkdf2, scrypt, keccak256, randomBytes } from '../crypto/index.js'; +/** + * Represents the Scrypt key derivation function parameters. + * Provides a set of properties required for deriving cryptographic keys using the Scrypt algorithm. + */ interface ScryptKdfParams { - dklen: number; - n: number; - p: number; - r: number; - salt: string; + /** + * The desired output key length in bytes. + */ +dklen: number; + /** + * The cost factor for scrypt key derivation function. + */ +n: number; + /** + * The parallelization factor for the scrypt key derivation function. + */ +p: number; + /** + * The CPU/memory cost factor for scrypt key derivation. + */ +r: number; + /** + * A cryptographic element used to enhance password security. + */ +salt: string; } +/** + * Represents the PBKDF2 key derivation function parameters. + * Provides the necessary information and options for the PBKDF2 algorithm to derive a cryptographic key from a password. + */ interface PbKdf2Params { - dklen: number; - c: number; - prf: string; - salt: string; + /** + * The desired length of the derived key in bytes. + */ +dklen: number; + /** + * The iteration count for the PBKDF2 key derivation function. + */ +c: number; + /** + * Pseudorandom function (PRF) used for key derivation. + */ +prf: string; + /** + * A random sequence of bytes used as an additional input for the key derivation function. + */ +salt: string; } +/** + * Represents a keystore object in JSON format. + * Contains necessary information required to encrypt and decrypt private keys using a user-provided password. + */ export interface KeyStoreJson { - address?: string; - crypto: { - cipher: string; - ciphertext: string; - cipherparams: { - iv: string; + /** + * Ethereum address associated with the keystore. + */ +address?: string; + /** + * Cryptographic configurations and encrypted data. + */ +crypto: { + /** + * The encryption algorithm used to secure the private key. + */ +cipher: string; + /** + * The encrypted private key in hexadecimal format. + */ +ciphertext: string; + /** + * Parameters required for cipher initialization. + */ +cipherparams: { + /** + * Initialization vector for the cipher algorithm. + */ +iv: string; }; - kdf: string; - kdfparams: ScryptKdfParams | PbKdf2Params; - mac: string; + /** + * Key derivation function used for encryption. + */ +kdf: string; + /** + * Key derivation function parameters for password-based key generation. + */ +kdfparams: ScryptKdfParams | PbKdf2Params; + /** + * Message authentication code generated from encrypted data. + */ +mac: string; }; - id: string; - version: number; + /** + * Unique identifier for the keystore object. + */ +id: string; + /** + * The version of the key store format. + */ +version: number; } +/** + * Decrypt a private key from a V3 keystore JSON object using the provided password. + * Supports 'scrypt' and 'pbkdf2' key derivation functions. Throws an error if the + * password is incorrect, keystore format is invalid, or unsupported key derivation + * or cipher schemes are used. + * + * @param v3Keystore - The V3 keystore JSON object containing encrypted private key information. + * @param password - The password used for encryption/decryption of the private key. + * @returns A Promise that resolves to the decrypted private key as a Buffer. + */ export async function decryptFromKeyStoreJson(v3Keystore: KeyStoreJson, password: string): Promise { if (!password.length) { throw new Error('No password given.'); @@ -77,19 +159,66 @@ export async function decryptFromKeyStoreJson(v3Keystore: KeyStoreJson, password return Buffer.concat([decipher.update(ciphertext), decipher.final()]); } +/** + * Represents the encryption options for a KeyStore JSON file. + * Provides optional parameters to customize the encryption process, such as cipher algorithm, salt, iv, kdf, and other related attributes. + */ export interface KeyStoreEncryptOptions { - cipher?: string; - salt?: Buffer; - iv?: Buffer; - kdf?: 'scrypt' | 'pbkdf2'; - id?: string; - c?: number; - dklen?: number; - n?: number; - r?: number; - p?: number; + /** + * Cipher algorithm used for encryption. + */ +cipher?: string; + /** + * A random value used to ensure unique derived encryption keys. + */ +salt?: Buffer; + /** + * Initialization Vector for the AES cipher. + */ +iv?: Buffer; + /** + * Key derivation function used for encryption/decryption. + */ +kdf?: 'scrypt' | 'pbkdf2'; + /** + * Unique identifier for the key store. + */ +id?: string; + /** + * The iteration count for the PBKDF2 key derivation function. + */ +c?: number; + /** + * Length of the derived key in bytes. + */ +dklen?: number; + /** + * The cost factor determining the CPU/memory complexity of the scrypt key derivation function. + */ +n?: number; + /** + * The scrypt memory cost factor. + */ +r?: number; + /** + * The parallelization factor for the scrypt key derivation function. + */ +p?: number; } +/** + * Encrypts a private key to a KeyStore JSON object using the specified password and encryption options. + * The resulting KeyStore JSON can be used to securely store the private key, and later decrypt it with the same password. + * Supports 'scrypt' and 'pbkdf2' key derivation functions (KDF) for generating the derived key. + * Uses AES-128-CTR cipher algorithm for encrypting the private key. + * Throws an error if unsupported cipher or KDF is provided. + * + * @param privateKey - The private key Buffer to be encrypted. + * @param address - The EthAddress associated with the privateKey. + * @param password - The password string used for encryption. + * @param options - Optional configuration settings for the encryption process. + * @returns A Promise resolving to a KeyStoreJson object containing the encrypted private key and related information. + */ export async function encryptToKeyStoreJson( privateKey: Buffer, address: EthAddress, diff --git a/yarn-project/ethereum.js/src/log/console.ts b/yarn-project/ethereum.js/src/log/console.ts index 6315a10e0e7..6bd6a0b70f2 100644 --- a/yarn-project/ethereum.js/src/log/console.ts +++ b/yarn-project/ethereum.js/src/log/console.ts @@ -1,13 +1,36 @@ +/** + * Type for logging functions that accept any number of arguments. + */ export type Logger = (...args: any[]) => void; +/** + * ConsoleLogger is a utility class for formatting and logging messages with a specified prefix. + * It provides a simple interface for directing log messages to a custom logger function (defaults to console.log). + * The 'log' method allows logging of multiple arguments while prepending the configured prefix to the log message. + */ class ConsoleLogger { constructor(private prefix: string, private logger: (...args: any[]) => void = console.log) {} - public log(...args: any[]) { + /** + * Logs a message with a prefixed string to the console. + * The log function takes any number of arguments that are passed to the logger function. + * The prefixed string is set during object instantiation and helps in differentiating the logs. + * + * @param args - Any number of arguments to be logged in the console. + */ +public log(...args: any[]) { this.logger(`${this.prefix}:`, ...args); } } +/** + * Create a Logger instance with an optional prefix string. + * If a prefix is provided, the logger will output messages with the format "prefix: message". + * Otherwise, it will use the default 'console.log' as the logger function. + * + * @param prefix - The optional string to prepend to log messages. + * @returns A Logger instance with the specified prefix. + */ export function createLogger(prefix: string): Logger { if (prefix) { const logger = new ConsoleLogger(prefix, console.log); diff --git a/yarn-project/ethereum.js/src/log/debug.ts b/yarn-project/ethereum.js/src/log/debug.ts index 812554cb762..053dee38e39 100644 --- a/yarn-project/ethereum.js/src/log/debug.ts +++ b/yarn-project/ethereum.js/src/log/debug.ts @@ -3,6 +3,16 @@ import debug from 'debug'; let preLogHook: ((...args: any[]) => void) | undefined; let postLogHook: ((...args: any[]) => void) | undefined; +/** + * The function that serves as a central hub through which all logs pass. + * It first checks if the log is enabled for the given logger's namespace, + * then calls the preLogHook (if any) with the logger's namespace and the provided arguments, + * followed by the actual logger function, and finally calls the postLogHook (if any) with the + * logger's namespace and the provided arguments. + * + * @param logger - The debug logger instance associated with a specific namespace. + * @param args - The arguments to be passed to the logger and hooks. + */ function theFunctionThroughWhichAllLogsPass(logger: any, ...args: any[]) { if (!debug.enabled(logger.namespace)) { return; @@ -16,23 +26,62 @@ function theFunctionThroughWhichAllLogsPass(logger: any, ...args: any[]) { } } +/** + * Creates a debug logger with the specified namespace. + * The returned logger function will only log messages if its namespace is enabled. + * Additionally, it passes the log messages through pre and post log hooks if they are set. + * + * @param name - The namespace for the debug logger. + * @returns A debug logger function with the given namespace. + */ export function createDebugLogger(name: string): any { const logger = debug(name); return (...args: any[]) => theFunctionThroughWhichAllLogsPass(logger, ...args); } +/** + * Set a hook function to be called before each log output by the debug logger. + * The provided function will be invoked with the logger namespace and log arguments. + * This can be useful for additional processing or filtering of logs before they are output. + * + * @param fn - The function to be called before logging. Receives the logger namespace and log arguments as parameters. + */ export function setPreDebugLogHook(fn: (...args: any[]) => void) { preLogHook = fn; } +/** + * Sets a post-debug log hook function that will be called after each log message. + * The function provided should accept any number of arguments, with the first argument being the logger's namespace, + * followed by the original log message arguments. This hook can be used to perform additional actions such as + * formatting, filtering or redirecting log messages. + * + * @param fn - The function to be called after each log message. + */ export function setPostDebugLogHook(fn: (...args: any[]) => void) { postLogHook = fn; } +/** + * Enable debug logs for specified namespaces. + * The input 'str' should be a comma-separated list of namespaces to enable logs. + * Wildcards (*) can be used to enable logs for multiple namespaces at once. + * For example, 'foo*,bar*' will enable logs for all namespaces starting with foo and bar. + * + * @param str - The string containing comma-separated namespaces or wildcard patterns. + */ export function enableLogs(str: string) { debug.enable(str); } +/** + * Checks whether logs for the specified namespace are enabled. + * The input 'str' should be a string representing the namespace, + * as defined during the creation of the debug logger. + * + * @param str - The namespace string to check if logs are enabled. + * @returns A boolean indicating whether logs are enabled for the specified namespace. + */ export function isLogEnabled(str: string) { return debug.enabled(str); } diff --git a/yarn-project/ethereum.js/src/provider/ethereum_provider.ts b/yarn-project/ethereum.js/src/provider/ethereum_provider.ts index c2326728928..eb6264e15d0 100644 --- a/yarn-project/ethereum.js/src/provider/ethereum_provider.ts +++ b/yarn-project/ethereum.js/src/provider/ethereum_provider.ts @@ -6,26 +6,71 @@ export enum ProviderError { CHAIN_DISCONNECTED = 4901, } +/** + * Represents a standardized message format for communication between Ethereum providers and applications. + * Contains type information to identify the purpose of the message and data payload for further processing. + */ export interface ProviderMessage { - readonly type: string; - readonly data: unknown; + /** + * The type of provider notification event. + */ +readonly type: string; + /** + * Arbitrary data associated with the provider message. + */ +readonly data: unknown; } +/** + * Represents the arguments for an Ethereum RPC request. + * Provides the necessary method and optional parameters to form a well-structured request to interact with the Ethereum network. + */ export interface RequestArguments { - readonly method: string; - readonly params?: any[]; + /** + * The JSON-RPC method to be called. + */ +readonly method: string; + /** + * An optional array of method-specific parameters. + */ +readonly params?: any[]; } +/** + * Represents an error encountered during Provider's RPC communication. + * It extends the native Error object and includes additional properties + * such as error code and data, providing more context about the occurred error. + */ export interface ProviderRpcError extends Error { - message: string; - code: ProviderError | number; - data?: unknown; + /** + * Represents a provider-specific message, typically used for communicating events or updates. + */ +message: string; + /** + * The error code representing the type of provider error. + */ +code: ProviderError | number; + /** + * An arbitrary data payload related to the corresponding provider event or error. + */ +data?: unknown; } +/** + * Represents the connection information for an Ethereum provider. + * Provides details such as the chain ID to ensure compatibility and connectivity with the desired blockchain network. + */ export interface ProviderConnectInfo { - readonly chainId: string; + /** + * The unique identifier for the connected blockchain network. + */ +readonly chainId: string; } +/** + * Type representing the different types of notifications that an EthereumProvider can emit. + * These notifications are related to events such as connection, disconnection, chain and account changes, and incoming messages. + */ export type EthereumProviderNotifications = 'connect' | 'disconnect' | 'chainChanged' | 'accountsChanged' | 'message'; /** diff --git a/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts b/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts index 2152357dd96..b1f025019c5 100644 --- a/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts +++ b/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts @@ -4,12 +4,28 @@ import { createDebugLogger } from '../log/index.js'; const log = createDebugLogger('json_rpc_provider'); +/** + * The JsonRpcProvider class implements EthereumProvider to facilitate communication with Ethereum nodes. + * It provides a request/response API using JSON-RPC 2.0 protocol, handling requests for blockchain data and network state. + * This class does not support event subscriptions and will throw errors if event-related methods are called. + * Uses fetch to perform HTTP POST requests and can be configured to automatically retry failed requests. + */ export class JsonRpcProvider implements EthereumProvider { private id = 0; constructor(private host: string, private netMustSucceed = true) {} - public async request({ method, params }: RequestArguments): Promise { + /** + * Sends a JSON-RPC request to the Ethereum provider with the given method and parameters. + * The 'method' should be a valid Ethereum JSON-RPC method, and 'params' should be an array of inputs required for that method. + * Returns a promise which resolves to the result of the request, or rejects with an error if the request fails. + * + * @param {RequestArguments} requestArguments - An object containing 'method' and 'params' properties. + * @param {string} requestArguments.method - The Ethereum JSON-RPC method to call. + * @param {Array} requestArguments.params - The parameters required for the called method. + * @returns {Promise} A promise resolving to the result of the request, or rejecting with an error if the request fails. + */ +public async request({ method, params }: RequestArguments): Promise { const body = { jsonrpc: '2.0', id: this.id++, @@ -25,15 +41,38 @@ export class JsonRpcProvider implements EthereumProvider { return res.result; } - on(): this { + /** + * Registers an event listener for the specified event on the JsonRpcProvider instance. + * This method is not supported in the current implementation and will throw an error when called. + * + * @throws {Error} An error indicating that events are not supported by the JsonRpcProvider. + * @returns {this} The current JsonRpcProvider instance. + */ +on(): this { throw new Error('Events not supported.'); } - removeListener(): this { + /** + * Remove an event listener from the Ethereum provider. This method is not supported by JsonRpcProvider + * and will throw an error when called. To use event handling, consider using a different provider implementation. + * + * @throws {Error} Throws an error indicating that events are not supported by this provider. + * @returns {this} Returns the current instance of the class for chaining purposes. + */ +removeListener(): this { throw new Error('Events not supported.'); } - private async fetch(body: any) { + /** + * Send a JSON-RPC request to the Ethereum node and return the parsed response. + * The 'body' parameter contains the JSON-RPC request payload, including method, id, and params. + * If 'netMustSucceed' is true, the function will be retried until the request succeeds. + * Throws an error if the response status is not ok or if the response body cannot be parsed as JSON. + * + * @param body - The JSON-RPC request payload containing the method, id, and params. + * @returns A Promise resolving to the parsed JSON-RPC response object. + */ +private async fetch(body: any) { const fn = async () => { const resp = await fetch(this.host, { method: 'POST', diff --git a/yarn-project/ethereum.js/src/provider/wallet_provider.ts b/yarn-project/ethereum.js/src/provider/wallet_provider.ts index f8c96abf6d3..5f20d02d96a 100644 --- a/yarn-project/ethereum.js/src/provider/wallet_provider.ts +++ b/yarn-project/ethereum.js/src/provider/wallet_provider.ts @@ -20,47 +20,130 @@ import { getTypedDataHash } from '../eth_typed_data/index.js'; export class WalletProvider implements EthereumProvider { constructor(private provider: EthereumProvider, private wallet = new EthWallet()) {} - public static fromHost(ethereumHost: string, wallet = new EthWallet()) { + /** + * Create a WalletProvider instance using the given Ethereum host and an optional EthWallet instance. + * This function initializes a JsonRpcProvider with the provided Ethereum host and then + * creates a WalletProvider using the initialized JsonRpcProvider and the provided wallet. + * If no wallet is provided, a new EthWallet instance will be created. + * + * @param ethereumHost - The Ethereum host URL used to initialize the JsonRpcProvider. + * @param wallet - (Optional) An EthWallet instance to be used as the local wallet. + * @returns A WalletProvider instance with the initialized JsonRpcProvider and the given wallet. + */ +public static fromHost(ethereumHost: string, wallet = new EthWallet()) { const provider = new JsonRpcProvider(ethereumHost); return new WalletProvider(provider, wallet); } - public addAccount(privateKey: Buffer) { + /** + * Adds an account to the wallet using a private key. + * The input 'privateKey' should be a Buffer containing the private key bytes of the account. + * Returns the corresponding EthAddress of the added account. + * + * @param privateKey - The Buffer containing the private key bytes of the account. + * @returns An EthAddress instance. + */ +public addAccount(privateKey: Buffer) { return this.wallet.add(privateKey).address; } - public addAccountsFromMnemonic(mnemonic: string, num: number, bip32Account = 0) { + /** + * Add multiple accounts to the wallet using a mnemonic phrase and the specified number of accounts. + * The accounts will be generated based on the provided BIP32 account index and indexed from 0 to (num-1). + * This function is useful for importing a set of accounts that were derived from a single mnemonic. + * + * @param mnemonic - The mnemonic phrase used to generate the accounts. + * @param num - The number of accounts to add to the wallet. + * @param bip32Account - The BIP32 account index to derive the accounts from, default is 0. + */ +public addAccountsFromMnemonic(mnemonic: string, num: number, bip32Account = 0) { for (let i = 0; i < num; ++i) { this.addAccountFromMnemonicAndPath(mnemonic, `m/44'/60'/${bip32Account}'/0/${i}`); } } - public addAccountFromMnemonicAndPath(mnemonic: string, path: string) { + /** + * Adds an account to the wallet using a mnemonic and a specified BIP32 derivation path. + * The generated account is derived from the given mnemonic using the provided path, + * following the BIP32 hierarchical deterministic key generation standard. + * Returns the Ethereum address of the added account. + * + * @param mnemonic - The seed phrase used to generate the private key for the account. + * @param path - The BIP32 derivation path used to derive the account from the mnemonic. + * @returns The Ethereum address of the added account. + */ +public addAccountFromMnemonicAndPath(mnemonic: string, path: string) { return this.wallet.add(EthAccount.fromMnemonicAndPath(mnemonic, path)).address; } - public async addAccountFromKeystore(file: string, password = '') { + /** + * Adds an account to the wallet provider by loading a keystore file and decrypting the private key using the provided password. + * The keystore file should follow the JSON format defined in Ethereum Improvement Proposal 55 (EIP-55). + * Throws an error if the input file is invalid or decryption fails due to incorrect password. + * + * @param file - The path to the keystore file containing the encrypted private key. + * @param password - The password used for decryption of the keystore file (default: ''). + * @returns An EthAddress instance representing the address of the added account. + */ +public async addAccountFromKeystore(file: string, password = '') { const json = JSON.parse(await readFile(file, { encoding: 'ascii' })); return this.wallet.add(await EthAccount.fromKeyStoreJson(json, password)).address; } - public getAccounts() { + /** + * Retrieve all available accounts in the wallet. + * This function returns an array of EthAddress instances corresponding to each account in the wallet. + * If no accounts have been added, it returns an empty array. + * + * @returns An array of EthAddress instances representing the accounts in the wallet. + */ +public getAccounts() { return this.wallet.getAccountAddresses(); } - public getAccount(account: number) { + /** + * Retrieve the EthAddress instance of an account at a specific index within the wallet. + * Returns `undefined` if the provided index is out of range or does not correspond to an existing account. + * + * @param account - The index (integer) of the account to be fetched from the wallet. + * @returns The EthAddress instance corresponding to the account, or `undefined` if not found. + */ +public getAccount(account: number) { return this.wallet.getAccount(account)?.address; } - public getPrivateKey(account: number) { + /** + * Retrieve the private key associated with the specified account index. + * Returns the private key as a Buffer if the account exists in the wallet, otherwise returns undefined. + * + * @param account - The index of the account whose private key is to be retrieved. + * @returns The private key as a Buffer, or undefined if the account does not exist. + */ +public getPrivateKey(account: number) { return this.wallet.getAccount(account)?.privateKey; } - public getPrivateKeyForAddress(account: EthAddress) { + /** + * Retrieves the private key associated with the given Ethereum address. + * Returns the private key as a Buffer if found within the wallet, or undefined otherwise. + * + * @param account - The EthAddress instance representing the Ethereum address to lookup. + * @returns The private key as a Buffer or undefined if not found in the wallet. + */ +public getPrivateKeyForAddress(account: EthAddress) { return this.wallet.getAccount(account)?.privateKey; } - public async request(args: RequestArguments): Promise { + /** + * Handles the processing of various Ethereum JSON-RPC requests, delegating them to the appropriate internal methods. + * If a local account is available for signing transactions or messages, it will be used, otherwise the request + * is forwarded to the underlying provider for further processing. This allows adding and managing local accounts + * while still interacting with external providers such as remote nodes or browser-based wallets like MetaMask. + * + * @param args - The RequestArguments object containing the method to be called and any necessary parameters. + * @returns A Promise resolving to the result of the requested operation or an error if the operation fails. + */ +public async request(args: RequestArguments): Promise { switch (args.method) { case 'eth_accounts': return this.wallet.length ? this.getAccounts().map(a => a.toString()) : await this.provider.request(args); @@ -107,7 +190,16 @@ export class WalletProvider implements EthereumProvider { return await this.provider.request(args); } - private async signTypedData(args: RequestArguments) { + /** + * Sign the provided typed data using an account's private key. + * This method is used for EIP-712 compliant signing of structured data. + * The signed digest can be used to verify the signer's identity and authenticity of the data. + * + * @param args - RequestArguments object containing the method name and input parameters. + * @returns A Promise that resolves to a string representing the signature of the typed data. + * @throws An error if the specified account is not found in the wallet or if the request to the provider fails. + */ +private async signTypedData(args: RequestArguments) { const [from, data] = args.params!; const account = this.wallet.getAccount(EthAddress.fromString(from)); if (account) { @@ -139,7 +231,15 @@ export class WalletProvider implements EthereumProvider { return signTransaction(populatedTx, account.privateKey).rawTransaction; } - private async ethSignTransaction(args: RequestArguments) { + /** + * Sign a transaction using the local account associated with the 'from' address in the given transaction object. + * If the 'from' address is not managed by the WalletProvider, the transaction will be forwarded to the underlying provider. + * The input transaction should be in Ethereum JSON-RPC format. + * + * @param args - A RequestArguments object containing the transaction details. + * @returns A Promise that resolves to the signed transaction as a hex-encoded string. + */ +private async ethSignTransaction(args: RequestArguments) { const tx = args.params![0]; const account = this.wallet.getAccount(EthAddress.fromString(tx.from)); if (account) { @@ -149,7 +249,15 @@ export class WalletProvider implements EthereumProvider { return await this.provider.request(args); } - private async ethSendTransaction(args: RequestArguments) { + /** + * Process and send a given Ethereum transaction using the EthAccount instance associated with the 'from' address. + * If the account is found in the local wallet, it will sign the transaction locally and send the raw transaction + * to the Ethereum provider. If the account is not found in the local wallet, it will forward the request to the provider. + * + * @param args - The RequestArguments object containing the Ethereum transaction details. + * @returns A promise that resolves to the transaction hash of the submitted transaction. + */ +private async ethSendTransaction(args: RequestArguments) { const tx = args.params![0]; const account = this.wallet.getAccount(EthAddress.fromString(tx.from)); if (account) { @@ -162,21 +270,127 @@ export class WalletProvider implements EthereumProvider { return this.provider.request(args); } - on(notification: 'connect', listener: (connectInfo: ProviderConnectInfo) => void): this; - on(notification: 'disconnect', listener: (error: ProviderRpcError) => void): this; - on(notification: 'chainChanged', listener: (chainId: string) => void): this; - on(notification: 'accountsChanged', listener: (accounts: string[]) => void): this; - on(notification: 'message', listener: (message: ProviderMessage) => void): this; - on(notification: any, listener: any) { + /** + * Attaches a callback function to the specified event type on the Ethereum provider. + * The listener will be invoked whenever the event occurs for the given notification. + * Common events include 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. + * + * @param notification - The event type to listen for. + * @param listener - The callback function to be invoked when the event occurs. + * @returns The WalletProvider instance, allowing for method chaining. + */ +on(notification: 'connect', listener: (connectInfo: ProviderConnectInfo) => void): this; + /** + * Registers an event listener for the specified notification type. + * The listener will be invoked with the relevant data when the provider emits that notification. + * + * @param notification - The notification type to subscribe to, such as 'connect', 'disconnect', 'chainChanged', 'accountsChanged', or 'message'. + * @param listener - The callback function to be invoked when the provider emits the specified notification. + * @returns This WalletProvider instance, allowing for chained method calls. + */ +on(notification: 'disconnect', listener: (error: ProviderRpcError) => void): this; + /** + * Registers an event listener for the specified notification type. + * The listener function will be invoked when the corresponding event is emitted by the provider. + * This allows for handling of various events such as connection changes, account changes, etc. + * + * @param notification - The type of event to listen for ('connect', 'disconnect', 'chainChanged', 'accountsChanged', or 'message'). + * @param listener - The callback function to be invoked when the specified event occurs. + * @returns The WalletProvider instance for chaining purposes. + */ +on(notification: 'chainChanged', listener: (chainId: string) => void): this; + /** + * Add an event listener for the specified notification type. + * The listener function will be called whenever an event of the specified type is emitted from the provider. + * Supported notification types are: 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. + * + * @param notification - The type of event to listen for. + * @param listener - The function to be called when the event occurs. + * @returns The WalletProvider instance, allowing chained calls. + */ +on(notification: 'accountsChanged', listener: (accounts: string[]) => void): this; + /** + * Add an event listener for the specified notification on this WalletProvider instance. + * The listener will be called with relevant information when the event occurs. + * Supported notifications include 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. + * + * @param notification - The type of event to listen for. + * @param listener - The function that will be called when the event occurs, with arguments based on the event type. + * @returns This WalletProvider instance, allowing for method chaining. + */ +on(notification: 'message', listener: (message: ProviderMessage) => void): this; + /** + * Registers a listener function to be called when the specified event occurs. + * The available events are 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. + * The listener function should take the appropriate argument based on the event type. + * + * @param notification - The event type to listen for. One of: 'connect', 'disconnect', 'chainChanged', 'accountsChanged', or 'message'. + * @param listener - The function to be called when the specified event occurs, taking the appropriate argument based on the event type. + * @returns The WalletProvider instance, allowing for method chaining. + */ +on(notification: any, listener: any) { return this.provider.on(notification, listener); } - removeListener(notification: 'connect', listener: (connectInfo: ProviderConnectInfo) => void): this; - removeListener(notification: 'disconnect', listener: (error: ProviderRpcError) => void): this; - removeListener(notification: 'chainChanged', listener: (chainId: string) => void): this; - removeListener(notification: 'accountsChanged', listener: (accounts: string[]) => void): this; - removeListener(notification: 'message', listener: (message: ProviderMessage) => void): this; - removeListener(notification: any, listener: any) { + /** + * Removes an event listener for the specified notification type. + * The listener should be a function previously added using the `on` method. + * If the listener is not found, this method does nothing. + * + * @param notification - The notification type to remove the listener from. + * @param listener - The event listener function to remove. + * @returns The WalletProvider instance. + */ +removeListener(notification: 'connect', listener: (connectInfo: ProviderConnectInfo) => void): this; + /** + * Removes a specified listener function from the given event notification. + * The listener function will no longer be triggered when the specified event occurs. + * + * @param notification - The event notification type for which the listener needs to be removed. + * @param listener - The listener function that was previously added and needs to be removed. + * @returns The modified WalletProvider instance. + */ +removeListener(notification: 'disconnect', listener: (error: ProviderRpcError) => void): this; + /** + * Removes a previously added listener function for the specified event notification. + * The function will no longer be invoked when the specified event is emitted. + * + * @param notification - The event notification from which to remove the listener. + * @param listener - The listener function that was previously added and now needs to be removed. + * @returns The WalletProvider instance for chaining. + */ +removeListener(notification: 'chainChanged', listener: (chainId: string) => void): this; + /** + * Removes a previously added listener function for the specified notification event. + * The listener function will no longer be called when the corresponding event occurs. + * This helps to prevent unwanted side-effects, memory leaks and improve performance + * by unregistering listeners that are no longer needed. + * + * @param notification - The event name for which the listener should be removed. + * @param listener - The callback function that was previously added as a listener for the specified event. + * @returns The WalletProvider instance, allowing for method chaining. + */ +removeListener(notification: 'accountsChanged', listener: (accounts: string[]) => void): this; + /** + * Removes a previously added event listener for the specified notification type. + * The listener function should be the same as the one used when calling 'on' to add the listener. + * If the listener is not found, this method will have no effect. + * + * @param notification - The notification type for which to remove the listener. + * @param listener - The listener function that was previously added. + * @returns The WalletProvider instance with the listener removed. + */ +removeListener(notification: 'message', listener: (message: ProviderMessage) => void): this; + /** + * Removes a specified listener function from the given event notification. + * Listeners are functions that have been previously added via the `on` method. + * If the listener is successfully removed, it will no longer be called when the corresponding event is triggered. + * + * @param notification - The event notification type from which the listener should be removed. + * @param listener - The listener function to be removed from the specified event notification. + * @returns The WalletProvider instance with the updated set of listeners. + */ +removeListener(notification: any, listener: any) { return this.provider.removeListener(notification, listener); } } diff --git a/yarn-project/ethereum.js/src/provider/web3_adapter.ts b/yarn-project/ethereum.js/src/provider/web3_adapter.ts index fd4ab63c25f..2e7757b4b96 100644 --- a/yarn-project/ethereum.js/src/provider/web3_adapter.ts +++ b/yarn-project/ethereum.js/src/provider/web3_adapter.ts @@ -9,7 +9,16 @@ export class Web3Adapter implements EthereumProvider { constructor(private provider: Web3Provider) {} - public request(args: RequestArguments): Promise { + /** + * Sends a JSON-RPC request to the legacy web3 provider and returns the result in a Promise. + * The function constructs a payload object using the method and params provided in the RequestArguments, + * and sends it to the provider for execution. It handles errors and responses accordingly, and + * resolves or rejects the Promise based on the response from the provider. + * + * @param args - A RequestArguments object containing the JSON-RPC method and parameters. + * @returns A Promise resolving with the result of the executed request or rejecting with an error. + */ +public request(args: RequestArguments): Promise { return new Promise((resolve, reject) => { const payload = { jsonrpc: '2.0', @@ -30,11 +39,25 @@ export class Web3Adapter implements EthereumProvider { }); } - on(): this { + /** + * Adds an event listener for the specified event on the Web3Adapter instance. + * Please note that this method is not implemented and will throw an error when called, as events are not supported. + * + * @throws {Error} Will throw an error if the method is called, because events are not supported in this implementation. + * @returns {this} Returns the Web3Adapter instance for chaining purposes (if events were supported). + */ +on(): this { throw new Error('Events not supported.'); } - removeListener(): this { + /** + * Remove an event listener from the Ethereum provider. + * This method is not supported for the Web3Adapter class, and calling it will result in an error being thrown. + * + * @throws {Error} - An error indicating that event removal is not supported. + * @returns {this} - The current instance of the Web3Adapter class. + */ +removeListener(): this { throw new Error('Events not supported.'); } } diff --git a/yarn-project/ethereum.js/src/provider/web3_provider.ts b/yarn-project/ethereum.js/src/provider/web3_provider.ts index 9ccceeaa98a..4effef7da6f 100644 --- a/yarn-project/ethereum.js/src/provider/web3_provider.ts +++ b/yarn-project/ethereum.js/src/provider/web3_provider.ts @@ -1,23 +1,72 @@ +/** + * Represents the structure of a JSON-RPC request. + * Provides a standardized format for remote procedure calls using the JSON data format. + */ interface JsonRpcRequest { - jsonrpc: string; - method: string; - params: any[]; - id: number; + /** + * A JSON-RPC version identifier. + */ +jsonrpc: string; + /** + * The name of the JSON-RPC method to call. + */ +method: string; + /** + * An array of method-specific parameters. + */ +params: any[]; + /** + * Unique identifier for the JSON-RPC request. + */ +id: number; } +/** + * Represents a JSON-RPC response object. + * Provides structured data for handling the result or error from a JSON-RPC call. + * Used commonly in web3 applications to interact with blockchain networks and services. + */ interface JsonRpcResponse { - jsonrpc: string; - id: number; - result?: any; - error?: { - code: number; - message: string; - data?: any; + /** + * JSON-RPC version used for communication. + */ +jsonrpc: string; + /** + * A unique identifier for the JSON-RPC request. + */ +id: number; + /** + * The outcome of the invoked method. + */ +result?: any; + /** + * Represents error details returned in JSON-RPC response. + */ +error?: { + /** + * The numerical error code representing the type of error occurred. + */ +code: number; + /** + * The name of the method to be called on the remote server. + */ +message: string; + /** + * Additional information related to the error. + */ +data?: any; }; } +/** + * Type for handling the results and errors of JSON-RPC based Web3 provider send operations. + */ type Callback = (err?: Error, result?: JsonRpcResponse) => void; +/** + * Represents a Web3 provider interface for JSON-RPC communication. + * Provides an abstract method for sending requests to interact with Ethereum blockchain nodes. + */ export interface Web3Provider { send(payload: JsonRpcRequest, callback: Callback): any; } diff --git a/yarn-project/ethereum.js/src/retry/index.ts b/yarn-project/ethereum.js/src/retry/index.ts index a293108ca6c..907d3fcd280 100644 --- a/yarn-project/ethereum.js/src/retry/index.ts +++ b/yarn-project/ethereum.js/src/retry/index.ts @@ -1,6 +1,13 @@ import { sleep } from '../sleep/index.js'; import { Timer } from '../timer/index.js'; +/** + * Generates a backoff sequence iterator for exponential backoff with pre-defined values. + * The iterator will yield a series of time intervals (in seconds) to be used for backing off + * in error handling scenarios. The sequence is [1, 1, 1, 2, 4, 8, 16, 32, 64] and will not exceed 64. + * + * @yields {number} The next value in the backoff sequence. + */ export function* backoffGenerator() { const v = [1, 1, 1, 2, 4, 8, 16, 32, 64]; let i = 0; @@ -9,6 +16,17 @@ export function* backoffGenerator() { } } +/** + * Retry executing the provided asynchronous function until it is successful, using a backoff strategy. + * The `backoff` generator determines the waiting time between retries. It defaults to the `backoffGenerator` function + * which increases the waiting time exponentially. The operation can be named for better error logging. + * If the backoff generator stops producing new values (returns undefined), the latest error will be thrown. + * + * @param fn - The asynchronous function to execute and retry if it fails. + * @param name - Optional name of the operation for better error logging. + * @param backoff - Optional custom backoff generator, defaults to exponential backoff. + * @returns A Promise that resolves with the successful result or rejects with the latest error after all retries fail. + */ export async function retry(fn: () => Promise, name = 'Operation', backoff = backoffGenerator()) { while (true) { try { diff --git a/yarn-project/ethereum.js/src/serialize/deserializer.ts b/yarn-project/ethereum.js/src/serialize/deserializer.ts index 7ff25fd9c63..06b9c2ab163 100644 --- a/yarn-project/ethereum.js/src/serialize/deserializer.ts +++ b/yarn-project/ethereum.js/src/serialize/deserializer.ts @@ -7,56 +7,155 @@ import { deserializeUInt32, } from './free_funcs.js'; -export type DeserializeFn = (buf: Buffer, offset: number) => { elem: T; adv: number }; +/** + * Type representing a deserialization function that takes a buffer and an offset as input parameters, + * and returns an object containing the deserialized element of type T and the number of bytes consumed. + */ +export type DeserializeFn = (buf: Buffer, offset: number) => { /** + * The deserialized element from the buffer. + */ +elem: T; /** + * The number of bytes advanced in the buffer after deserialization. + */ +adv: number }; +/** + * The Deserializer class provides a set of utility methods for efficiently deserializing data from a buffer. + * It supports various primitive types such as boolean, integers, BigInt, string, and Date, as well as + * more complex structures like arrays and vectors. The class maintains an internal offset to keep track + * of the current deserialization position within the buffer, allowing for sequential deserialization + * of multiple elements. Additionally, custom deserialization functions can be executed, offering + * flexibility and extensibility for handling custom data types or structures. + */ export class Deserializer { constructor(private buf: Buffer, private offset = 0) {} - public bool() { + /** + * Deserialize a boolean value from the buffer at the current offset. + * Advances the buffer offset by one byte after deserialization. + * + * @returns The deserialized boolean value, either true or false. + */ +public bool() { return this.exec(deserializeBool) ? true : false; } - public uInt32() { + /** + * Deserialize an unsigned 32-bit integer from the internal buffer. + * Advances the internal offset by 4 bytes after deserialization. + * + * @returns The deserialized unsigned 32-bit integer. + */ +public uInt32() { return this.exec(deserializeUInt32); } - public int32() { + /** + * Deserialize a signed 32-bit integer from the buffer. + * The input buffer should have at least 4 bytes available starting from the current offset. + * Advances the internal offset by 4 bytes after reading the value. + * + * @returns The deserialized signed 32-bit integer. + */ +public int32() { return this.exec(deserializeInt32); } - public bigInt(width = 32) { + /** + * Deserialize a BigInt from the internal buffer using the specified width in bytes. + * The 'bigInt' method reads the next 'width' bytes from the buffer, starting at the current offset, + * and converts them into a BigInt. If the 'width' parameter is not provided, it defaults to 32 bytes. + * After reading the value, it increments the internal offset by the number of bytes read. + * + * @param width - The number of bytes to read for the BigInt (default: 32). + * @returns The deserialized BigInt value. + */ +public bigInt(width = 32) { return this.exec((buf: Buffer, offset: number) => deserializeBigInt(buf, offset, width)); } - public vector() { + /** + * Deserialize a vector from the buffer and return it as a new Buffer object. + * The vector is expected to be prefixed with its length encoded as a CompactSize unsigned integer. + * Throws an error if the buffer size is insufficient or the length prefix is invalid. + * + * @returns A Buffer object containing the deserialized vector data. + */ +public vector() { return this.exec(deserializeBufferFromVector); } - public buffer(width: number) { + /** + * Extracts a sub-buffer of the given width from the internal buffer starting at the current offset. + * Advances the internal offset by the width after extraction. + * Useful for extracting raw binary data of a specific size or when custom processing is needed. + * + * @param width - The width (in bytes) of the sub-buffer to extract. + * @returns A Buffer instance containing the extracted data. + */ +public buffer(width: number) { const buf = this.buf.slice(this.offset, this.offset + width); this.offset += width; return buf; } - public string() { + /** + * Deserialize a string from the internal buffer. + * The string is read from the buffer starting at the current offset as a vector of bytes, then converted to a string. + * Updates the internal offset position after the operation. + * + * @returns The deserialized string. + */ +public string() { return this.vector().toString(); } - public date() { + /** + * Deserialize a date object from the buffer using 8-byte BigInt as the underlying data. + * The function reads an 8-byte BigInt from the current position of the buffer, + * interprets it as milliseconds since UNIX epoch, and creates a new Date object. + * + * @returns A Date object representing the deserialized date value. + */ +public date() { return new Date(Number(this.bigInt(8))); } - public deserializeArray(fn: DeserializeFn) { + /** + * Deserialize an array of elements from the buffer using the provided deserialization function. + * The deserialization function should take a buffer and an offset as parameters and return + * an object with two properties: 'elem' representing the deserialized element and 'adv' + * denoting the number of bytes consumed during deserialization. This function updates the + * internal offset according to the total bytes consumed. + * + * @param fn - The deserialization function used to deserialize individual elements of the array. + * @returns An array of deserialized elements. + */ +public deserializeArray(fn: DeserializeFn) { return this.exec((buf: Buffer, offset: number) => deserializeArrayFromVector(fn, buf, offset)); } - public exec(fn: DeserializeFn): T { + /** + * Executes the given deserialization function with the internal buffer and offset, updating the offset accordingly. + * This method is useful for performing custom deserialization operations within the context of the Deserializer instance. + * + * @param fn - The deserialization function to be executed. It should accept a Buffer and an offset as its parameters and return an object containing 'elem' (the deserialized value) and 'adv' (the number of bytes processed). + * @returns The deserialized value of type T obtained from the deserialization function. + */ +public exec(fn: DeserializeFn): T { const { elem, adv } = fn(this.buf, this.offset); this.offset += adv; return elem; } - public getOffset() { + /** + * Retrieves the current offset value of the Deserializer instance. + * The offset is a numeric representation of the position within the buffer, + * and it gets updated as the data elements are deserialized. + * + * @returns The current offset value as a number. + */ +public getOffset() { return this.offset; } } diff --git a/yarn-project/ethereum.js/src/serialize/free_funcs.ts b/yarn-project/ethereum.js/src/serialize/free_funcs.ts index 1e03cd0914d..a410bc743b8 100644 --- a/yarn-project/ethereum.js/src/serialize/free_funcs.ts +++ b/yarn-project/ethereum.js/src/serialize/free_funcs.ts @@ -43,39 +43,111 @@ export function serializeBufferToVector(buf: Buffer) { return Buffer.concat([lengthBuf, buf]); } +/** + * Serialize a BigInt value into a buffer with specified width (number of bytes). + * The output buffer represents the big-endian encoding of the input BigInt value. + * If the width is not provided, it defaults to 32 bytes. + * + * @param n - The BigInt value to be serialized. + * @param width - The number of bytes for the output buffer (optional, default: 32). + * @returns A Buffer containing the serialized big-endian representation of the BigInt value. + */ export function serializeBigInt(n: bigint, width = 32) { return toBufferBE(n, width); } +/** + * Deserialize a bigint from a buffer with a specified offset and width. + * The function extracts a slice of the buffer based on the given offset and width, + * and converts that slice into a bigint value. + * + * @param buf - The input buffer containing the serialized bigint data. + * @param offset - The starting index within the buffer to deserialize from. Default is 0. + * @param width - The number of bytes to use for deserialization. Default is 32. + * @returns An object containing the deserialized bigint ('elem') and the advancement ('adv') in the buffer. + */ export function deserializeBigInt(buf: Buffer, offset = 0, width = 32) { return { elem: toBigIntBE(buf.slice(offset, offset + width)), adv: width }; } +/** + * Serialize a given JavaScript Date object into an 8-byte big-endian BigInt buffer. + * The function first converts the date to its corresponding UNIX timestamp (in milliseconds), + * then creates a BigInt from the timestamp and serializes it to an 8-byte buffer using + * big-endian format. This buffer can be useful for interoperability with other systems and + * data storage. + * + * @param date - The JavaScript Date object to be serialized. + * @returns A Buffer containing the serialized date as an 8-byte big-endian BigInt. + */ export function serializeDate(date: Date) { return serializeBigInt(BigInt(date.getTime()), 8); } +/** + * Deserialize a Buffer from a vector, given its starting offset. + * This function reads the length of the buffer from the vector and extracts the corresponding bytes. + * It returns an object containing the deserialized Buffer element and the total number of bytes advanced (including the length). + * + * @param vector - The input vector Buffer from which the buffer will be deserialized. + * @param offset - The starting offset in the input vector where the buffer begins. Default is 0. + * @returns An object with the deserialized Buffer element as 'elem' and the total number of bytes advanced as 'adv'. + */ export function deserializeBufferFromVector(vector: Buffer, offset = 0) { const length = vector.readUInt32BE(offset); const adv = 4 + length; return { elem: vector.slice(offset + 4, offset + adv), adv }; } +/** + * Deserialize a boolean value from a buffer at the specified offset. + * The function reads one byte from the buffer and returns an object with the deserialized boolean value and the number of bytes advanced (adv). + * + * @param buf - The buffer containing the serialized boolean value. + * @param offset - The starting position in the buffer to read the boolean value. Default is 0. + * @returns An object with the deserialized boolean value (elem) and the number of bytes advanced (adv). + */ export function deserializeBool(buf: Buffer, offset = 0) { const adv = 1; return { elem: buf.readUInt8(offset), adv }; } +/** + * Deserialize a 32-bit unsigned integer from a Buffer. + * Extracts a 32-bit unsigned integer from the provided Buffer at the specified offset and + * returns the deserialized value along with the number of bytes advanced in the buffer. + * + * @param buf - The source Buffer to deserialize the unsigned integer from. + * @param offset - The starting position within the Buffer to read the unsigned integer. + * @returns An object containing the deserialized 32-bit unsigned integer (elem) and number of bytes advanced (adv). + */ export function deserializeUInt32(buf: Buffer, offset = 0) { const adv = 4; return { elem: buf.readUInt32BE(offset), adv }; } +/** + * Deserialize a signed 32-bit integer from the given buffer at the specified offset. + * Returns the deserialized integer value along with the number of bytes advanced (4) as an object. + * + * @param buf - The input buffer containing the binary data to deserialize. + * @param offset - The optional starting position (index) in the buffer for deserialization. Default is 0. + * @returns An object containing the deserialized signed 32-bit integer ('elem') and the number of bytes advanced ('adv', always 4). + */ export function deserializeInt32(buf: Buffer, offset = 0) { const adv = 4; return { elem: buf.readInt32BE(offset), adv }; } +/** + * Deserialize a field from a given buffer starting at the specified offset. + * This function reads a fixed size (32 bytes) slice of the buffer and returns an object containing + * the extracted field as a Buffer and the number of bytes advanced in the input buffer. + * + * @param buf - The input buffer containing the serialized data. + * @param offset - The starting position in the buffer to begin deserialization (default is 0). + * @returns An object containing the extracted field as a Buffer and the number of bytes advanced in the input buffer. + */ export function deserializeField(buf: Buffer, offset = 0) { const adv = 32; return { elem: buf.slice(offset, offset + adv), adv }; @@ -88,8 +160,26 @@ export function serializeBufferArrayToVector(arr: Buffer[]) { return Buffer.concat([lengthBuf, ...arr]); } +/** + * Deserialize an array of fixed length elements from a buffer, given a deserialization function. + * Reads the size of the array from the buffer at the provided offset, then iterates through the + * elements and applies the provided deserialization function on each element. Returns an array + * of the deserialized elements and the total bytes consumed in the process. + * + * @template T - The type of the deserialized elements. + * @param deserialize - The deserialization function to be applied on each element of the array. + * @param vector - The source buffer containing the serialized data. + * @param offset - The starting position in the buffer to begin deserialization (optional, default is 0). + * @returns An object containing the deserialized array of elements (elem) and the total bytes consumed in the process (adv). + */ export function deserializeArrayFromVector( - deserialize: (buf: Buffer, offset: number) => { elem: T; adv: number }, + deserialize: (buf: Buffer, offset: number) => { /** + * The deserialized element from the buffer. + */ +elem: T; /** + * The number of bytes advanced in the buffer during deserialization. + */ +adv: number }, vector: Buffer, offset = 0, ) { diff --git a/yarn-project/ethereum.js/src/serialize/serializer.ts b/yarn-project/ethereum.js/src/serialize/serializer.ts index 8bebb7ada96..16364868d8c 100644 --- a/yarn-project/ethereum.js/src/serialize/serializer.ts +++ b/yarn-project/ethereum.js/src/serialize/serializer.ts @@ -15,19 +15,46 @@ export class Serializer { constructor() {} - public bool(bool: boolean) { + /** + * Serializes a boolean value into a Buffer and appends it to the internal buffer array. + * The serialized byte can represent either true or false, using 1 for true and 0 for false. + * + * @param bool - The boolean value to be serialized. + */ +public bool(bool: boolean) { this.buf.push(boolToByte(bool)); } - public uInt32(num: number) { + /** + * Serialize an unsigned 32-bit integer into a big-endian byte Buffer and add it to the internal buffer list. + * The input 'num' should be within the range of 0 to 2^32-1, inclusive. + * Throws an error if the input value is out of range. + * + * @param num - The unsigned 32-bit integer to be serialized. + */ +public uInt32(num: number) { this.buf.push(numToUInt32BE(num)); } - public int32(num: number) { + /** + * Serializes the given signed 32-bit integer as a big-endian buffer and stores it in the internal buffer. + * The input 'num' should be within the range of [-2147483648, 2147483647], inclusive. + * Throws an error if the input value is out of range. + * + * @param num - The signed 32-bit integer to serialize. + */ +public int32(num: number) { this.buf.push(numToInt32BE(num)); } - public bigInt(num: bigint) { + /** + * Serialize a bigint value into a Buffer and append it to the internal buffer array. + * The function takes care of handling large integer values that cannot be stored in + * standard JavaScript number type, allowing serialization of big integers without loss of precision. + * + * @param num - The bigint value to be serialized and added to the buffer. + */ +public bigInt(num: bigint) { this.buf.push(serializeBigInt(num)); } @@ -48,19 +75,47 @@ export class Serializer { this.buf.push(buf); } - public string(str: string) { + /** + * Serialize a given string by first converting it to a Buffer and then appending its length as a prefix. + * The converted buffer is pushed into the internal buffer array for further serialization. + * This method ensures the corresponding deserialize function can correctly read variable length strings. + * + * @param str - The input string to be serialized. + */ +public string(str: string) { this.vector(Buffer.from(str)); } - public date(date: Date) { + /** + * Serializes a Date object and appends it to the buffer. + * The date is converted into a 64-bit integer representing the number of milliseconds since + * January 1, 1970, 00:00:00 UTC. This ensures accurate representation and reconstruction of dates + * during serialization and deserialization processes. + * + * @param date - The Date object to be serialized. + */ +public date(date: Date) { this.buf.push(serializeDate(date)); } - public getBuffer() { + /** + * Returns the serialized buffer obtained by concatenating all the serialized elements added to the Serializer instance. + * The resulting buffer can be used for data transmission or storage, and can be deserialized later to retrieve the original elements. + * + * @returns A Buffer containing the serialized data from the Serializer instance. + */ +public getBuffer() { return Buffer.concat(this.buf); } - public serializeArray(arr: T[]) { + /** + * Serializes an array of elements and appends it to the internal buffer as a vector. + * Each element in the array is assumed to have a 'toBuffer' method which returns its serialized representation as a Buffer. + * The serialized array is prefixed with its length, allowing for variable-length arrays to be deserialized correctly. + * + * @param arr - The array of elements to be serialized. + */ +public serializeArray(arr: T[]) { this.buf.push(serializeBufferArrayToVector(arr.map((e: any) => e.toBuffer()))); } } diff --git a/yarn-project/ethereum.js/src/sleep/index.ts b/yarn-project/ethereum.js/src/sleep/index.ts index a218ae676dc..45704938171 100644 --- a/yarn-project/ethereum.js/src/sleep/index.ts +++ b/yarn-project/ethereum.js/src/sleep/index.ts @@ -1,11 +1,30 @@ +/** + * InterruptError is a custom error class that extends the built-in JavaScript Error. It represents an interrupt event + * in an asynchronous sleep operation by the InterruptableSleep class. When thrown, it signifies that the sleep operation + * has been interrupted and allows developers to handle such events gracefully. + */ export class InterruptError extends Error {} +/** + * The InterruptableSleep class provides an enhanced sleep functionality that can be interrupted before the specified duration has elapsed. + * It allows you to create sleep instances with specified durations, which can be interrupted by calling the 'interrupt' method on the instance. + * In case of interruption, it can be configured to throw an 'InterruptError' or continue without throwing any error. + * This is useful in scenarios where you want to break out of a sleep state based on external conditions or events. + */ export class InterruptableSleep { private interruptResolve: (shouldThrow: boolean) => void = () => {}; private interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); private timeouts: NodeJS.Timeout[] = []; - public async sleep(ms: number) { + /** + * Sleeps for a specified amount of milliseconds and optionally throws an InterruptError if interrupted. + * The function creates a promise that resolves after the given milliseconds and races it with an interruptPromise. + * If the sleep is interrupted before the timer is completed, it can either resolve or throw an InterruptError based on the shouldThrow flag. + * + * @param ms - The number of milliseconds to sleep. + * @throws InterruptError when the sleep is interrupted and shouldThrow flag is true. + */ +public async sleep(ms: number) { let timeout!: NodeJS.Timeout; const promise = new Promise(resolve => (timeout = setTimeout(() => resolve(false), ms))); this.timeouts.push(timeout); @@ -17,12 +36,29 @@ export class InterruptableSleep { } } - public interrupt(sleepShouldThrow = false) { + /** + * Interrupts the sleep currently in progress by resolving the interruptPromise. + * If sleepShouldThrow is set to true, it will cause the sleep function to throw an InterruptError. + * The interrupt method can be called multiple times during the lifetime of the InterruptableSleep instance + * to interrupt the subsequent sleeps. By default, sleepShouldThrow is false, which means the sleep function + * will not throw an error when interrupted. + * + * @param sleepShouldThrow - Optional flag to determine if the sleep function should throw an InterruptError on interruption. Default value is false. + */ +public interrupt(sleepShouldThrow = false) { this.interruptResolve(sleepShouldThrow); this.interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); } } +/** + * Sleeps for the specified number of milliseconds before resolving. The sleep can be interrupted using the 'interrupt' method. + * If interrupted, the sleep will either resolve immediately or throw an InterruptError depending on the value passed to 'interrupt'. + * + * @param ms - The number of milliseconds to sleep. + * @throws {InterruptError} When sleep is interrupted and 'sleepShouldThrow' parameter in 'interrupt' is set to true. + * @returns A Promise that resolves after the specified number of milliseconds or when interrupted. + */ export function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } diff --git a/yarn-project/ethereum.js/src/timer/index.ts b/yarn-project/ethereum.js/src/timer/index.ts index 3e1aac7c0f6..5d548db4723 100644 --- a/yarn-project/ethereum.js/src/timer/index.ts +++ b/yarn-project/ethereum.js/src/timer/index.ts @@ -1,3 +1,10 @@ +/** + * The Timer class is a versatile utility for measuring elapsed time in both milliseconds and seconds. + * It simplifies the process of calculating time intervals by internally handling date and time operations. + * Upon instantiation, it records the current time as the starting point, which can be compared to + * the actual time at any subsequent calls. Use the ms() function to retrieve the elapsed time in milliseconds, + * or the s() function to obtain the duration in seconds. + */ export class Timer { private start: number; @@ -5,11 +12,26 @@ export class Timer { this.start = new Date().getTime(); } - public ms() { + /** + * Returns the elapsed time in milliseconds since the Timer instance was created. + * The returned value is based on the difference between the current time and the + * start time of the Timer instance. This method allows for precise measurement of + * durations in milliseconds. + * + * @returns The elapsed time in milliseconds. + */ +public ms() { return new Date().getTime() - this.start; } - public s() { + /** + * Returns the elapsed time in seconds since the Timer instance was created. + * The returned value is a floating-point number representing the time difference + * between the current time and the time when the Timer instance was initialized. + * + * @returns The elapsed time in seconds as a number. + */ +public s() { return (new Date().getTime() - this.start) / 1000; } } From f6ab79ff75aa7219f4177226eaff5992fa8dd659 Mon Sep 17 00:00:00 2001 From: Orloaft Date: Thu, 13 Apr 2023 19:34:48 -0400 Subject: [PATCH 2/5] deduplicate docs for utilities from foundation package --- yarn-project/ethereum.js/src/log/console.ts | 27 +--- yarn-project/ethereum.js/src/log/debug.ts | 55 +-------- yarn-project/ethereum.js/src/retry/index.ts | 20 +-- .../ethereum.js/src/serialize/deserializer.ts | 115 +++--------------- yarn-project/ethereum.js/src/sleep/index.ts | 34 +----- yarn-project/ethereum.js/src/timer/index.ts | 25 +--- 6 files changed, 35 insertions(+), 241 deletions(-) diff --git a/yarn-project/ethereum.js/src/log/console.ts b/yarn-project/ethereum.js/src/log/console.ts index 6bd6a0b70f2..0f758af3a87 100644 --- a/yarn-project/ethereum.js/src/log/console.ts +++ b/yarn-project/ethereum.js/src/log/console.ts @@ -1,36 +1,17 @@ -/** - * Type for logging functions that accept any number of arguments. - */ + export type Logger = (...args: any[]) => void; -/** - * ConsoleLogger is a utility class for formatting and logging messages with a specified prefix. - * It provides a simple interface for directing log messages to a custom logger function (defaults to console.log). - * The 'log' method allows logging of multiple arguments while prepending the configured prefix to the log message. - */ + class ConsoleLogger { constructor(private prefix: string, private logger: (...args: any[]) => void = console.log) {} - /** - * Logs a message with a prefixed string to the console. - * The log function takes any number of arguments that are passed to the logger function. - * The prefixed string is set during object instantiation and helps in differentiating the logs. - * - * @param args - Any number of arguments to be logged in the console. - */ + public log(...args: any[]) { this.logger(`${this.prefix}:`, ...args); } } -/** - * Create a Logger instance with an optional prefix string. - * If a prefix is provided, the logger will output messages with the format "prefix: message". - * Otherwise, it will use the default 'console.log' as the logger function. - * - * @param prefix - The optional string to prepend to log messages. - * @returns A Logger instance with the specified prefix. - */ + export function createLogger(prefix: string): Logger { if (prefix) { const logger = new ConsoleLogger(prefix, console.log); diff --git a/yarn-project/ethereum.js/src/log/debug.ts b/yarn-project/ethereum.js/src/log/debug.ts index 053dee38e39..f0dc7fd0ead 100644 --- a/yarn-project/ethereum.js/src/log/debug.ts +++ b/yarn-project/ethereum.js/src/log/debug.ts @@ -3,16 +3,7 @@ import debug from 'debug'; let preLogHook: ((...args: any[]) => void) | undefined; let postLogHook: ((...args: any[]) => void) | undefined; -/** - * The function that serves as a central hub through which all logs pass. - * It first checks if the log is enabled for the given logger's namespace, - * then calls the preLogHook (if any) with the logger's namespace and the provided arguments, - * followed by the actual logger function, and finally calls the postLogHook (if any) with the - * logger's namespace and the provided arguments. - * - * @param logger - The debug logger instance associated with a specific namespace. - * @param args - The arguments to be passed to the logger and hooks. - */ + function theFunctionThroughWhichAllLogsPass(logger: any, ...args: any[]) { if (!debug.enabled(logger.namespace)) { return; @@ -26,62 +17,28 @@ function theFunctionThroughWhichAllLogsPass(logger: any, ...args: any[]) { } } -/** - * Creates a debug logger with the specified namespace. - * The returned logger function will only log messages if its namespace is enabled. - * Additionally, it passes the log messages through pre and post log hooks if they are set. - * - * @param name - The namespace for the debug logger. - * @returns A debug logger function with the given namespace. - */ + export function createDebugLogger(name: string): any { const logger = debug(name); return (...args: any[]) => theFunctionThroughWhichAllLogsPass(logger, ...args); } -/** - * Set a hook function to be called before each log output by the debug logger. - * The provided function will be invoked with the logger namespace and log arguments. - * This can be useful for additional processing or filtering of logs before they are output. - * - * @param fn - The function to be called before logging. Receives the logger namespace and log arguments as parameters. - */ + export function setPreDebugLogHook(fn: (...args: any[]) => void) { preLogHook = fn; } -/** - * Sets a post-debug log hook function that will be called after each log message. - * The function provided should accept any number of arguments, with the first argument being the logger's namespace, - * followed by the original log message arguments. This hook can be used to perform additional actions such as - * formatting, filtering or redirecting log messages. - * - * @param fn - The function to be called after each log message. - */ + export function setPostDebugLogHook(fn: (...args: any[]) => void) { postLogHook = fn; } -/** - * Enable debug logs for specified namespaces. - * The input 'str' should be a comma-separated list of namespaces to enable logs. - * Wildcards (*) can be used to enable logs for multiple namespaces at once. - * For example, 'foo*,bar*' will enable logs for all namespaces starting with foo and bar. - * - * @param str - The string containing comma-separated namespaces or wildcard patterns. - */ + export function enableLogs(str: string) { debug.enable(str); } -/** - * Checks whether logs for the specified namespace are enabled. - * The input 'str' should be a string representing the namespace, - * as defined during the creation of the debug logger. - * - * @param str - The namespace string to check if logs are enabled. - * @returns A boolean indicating whether logs are enabled for the specified namespace. - */ + export function isLogEnabled(str: string) { return debug.enabled(str); } diff --git a/yarn-project/ethereum.js/src/retry/index.ts b/yarn-project/ethereum.js/src/retry/index.ts index 907d3fcd280..c5d6e4cdf44 100644 --- a/yarn-project/ethereum.js/src/retry/index.ts +++ b/yarn-project/ethereum.js/src/retry/index.ts @@ -1,13 +1,7 @@ import { sleep } from '../sleep/index.js'; import { Timer } from '../timer/index.js'; -/** - * Generates a backoff sequence iterator for exponential backoff with pre-defined values. - * The iterator will yield a series of time intervals (in seconds) to be used for backing off - * in error handling scenarios. The sequence is [1, 1, 1, 2, 4, 8, 16, 32, 64] and will not exceed 64. - * - * @yields {number} The next value in the backoff sequence. - */ + export function* backoffGenerator() { const v = [1, 1, 1, 2, 4, 8, 16, 32, 64]; let i = 0; @@ -16,17 +10,7 @@ export function* backoffGenerator() { } } -/** - * Retry executing the provided asynchronous function until it is successful, using a backoff strategy. - * The `backoff` generator determines the waiting time between retries. It defaults to the `backoffGenerator` function - * which increases the waiting time exponentially. The operation can be named for better error logging. - * If the backoff generator stops producing new values (returns undefined), the latest error will be thrown. - * - * @param fn - The asynchronous function to execute and retry if it fails. - * @param name - Optional name of the operation for better error logging. - * @param backoff - Optional custom backoff generator, defaults to exponential backoff. - * @returns A Promise that resolves with the successful result or rejects with the latest error after all retries fail. - */ + export async function retry(fn: () => Promise, name = 'Operation', backoff = backoffGenerator()) { while (true) { try { diff --git a/yarn-project/ethereum.js/src/serialize/deserializer.ts b/yarn-project/ethereum.js/src/serialize/deserializer.ts index 06b9c2ab163..7f2901c0c7f 100644 --- a/yarn-project/ethereum.js/src/serialize/deserializer.ts +++ b/yarn-project/ethereum.js/src/serialize/deserializer.ts @@ -7,154 +7,71 @@ import { deserializeUInt32, } from './free_funcs.js'; -/** - * Type representing a deserialization function that takes a buffer and an offset as input parameters, - * and returns an object containing the deserialized element of type T and the number of bytes consumed. - */ -export type DeserializeFn = (buf: Buffer, offset: number) => { /** - * The deserialized element from the buffer. - */ -elem: T; /** - * The number of bytes advanced in the buffer after deserialization. - */ + +export type DeserializeFn = (buf: Buffer, offset: number) => { + +elem: T; adv: number }; -/** - * The Deserializer class provides a set of utility methods for efficiently deserializing data from a buffer. - * It supports various primitive types such as boolean, integers, BigInt, string, and Date, as well as - * more complex structures like arrays and vectors. The class maintains an internal offset to keep track - * of the current deserialization position within the buffer, allowing for sequential deserialization - * of multiple elements. Additionally, custom deserialization functions can be executed, offering - * flexibility and extensibility for handling custom data types or structures. - */ + export class Deserializer { constructor(private buf: Buffer, private offset = 0) {} - /** - * Deserialize a boolean value from the buffer at the current offset. - * Advances the buffer offset by one byte after deserialization. - * - * @returns The deserialized boolean value, either true or false. - */ + public bool() { return this.exec(deserializeBool) ? true : false; } - /** - * Deserialize an unsigned 32-bit integer from the internal buffer. - * Advances the internal offset by 4 bytes after deserialization. - * - * @returns The deserialized unsigned 32-bit integer. - */ + public uInt32() { return this.exec(deserializeUInt32); } - /** - * Deserialize a signed 32-bit integer from the buffer. - * The input buffer should have at least 4 bytes available starting from the current offset. - * Advances the internal offset by 4 bytes after reading the value. - * - * @returns The deserialized signed 32-bit integer. - */ + public int32() { return this.exec(deserializeInt32); } - /** - * Deserialize a BigInt from the internal buffer using the specified width in bytes. - * The 'bigInt' method reads the next 'width' bytes from the buffer, starting at the current offset, - * and converts them into a BigInt. If the 'width' parameter is not provided, it defaults to 32 bytes. - * After reading the value, it increments the internal offset by the number of bytes read. - * - * @param width - The number of bytes to read for the BigInt (default: 32). - * @returns The deserialized BigInt value. - */ + public bigInt(width = 32) { return this.exec((buf: Buffer, offset: number) => deserializeBigInt(buf, offset, width)); } - /** - * Deserialize a vector from the buffer and return it as a new Buffer object. - * The vector is expected to be prefixed with its length encoded as a CompactSize unsigned integer. - * Throws an error if the buffer size is insufficient or the length prefix is invalid. - * - * @returns A Buffer object containing the deserialized vector data. - */ + public vector() { return this.exec(deserializeBufferFromVector); } - /** - * Extracts a sub-buffer of the given width from the internal buffer starting at the current offset. - * Advances the internal offset by the width after extraction. - * Useful for extracting raw binary data of a specific size or when custom processing is needed. - * - * @param width - The width (in bytes) of the sub-buffer to extract. - * @returns A Buffer instance containing the extracted data. - */ + public buffer(width: number) { const buf = this.buf.slice(this.offset, this.offset + width); this.offset += width; return buf; } - /** - * Deserialize a string from the internal buffer. - * The string is read from the buffer starting at the current offset as a vector of bytes, then converted to a string. - * Updates the internal offset position after the operation. - * - * @returns The deserialized string. - */ + public string() { return this.vector().toString(); } - /** - * Deserialize a date object from the buffer using 8-byte BigInt as the underlying data. - * The function reads an 8-byte BigInt from the current position of the buffer, - * interprets it as milliseconds since UNIX epoch, and creates a new Date object. - * - * @returns A Date object representing the deserialized date value. - */ + public date() { return new Date(Number(this.bigInt(8))); } - /** - * Deserialize an array of elements from the buffer using the provided deserialization function. - * The deserialization function should take a buffer and an offset as parameters and return - * an object with two properties: 'elem' representing the deserialized element and 'adv' - * denoting the number of bytes consumed during deserialization. This function updates the - * internal offset according to the total bytes consumed. - * - * @param fn - The deserialization function used to deserialize individual elements of the array. - * @returns An array of deserialized elements. - */ + public deserializeArray(fn: DeserializeFn) { return this.exec((buf: Buffer, offset: number) => deserializeArrayFromVector(fn, buf, offset)); } - /** - * Executes the given deserialization function with the internal buffer and offset, updating the offset accordingly. - * This method is useful for performing custom deserialization operations within the context of the Deserializer instance. - * - * @param fn - The deserialization function to be executed. It should accept a Buffer and an offset as its parameters and return an object containing 'elem' (the deserialized value) and 'adv' (the number of bytes processed). - * @returns The deserialized value of type T obtained from the deserialization function. - */ + public exec(fn: DeserializeFn): T { const { elem, adv } = fn(this.buf, this.offset); this.offset += adv; return elem; } - /** - * Retrieves the current offset value of the Deserializer instance. - * The offset is a numeric representation of the position within the buffer, - * and it gets updated as the data elements are deserialized. - * - * @returns The current offset value as a number. - */ + public getOffset() { return this.offset; } diff --git a/yarn-project/ethereum.js/src/sleep/index.ts b/yarn-project/ethereum.js/src/sleep/index.ts index 45704938171..70207608aa6 100644 --- a/yarn-project/ethereum.js/src/sleep/index.ts +++ b/yarn-project/ethereum.js/src/sleep/index.ts @@ -1,8 +1,4 @@ -/** - * InterruptError is a custom error class that extends the built-in JavaScript Error. It represents an interrupt event - * in an asynchronous sleep operation by the InterruptableSleep class. When thrown, it signifies that the sleep operation - * has been interrupted and allows developers to handle such events gracefully. - */ + export class InterruptError extends Error {} /** @@ -16,14 +12,7 @@ export class InterruptableSleep { private interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); private timeouts: NodeJS.Timeout[] = []; - /** - * Sleeps for a specified amount of milliseconds and optionally throws an InterruptError if interrupted. - * The function creates a promise that resolves after the given milliseconds and races it with an interruptPromise. - * If the sleep is interrupted before the timer is completed, it can either resolve or throw an InterruptError based on the shouldThrow flag. - * - * @param ms - The number of milliseconds to sleep. - * @throws InterruptError when the sleep is interrupted and shouldThrow flag is true. - */ + public async sleep(ms: number) { let timeout!: NodeJS.Timeout; const promise = new Promise(resolve => (timeout = setTimeout(() => resolve(false), ms))); @@ -36,29 +25,14 @@ public async sleep(ms: number) { } } - /** - * Interrupts the sleep currently in progress by resolving the interruptPromise. - * If sleepShouldThrow is set to true, it will cause the sleep function to throw an InterruptError. - * The interrupt method can be called multiple times during the lifetime of the InterruptableSleep instance - * to interrupt the subsequent sleeps. By default, sleepShouldThrow is false, which means the sleep function - * will not throw an error when interrupted. - * - * @param sleepShouldThrow - Optional flag to determine if the sleep function should throw an InterruptError on interruption. Default value is false. - */ + public interrupt(sleepShouldThrow = false) { this.interruptResolve(sleepShouldThrow); this.interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); } } -/** - * Sleeps for the specified number of milliseconds before resolving. The sleep can be interrupted using the 'interrupt' method. - * If interrupted, the sleep will either resolve immediately or throw an InterruptError depending on the value passed to 'interrupt'. - * - * @param ms - The number of milliseconds to sleep. - * @throws {InterruptError} When sleep is interrupted and 'sleepShouldThrow' parameter in 'interrupt' is set to true. - * @returns A Promise that resolves after the specified number of milliseconds or when interrupted. - */ + export function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } diff --git a/yarn-project/ethereum.js/src/timer/index.ts b/yarn-project/ethereum.js/src/timer/index.ts index 5d548db4723..6c4c17cf3d6 100644 --- a/yarn-project/ethereum.js/src/timer/index.ts +++ b/yarn-project/ethereum.js/src/timer/index.ts @@ -1,10 +1,4 @@ -/** - * The Timer class is a versatile utility for measuring elapsed time in both milliseconds and seconds. - * It simplifies the process of calculating time intervals by internally handling date and time operations. - * Upon instantiation, it records the current time as the starting point, which can be compared to - * the actual time at any subsequent calls. Use the ms() function to retrieve the elapsed time in milliseconds, - * or the s() function to obtain the duration in seconds. - */ + export class Timer { private start: number; @@ -12,25 +6,12 @@ export class Timer { this.start = new Date().getTime(); } - /** - * Returns the elapsed time in milliseconds since the Timer instance was created. - * The returned value is based on the difference between the current time and the - * start time of the Timer instance. This method allows for precise measurement of - * durations in milliseconds. - * - * @returns The elapsed time in milliseconds. - */ + public ms() { return new Date().getTime() - this.start; } - /** - * Returns the elapsed time in seconds since the Timer instance was created. - * The returned value is a floating-point number representing the time difference - * between the current time and the time when the Timer instance was initialized. - * - * @returns The elapsed time in seconds as a number. - */ + public s() { return (new Date().getTime() - this.start) / 1000; } From e9025a17e3f685bafc496f15ecd3805edd868ab3 Mon Sep 17 00:00:00 2001 From: Orloaft Date: Thu, 13 Apr 2023 20:19:18 -0400 Subject: [PATCH 3/5] clean up mistakes in comments --- yarn-project/ethereum.js/src/serialize/free_funcs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/ethereum.js/src/serialize/free_funcs.ts b/yarn-project/ethereum.js/src/serialize/free_funcs.ts index a410bc743b8..40b9819c8fa 100644 --- a/yarn-project/ethereum.js/src/serialize/free_funcs.ts +++ b/yarn-project/ethereum.js/src/serialize/free_funcs.ts @@ -166,7 +166,7 @@ export function serializeBufferArrayToVector(arr: Buffer[]) { * elements and applies the provided deserialization function on each element. Returns an array * of the deserialized elements and the total bytes consumed in the process. * - * @template T - The type of the deserialized elements. + * @typeparam - The type of the deserialized elements. * @param deserialize - The deserialization function to be applied on each element of the array. * @param vector - The source buffer containing the serialized data. * @param offset - The starting position in the buffer to begin deserialization (optional, default is 0). From 031688f355f1f739820ae640f5147be79c4008e3 Mon Sep 17 00:00:00 2001 From: Orloaft Date: Thu, 13 Apr 2023 21:13:28 -0400 Subject: [PATCH 4/5] remove extra characters, replace redundant byte class comments, fix formatting --- .../abi/abi-coder/ethers/abi-coder.ts | 645 +++++++++--------- .../src/contract/abi/contract_abi.ts | 78 +-- .../contract/abi/contract_abi_definition.ts | 114 ++-- .../src/contract/abi/contract_entry.ts | 14 +- .../src/contract/abi/contract_error_entry.ts | 90 +-- .../src/contract/abi/contract_event_entry.ts | 42 +- .../contract/abi/contract_function_entry.ts | 86 +-- .../ethereum.js/src/contract/bytes.ts | 236 +------ .../src/contract/constructor_interaction.ts | 16 +- .../ethereum.js/src/contract/contract.test.ts | 12 +- .../ethereum.js/src/contract/contract.ts | 168 ++--- .../src/contract/contract_tx_receipt.ts | 124 ++-- .../ethereum.js/src/contract/decode_error.ts | 24 +- .../src/contract/function_interaction.ts | 158 ++--- .../ethereum.js/src/contract/gen_def/index.ts | 2 +- .../src/contract/gen_def/sources/config.ts | 126 ++-- .../src/contract/gen_def/sources/index.ts | 12 +- .../gen_def/sources/source-foundry.ts | 17 +- .../gen_def/sources/source-truffle.ts | 19 +- .../src/contract/sent_contract_tx.ts | 26 +- .../src/contract/sent_deploy_contract_tx.ts | 18 +- .../src/eth_account/eth_account.ts | 190 +++--- .../ethereum.js/src/eth_rpc/ethereum_rpc.ts | 312 ++++----- .../ethereum.js/src/eth_rpc/sent_tx.ts | 56 +- .../ethereum.js/src/eth_rpc/tx_hash.ts | 108 +-- .../src/eth_rpc/types/block_response.ts | 240 +++---- .../src/eth_rpc/types/call_request.ts | 84 +-- .../src/eth_rpc/types/estimate_gas_request.ts | 84 +-- .../src/eth_rpc/types/log_request.ts | 54 +- .../src/eth_rpc/types/log_response.ts | 122 ++-- .../src/eth_rpc/types/transaction_receipt.ts | 132 ++-- .../src/eth_rpc/types/transaction_request.ts | 48 +- .../src/eth_rpc/types/transaction_response.ts | 204 +++--- yarn-project/ethereum.js/src/eth_sign/sign.ts | 82 +-- .../src/eth_transaction/eth_transaction.ts | 48 +- .../src/eth_transaction/sign_transaction.ts | 18 +- .../src/eth_typed_data/typed_data.ts | 65 +- .../ethereum.js/src/eth_wallet/eth_wallet.ts | 232 +++---- .../ethereum.js/src/keystore/index.test.ts | 24 +- .../ethereum.js/src/keystore/index.ts | 180 ++--- yarn-project/ethereum.js/src/log/console.ts | 6 +- yarn-project/ethereum.js/src/log/debug.ts | 6 - .../src/provider/ethereum_provider.ts | 48 +- .../src/provider/json_rpc_provider.ts | 66 +- .../src/provider/wallet_provider.ts | 428 ++++++------ .../ethereum.js/src/provider/web3_adapter.ts | 46 +- .../ethereum.js/src/provider/web3_provider.ts | 66 +- yarn-project/ethereum.js/src/retry/index.ts | 2 - .../ethereum.js/src/serialize/deserializer.ts | 46 +- .../ethereum.js/src/serialize/free_funcs.ts | 20 +- .../ethereum.js/src/serialize/serializer.ts | 110 +-- yarn-project/ethereum.js/src/sleep/index.ts | 8 +- yarn-project/ethereum.js/src/timer/index.ts | 7 +- 53 files changed, 2503 insertions(+), 2666 deletions(-) diff --git a/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts b/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts index 57658916c67..04afebad9d4 100644 --- a/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts +++ b/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts @@ -12,21 +12,21 @@ const MaxUint256 = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffff */ type ParamType = { /** - * The name of the parameter or variable. - */ -name?: string; + * The name of the parameter or variable. + */ + name?: string; /** - * The data type for a specific parameter. - */ -type: string; + * The data type for a specific parameter. + */ + type: string; /** - * Indicates whether the event parameter is indexed or not. - */ -indexed?: boolean; + * Indicates whether the event parameter is indexed or not. + */ + indexed?: boolean; /** - * An array of component objects representing the structure and types of a tuple. - */ -components?: Array; + * An array of component objects representing the structure and types of a tuple. + */ + components?: Array; }; // type EventFragment = { @@ -79,25 +79,25 @@ function verifyType(type: string): string { */ type ParseState = { /** - * Indicates whether an array type is allowed. - */ -allowArray?: boolean; + * Indicates whether an array type is allowed. + */ + allowArray?: boolean; /** - * Determines if a name is allowed for the parameter. - */ -allowName?: boolean; + * Determines if a name is allowed for the parameter. + */ + allowName?: boolean; /** - * Indicates whether parameters are allowed for the current node. - */ -allowParams?: boolean; + * Indicates whether parameters are allowed for the current node. + */ + allowParams?: boolean; /** - * Determines if type can be accepted or not. - */ -allowType?: boolean; + * Determines if type can be accepted or not. + */ + allowType?: boolean; /** - * Indicates whether the array is being read during parsing. - */ -readArray?: boolean; + * Indicates whether the array is being read during parsing. + */ + readArray?: boolean; }; /** @@ -105,29 +105,29 @@ readArray?: boolean; */ type ParseNode = { /** - * The parent node of the current parse tree. - */ -parent?: any; + * The parent node of the current parse tree. + */ + parent?: any; /** - * The data type of the parameter. - */ -type?: string; + * The data type of the parameter. + */ + type?: string; /** - * The name representing an identifiable entity. - */ -name?: string; + * The name representing an identifiable entity. + */ + name?: string; /** - * Represents the current state of parsing in a given node. - */ -state?: ParseState; + * Represents the current state of parsing in a given node. + */ + state?: ParseState; /** - * Indicates if the parameter is indexed in event logs. - */ -indexed?: boolean; + * Indicates if the parameter is indexed in event logs. + */ + indexed?: boolean; /** - * An array of nested parameter types. - */ -components?: Array; + * An array of nested parameter types. + */ + components?: Array; }; /** @@ -142,16 +142,16 @@ components?: Array; */ function parseParam(param: string, allowIndexed?: boolean): ParamType { /** - * Throws a custom error with the specified reason, code, and additional error information. - * This function is used to generate standardized error messages for better error handling - * and debugging throughout the codebase. - * - * @param reason - The main reason for the error being thrown. - * @param code - The error code associated with the particular type of error. - * @param params - An optional object containing any additional information related to the error. - * @throws {Error} A custom error with the provided details. - */ -function throwError(i: number) { + * Throws a custom error with the specified reason, code, and additional error information. + * This function is used to generate standardized error messages for better error handling + * and debugging throughout the codebase. + * + * @param reason - The main reason for the error being thrown. + * @param code - The error code associated with the particular type of error. + * @param params - An optional object containing any additional information related to the error. + * @throws {Error} A custom error with the provided details. + */ + function throwError(i: number) { throw new Error('unexpected character "' + param[i] + '" at position ' + i + ' in "' + param + '"'); } @@ -454,19 +454,22 @@ function throwError(i: number) { /////////////////////////////////// // Coders -type DecodedResult = { /** - * The number of bytes consumed during decoding. - */ -/** - * The number of bytes consumed during decoding. - */ -consumed: number; /** - * The actual data value for the corresponding coder type. - */ -/** - * The actual data value for the corresponding coder type. - */ -value: T }; +type DecodedResult = { + /** + * The number of bytes consumed during decoding. + */ + /** + * The number of bytes consumed during decoding. + */ + consumed: number; + /** + * The actual data value for the corresponding coder type. + */ + /** + * The actual data value for the corresponding coder type. + */ + value: T; +}; /** * The Coder class is an abstract base class that provides encoding and decoding functionality * for specific types in the Ethereum ABI (Application Binary Interface) format. It handles the @@ -487,25 +490,25 @@ abstract class Coder { } /** - * Encode the given value using the coder's type and rules. - * The function takes a value as input, processes it according to the specific - * coder implementation and returns a buffer containing the encoded value. - * Throws an error if the input value is not valid for the coder's type. - * - * @param value - The value to be encoded. - * @returns A Buffer containing the encoded value. - */ -abstract encode(value: any): Buffer; + * Encode the given value using the coder's type and rules. + * The function takes a value as input, processes it according to the specific + * coder implementation and returns a buffer containing the encoded value. + * Throws an error if the input value is not valid for the coder's type. + * + * @param value - The value to be encoded. + * @returns A Buffer containing the encoded value. + */ + abstract encode(value: any): Buffer; /** - * Decodes the given data buffer at the specified offset using the coder's type and properties. - * Returns an object containing the number of bytes consumed during decoding and the decoded value. - * Throws an error if there is insufficient data or any issues encountered during the decoding process. - * - * @param data - The input data buffer to be decoded. - * @param offset - The starting position in the data buffer where decoding should begin. - * @returns A DecodedResult object with the 'consumed' and 'value' properties. - */ -abstract decode(data: Buffer, offset: number): DecodedResult; + * Decodes the given data buffer at the specified offset using the coder's type and properties. + * Returns an object containing the number of bytes consumed during decoding and the decoded value. + * Throws an error if there is insufficient data or any issues encountered during the decoding process. + * + * @param data - The input data buffer to be decoded. + * @param offset - The starting position in the data buffer where decoding should begin. + * @returns A DecodedResult object with the 'consumed' and 'value' properties. + */ + abstract decode(data: Buffer, offset: number): DecodedResult; } // Clones the functionality of an existing Coder, but without a localName @@ -514,27 +517,27 @@ class CoderAnonymous extends Coder { super(coder.name, coder.type, undefined, coder.dynamic); } /** - * Encode the given value into a Buffer based on the coder type. - * This function handles various data types such as numbers, booleans, fixed bytes, and strings. - * Throws an error if the input value is invalid or not compatible with the coder type. - * - * @param value - The value to be encoded according to the coder type. - * @returns A Buffer containing the encoded value. - */ -encode(value: any): Buffer { + * Encode the given value into a Buffer based on the coder type. + * This function handles various data types such as numbers, booleans, fixed bytes, and strings. + * Throws an error if the input value is invalid or not compatible with the coder type. + * + * @param value - The value to be encoded according to the coder type. + * @returns A Buffer containing the encoded value. + */ + encode(value: any): Buffer { return this.coder.encode(value); } /** - * Decodes the given data starting from the specified offset using the associated coder. - * Returns an object containing the consumed bytes and the decoded value. - * Throws an error if there is insufficient data for decoding or any other issue occurs during decoding. - * - * @param data - The buffer containing the encoded data to be decoded. - * @param offset - The position in the buffer where the decoding should start. - * @returns An object with 'consumed' property indicating the number of bytes consumed during decoding, - * and 'value' property holding the decoded value. - */ -decode(data: Buffer, offset: number): DecodedResult { + * Decodes the given data starting from the specified offset using the associated coder. + * Returns an object containing the consumed bytes and the decoded value. + * Throws an error if there is insufficient data for decoding or any other issue occurs during decoding. + * + * @param data - The buffer containing the encoded data to be decoded. + * @param offset - The position in the buffer where the decoding should start. + * @returns An object with 'consumed' property indicating the number of bytes consumed during decoding, + * and 'value' property holding the decoded value. + */ + decode(data: Buffer, offset: number): DecodedResult { return this.coder.decode(data, offset); } } @@ -551,31 +554,31 @@ class CoderNull extends Coder { } /** - * Encode the given value using the Coder's type and rules. - * Converts various data types (boolean, number, string, etc.) into a Buffer representation - * based on the ABI encoding specifications. Throws an error if the input value is invalid - * or cannot be encoded according to the Coder's rules. - * - * @param value - The value to be encoded according to the Coder's type and rules. - * @returns A Buffer containing the encoded representation of the input value. - */ -encode(): Buffer { + * Encode the given value using the Coder's type and rules. + * Converts various data types (boolean, number, string, etc.) into a Buffer representation + * based on the ABI encoding specifications. Throws an error if the input value is invalid + * or cannot be encoded according to the Coder's rules. + * + * @param value - The value to be encoded according to the Coder's type and rules. + * @returns A Buffer containing the encoded representation of the input value. + */ + encode(): Buffer { return Buffer.alloc(0); } /** - * Decodes the provided data buffer starting from the given offset and returns an object with - * the decoded value and the number of bytes consumed during the decoding process. - * This function is used to decode ABI-encoded data for the specific coder type. - * - * @param data - The buffer containing the ABI-encoded data to be decoded. - * @param offset - The index at which to start decoding in the data buffer. - * @returns An object with the following properties: - * - `value`: The decoded value according to the coder type. - * - `consumed`: The number of bytes consumed during the decoding process. - * @throws An error if there is insufficient data or the data is invalid for the coder type. - */ -decode(data: Buffer, offset: number): DecodedResult { + * Decodes the provided data buffer starting from the given offset and returns an object with + * the decoded value and the number of bytes consumed during the decoding process. + * This function is used to decode ABI-encoded data for the specific coder type. + * + * @param data - The buffer containing the ABI-encoded data to be decoded. + * @param offset - The index at which to start decoding in the data buffer. + * @returns An object with the following properties: + * - `value`: The decoded value according to the coder type. + * - `consumed`: The number of bytes consumed during the decoding process. + * @throws An error if there is insufficient data or the data is invalid for the coder type. + */ + decode(data: Buffer, offset: number): DecodedResult { if (offset > data.length) { throw new Error('invalid null'); } @@ -605,16 +608,16 @@ class CoderNumber extends Coder { } /** - * Encodes the given array of values according to the CoderArray rules. - * The input value must be an array, and its length should match - * the length specified in the CoderArray instance. If the length is dynamic, - * any number of elements are allowed. Throws an error if the input is not an array - * or its length does not match the expected length. - * - * @param value - The array of values to be encoded. - * @returns A Buffer containing the encoded data. - */ -encode(value: any): Buffer { + * Encodes the given array of values according to the CoderArray rules. + * The input value must be an array, and its length should match + * the length specified in the CoderArray instance. If the length is dynamic, + * any number of elements are allowed. Throws an error if the input is not an array + * or its length does not match the expected length. + * + * @param value - The array of values to be encoded. + * @returns A Buffer containing the encoded data. + */ + encode(value: any): Buffer { try { let v = BigInt(value); if (this.signed) { @@ -649,15 +652,15 @@ encode(value: any): Buffer { } /** - * Decodes the provided data buffer at the specified offset using the current coder instance. - * Consumes a certain number of bytes from the data buffer and returns the decoded value along with the consumed byte count. - * Throws an error if there is insufficient data or any issues while decoding the given data. - * - * @param data - The data buffer to decode. - * @param offset - The starting offset in the data buffer for decoding. - * @returns An object containing the decoded value and the number of bytes consumed from the data buffer. - */ -decode(data: Buffer, offset: number): DecodedResult { + * Decodes the provided data buffer at the specified offset using the current coder instance. + * Consumes a certain number of bytes from the data buffer and returns the decoded value along with the consumed byte count. + * Throws an error if there is insufficient data or any issues while decoding the given data. + * + * @param data - The data buffer to decode. + * @param offset - The starting offset in the data buffer for decoding. + * @returns An object containing the decoded value and the number of bytes consumed from the data buffer. + */ + decode(data: Buffer, offset: number): DecodedResult { if (data.length < offset + 32) { errors.throwError('insufficient data for ' + this.name + ' type', errors.INVALID_ARGUMENT, { arg: this.localName, @@ -693,26 +696,26 @@ class CoderBoolean extends Coder { } /** - * Encodes the given value using the appropriate Coder, resulting in a Buffer. - * The encoded data can be later decoded using the corresponding 'decode' function. - * Throws an error if the input value is invalid or not compatible with the Coder type. - * - * @param value - The value to be encoded according to the Coder's type. - * @returns A Buffer containing the encoded data. - */ -encode(value: boolean): Buffer { + * Encodes the given value using the appropriate Coder, resulting in a Buffer. + * The encoded data can be later decoded using the corresponding 'decode' function. + * Throws an error if the input value is invalid or not compatible with the Coder type. + * + * @param value - The value to be encoded according to the Coder's type. + * @returns A Buffer containing the encoded data. + */ + encode(value: boolean): Buffer { return uint256Coder.encode(value ? 1 : 0); } /** - * Decodes the binary data from the provided buffer using the coder's associated type and offset. - * Throws an error if there is insufficient data, or if the decoded value does not match the expected format. - * - * @param data - The buffer containing the binary data to decode. - * @param offset - The starting position within the buffer to begin decoding. - * @returns An object containing the number of bytes consumed and the decoded value of the specified type. - */ -decode(data: Buffer, offset: number): DecodedResult { + * Decodes the binary data from the provided buffer using the coder's associated type and offset. + * Throws an error if there is insufficient data, or if the decoded value does not match the expected format. + * + * @param data - The buffer containing the binary data to decode. + * @param offset - The starting position within the buffer to begin decoding. + * @returns An object containing the number of bytes consumed and the decoded value of the specified type. + */ + decode(data: Buffer, offset: number): DecodedResult { try { const result = uint256Coder.decode(data, offset); return { @@ -746,16 +749,16 @@ class CoderFixedBytes extends Coder { } /** - * Encodes the given value using the coder and returns a Buffer. - * This function handles various data types such as numbers, booleans, fixed bytes, - * addresses, dynamic bytes, strings, arrays and tuples. It validates the input value - * based on the coder properties and converts them into a suitable binary format - * compatible with Ethereum encoding standards. - * - * @param value - The value to be encoded. - * @returns A Buffer containing the encoded value. - */ -encode(value: Buffer | string): Buffer { + * Encodes the given value using the coder and returns a Buffer. + * This function handles various data types such as numbers, booleans, fixed bytes, + * addresses, dynamic bytes, strings, arrays and tuples. It validates the input value + * based on the coder properties and converts them into a suitable binary format + * compatible with Ethereum encoding standards. + * + * @param value - The value to be encoded. + * @returns A Buffer containing the encoded value. + */ + encode(value: Buffer | string): Buffer { if (typeof value === 'string') { value = hexToBuffer(value); } @@ -776,15 +779,15 @@ encode(value: Buffer | string): Buffer { } /** - * Decode the given data buffer starting from the specified offset using the implemented coder. - * Returns an object containing the decoded value and the number of bytes consumed during decoding. - * Throws an error if the input data is insufficient or invalid for the implemented coder type. - * - * @param data - The data buffer to be decoded. - * @param offset - The starting index for decoding in the data buffer. - * @returns DecodedResult object containing the decoded value and the consumed bytes count. - */ -decode(data: Buffer, offset: number): DecodedResult { + * Decode the given data buffer starting from the specified offset using the implemented coder. + * Returns an object containing the decoded value and the number of bytes consumed during decoding. + * Throws an error if the input data is insufficient or invalid for the implemented coder type. + * + * @param data - The data buffer to be decoded. + * @param offset - The starting index for decoding in the data buffer. + * @returns DecodedResult object containing the decoded value and the consumed bytes count. + */ + decode(data: Buffer, offset: number): DecodedResult { if (data.length < offset + 32) { errors.throwError('insufficient data for ' + name + ' type', errors.INVALID_ARGUMENT, { arg: this.localName, @@ -814,16 +817,16 @@ class CoderAddress extends Coder { } /** - * Encode the provided value according to the Coder type rules. - * This function converts any given value into a Buffer format based on the specific - * encoding rules defined for each Coder type, such as address, boolean, number, etc. - * Throws an error if the input value is not compatible with the Coder type or if - * any internal encoding operation fails. - * - * @param value - The value to be encoded according to the Coder rules. - * @returns A Buffer instance containing the encoded value. - */ -encode(value: EthAddress | string): Buffer { + * Encode the provided value according to the Coder type rules. + * This function converts any given value into a Buffer format based on the specific + * encoding rules defined for each Coder type, such as address, boolean, number, etc. + * Throws an error if the input value is not compatible with the Coder type or if + * any internal encoding operation fails. + * + * @param value - The value to be encoded according to the Coder rules. + * @returns A Buffer instance containing the encoded value. + */ + encode(value: EthAddress | string): Buffer { if (typeof value === 'string') { value = EthAddress.fromString(value); } @@ -839,16 +842,16 @@ encode(value: EthAddress | string): Buffer { } /** - * Decode the data buffer at the given offset according to the coder's type. - * This function extracts and interprets the relevant data from the buffer based on the coder specification, - * consuming a specific number of bytes in the process. It returns an object containing the decoded value - * and the number of bytes consumed during decoding. - * - * @param data - The data buffer to decode. - * @param offset - The starting offset within the data buffer to begin decoding. - * @returns An object containing the decoded value and the number of bytes consumed during decoding. - */ -decode(data: Buffer, offset: number): DecodedResult { + * Decode the data buffer at the given offset according to the coder's type. + * This function extracts and interprets the relevant data from the buffer based on the coder specification, + * consuming a specific number of bytes in the process. It returns an object containing the decoded value + * and the number of bytes consumed during decoding. + * + * @param data - The data buffer to decode. + * @param offset - The starting offset within the data buffer to begin decoding. + * @returns An object containing the decoded value and the number of bytes consumed during decoding. + */ + decode(data: Buffer, offset: number): DecodedResult { if (data.length < offset + 32) { errors.throwError('insufficuent data for address type', errors.INVALID_ARGUMENT, { arg: this.localName, @@ -923,7 +926,7 @@ function _decodeDynamicBytes(data: Buffer, offset: number, localName: string): D /** * The CoderDynamicBytes class is a coder for encoding and decoding dynamic bytes data types in ABI. - * It handles the variable-length byte arrays, allowing efficient serialization and deserialization of + * It handles the variable-length byte arrays, allowing efficient serialization and deserialization of * such data while interacting with the Ethereum blockchain through smart contracts. The class extends the * base Coder class and overrides its methods to provide specific implementation for dynamic bytes. */ @@ -933,15 +936,15 @@ class CoderDynamicBytes extends Coder { } /** - * Encodes the input values according to the specified ABI types, returning a hex-encoded string of the packed data. - * This function takes an array of types and an array of corresponding values as input, and generates a representation - * that can be used in Ethereum smart contracts for function calls or events. - * - * @param types - An array of strings or ParamType objects describing the types of the input values. - * @param values - An array of input values matching the types specified in the "types" parameter. - * @returns A hex-encoded string representing the packed data according to the ABI types. - */ -encode(value: Buffer | string): Buffer { + * Encodes the input values according to the specified ABI types, returning a hex-encoded string of the packed data. + * This function takes an array of types and an array of corresponding values as input, and generates a representation + * that can be used in Ethereum smart contracts for function calls or events. + * + * @param types - An array of strings or ParamType objects describing the types of the input values. + * @param values - An array of input values matching the types specified in the "types" parameter. + * @returns A hex-encoded string representing the packed data according to the ABI types. + */ + encode(value: Buffer | string): Buffer { try { if (typeof value === 'string') { value = hexToBuffer(value); @@ -957,17 +960,17 @@ encode(value: Buffer | string): Buffer { } /** - * Decodes the given data according to the specified parameter types. - * The types array represents the data types of the expected decoding results, - * where each type is either a string or a ParamType object. - * The data argument should be a buffer containing the encoded data. - * Returns an array of decoded values, with each value corresponding to the provided types. - * - * @param types - An array of strings or ParamType objects representing the data types to decode. - * @param data - A Buffer containing the encoded data to be decoded. - * @returns An array of decoded values corresponding to the specified types. - */ -decode(data: Buffer, offset: number): DecodedResult { + * Decodes the given data according to the specified parameter types. + * The types array represents the data types of the expected decoding results, + * where each type is either a string or a ParamType object. + * The data argument should be a buffer containing the encoded data. + * Returns an array of decoded values, with each value corresponding to the provided types. + * + * @param types - An array of strings or ParamType objects representing the data types to decode. + * @param data - A Buffer containing the encoded data to be decoded. + * @returns An array of decoded values corresponding to the specified types. + */ + decode(data: Buffer, offset: number): DecodedResult { const result = _decodeDynamicBytes(data, offset, this.localName); result.value = bufferToHex(result.value); return result; @@ -986,16 +989,16 @@ class CoderString extends Coder { } /** - * Encodes the given types and values into a single ABI-formatted hex string. - * The types array should contain a list of type strings or ParamType objects that describe each value's type. - * The values array should have the same length as the types array and contain the data to be encoded. - * Throws an error if the types/values length mismatch or if any invalid argument is encountered during encoding. - * - * @param types - An array of type strings or ParamType objects describing each value's type. - * @param values - An array of values corresponding to the types provided. - * @returns A hex-encoded ABI-formatted string representing the encoded values. - */ -encode(value: string): Buffer { + * Encodes the given types and values into a single ABI-formatted hex string. + * The types array should contain a list of type strings or ParamType objects that describe each value's type. + * The values array should have the same length as the types array and contain the data to be encoded. + * Throws an error if the types/values length mismatch or if any invalid argument is encountered during encoding. + * + * @param types - An array of type strings or ParamType objects describing each value's type. + * @param values - An array of values corresponding to the types provided. + * @returns A hex-encoded ABI-formatted string representing the encoded values. + */ + encode(value: string): Buffer { if (typeof value !== 'string') { errors.throwError('invalid string value', errors.INVALID_ARGUMENT, { arg: this.localName, @@ -1007,17 +1010,17 @@ encode(value: string): Buffer { } /** - * Decodes the ABI-encoded data based on the specified input types. - * Takes an array of input types (strings or ParamType objects) and a buffer containing - * the ABI-encoded data. Returns an array or an object containing the decoded values, depending - * on whether the local names are available in the input types. If any error occurs during decoding, - * it throws an exception with a detailed message about the issue. - * - * @param types - An array of input types, either as strings or ParamType objects. - * @param data - A Buffer containing the ABI-encoded data to decode. - * @returns An array or an object containing the decoded values based on the input types. - */ -decode(data: Buffer, offset: number): DecodedResult { + * Decodes the ABI-encoded data based on the specified input types. + * Takes an array of input types (strings or ParamType objects) and a buffer containing + * the ABI-encoded data. Returns an array or an object containing the decoded values, depending + * on whether the local names are available in the input types. If any error occurs during decoding, + * it throws an exception with a detailed message about the issue. + * + * @param types - An array of input types, either as strings or ParamType objects. + * @param data - A Buffer containing the ABI-encoded data to decode. + * @returns An array or an object containing the decoded values based on the input types. + */ + decode(data: Buffer, offset: number): DecodedResult { const result = _decodeDynamicBytes(data, offset, this.localName); result.value = new TextDecoder('utf-8').decode(result.value); return result; @@ -1069,19 +1072,22 @@ function pack(coders: Array, values: Array): Buffer { }); } - const parts: Array<{ /** - * Indicates if the coder has a dynamic size. - */ -/** - * Indicates if the coder has a dynamic size. - */ -dynamic: boolean; /** - * The encoded or decoded value based on the ABI data type. - */ -/** - * The encoded or decoded value based on the ABI data type. - */ -value: any }> = []; + const parts: Array<{ + /** + * Indicates if the coder has a dynamic size. + */ + /** + * Indicates if the coder has a dynamic size. + */ + dynamic: boolean; + /** + * The encoded or decoded value based on the ABI data type. + */ + /** + * The encoded or decoded value based on the ABI data type. + */ + value: any; + }> = []; coders.forEach(function (coder, index) { parts.push({ dynamic: coder.dynamic, value: coder.encode(values[index]) }); @@ -1195,18 +1201,18 @@ class CoderArray extends Coder { } /** - * Encode the given input types and values into a hexadecimal string according to the ABI specification. - * The function takes an array of types and values, and encodes them into a single data string, - * which can be used for contract function calls or event encoding. The types array should contain - * strings representing Ethereum Solidity types (e.g. 'uint256', 'address', 'bytes32'), - * and the values array should contain corresponding JavaScript values to be encoded. - * Throws an error if the types and values length mismatch or if there's an issue during encoding. - * - * @param types - An array of strings or ParamType objects representing the Ethereum Solidity types. - * @param values - An array of JavaScript values corresponding to the input types. - * @returns A hex-encoded string of the encoded input types and values. - */ -encode(value: Array): Buffer { + * Encode the given input types and values into a hexadecimal string according to the ABI specification. + * The function takes an array of types and values, and encodes them into a single data string, + * which can be used for contract function calls or event encoding. The types array should contain + * strings representing Ethereum Solidity types (e.g. 'uint256', 'address', 'bytes32'), + * and the values array should contain corresponding JavaScript values to be encoded. + * Throws an error if the types and values length mismatch or if there's an issue during encoding. + * + * @param types - An array of strings or ParamType objects representing the Ethereum Solidity types. + * @param values - An array of JavaScript values corresponding to the input types. + * @returns A hex-encoded string of the encoded input types and values. + */ + encode(value: Array): Buffer { if (!Array.isArray(value)) { errors.throwError('expected array value', errors.INVALID_ARGUMENT, { arg: this.localName, @@ -1234,15 +1240,15 @@ encode(value: Array): Buffer { } /** - * Decodes the ABI (Application Binary Interface) encoded data based on the specified types. - * The function takes an array of type descriptors and a buffer containing the ABI encoded data, - * and returns an object with decoded values. - * - * @param {Array} types - An array of type descriptors, either as strings or ParamType objects. - * @param {Buffer} data - A Buffer containing the ABI encoded data to be decoded. - * @returns {any} An object with the decoded values based on the provided types. - */ -decode(data: Buffer, offset: number) { + * Decodes the ABI (Application Binary Interface) encoded data based on the specified types. + * The function takes an array of type descriptors and a buffer containing the ABI encoded data, + * and returns an object with decoded values. + * + * @param {Array} types - An array of type descriptors, either as strings or ParamType objects. + * @param {Buffer} data - A Buffer containing the ABI encoded data to be decoded. + * @returns {any} An object with the decoded values based on the provided types. + */ + decode(data: Buffer, offset: number) { // @TODO: //if (data.length < offset + length * 32) { throw new Error('invalid array'); } @@ -1286,7 +1292,7 @@ decode(data: Buffer, offset: number) { /** * The CoderTuple class is responsible for encoding and decoding tuple data types in the ABI encoding format. - * It extends the Coder class and takes an array of coders representing each component. + * It extends the Coder class and takes an array of coders representing each component. * When encoding, it processes the components using the appropriate coder instances and returns the encoded data. * When decoding, it parses the encoded data and constructs the tuple by applying each coder's decode method to their respective components. */ @@ -1307,31 +1313,31 @@ class CoderTuple extends Coder { } /** - * Encodes the given function signature with the corresponding parameter types and values. - * This function takes an array of parameter types, such as strings or ParamType objects, - * and an array of corresponding parameter values to generate the ABI-encoded data. - * The generated encoded data is useful for interacting with smart contracts. - * Throws an error if the length of the input types and values mismatch. - * - * @param types - An array of parameter types represented as strings or ParamType objects. - * @param values - An array of corresponding values to be encoded with the parameter types. - * @returns A hex-encoded string representing the ABI-encoded data. - */ -encode(value: Array): Buffer { + * Encodes the given function signature with the corresponding parameter types and values. + * This function takes an array of parameter types, such as strings or ParamType objects, + * and an array of corresponding parameter values to generate the ABI-encoded data. + * The generated encoded data is useful for interacting with smart contracts. + * Throws an error if the length of the input types and values mismatch. + * + * @param types - An array of parameter types represented as strings or ParamType objects. + * @param values - An array of corresponding values to be encoded with the parameter types. + * @returns A hex-encoded string representing the ABI-encoded data. + */ + encode(value: Array): Buffer { return pack(this.coders, value); } /** - * Decodes the provided data using the specified input types and returns an array of decoded values. - * The input 'types' is an array of either strings or ParamType objects representing the expected data types. - * The input 'data' should be a Buffer containing the encoded data to decode. - * Throws an error if the number of input types does not match the number of values in the data or if decoding fails. - * - * @param types - Array of strings or ParamType objects representing the expected data types. - * @param data - Buffer containing the encoded data to decode. - * @returns An array of decoded values. - */ -decode(data: Buffer, offset: number): DecodedResult { + * Decodes the provided data using the specified input types and returns an array of decoded values. + * The input 'types' is an array of either strings or ParamType objects representing the expected data types. + * The input 'data' should be a Buffer containing the encoded data to decode. + * Throws an error if the number of input types does not match the number of values in the data or if decoding fails. + * + * @param types - Array of strings or ParamType objects representing the expected data types. + * @param data - Buffer containing the encoded data to decode. + * @returns An array of decoded values. + */ + decode(data: Buffer, offset: number): DecodedResult { const result = unpack(this.coders, data, offset); return result; } @@ -1468,16 +1474,16 @@ export class AbiCoder { constructor() {} /** - * Encodes the given types and values into a hex-encoded ABI string. - * Takes an array of types (strings or ParamType objects) and an array of corresponding values. - * Each type in the 'types' array should have a corresponding value in the 'values' array. - * Throws an error if the length of types and values arrays do not match, or if there are any issues during encoding. - * - * @param types - An array of strings or ParamType objects representing the data types. - * @param values - An array of values corresponding to the types. - * @returns A hex-encoded string representing the encoded ABI data. - */ -encode(types: Array, values: Array): string { + * Encodes the given types and values into a hex-encoded ABI string. + * Takes an array of types (strings or ParamType objects) and an array of corresponding values. + * Each type in the 'types' array should have a corresponding value in the 'values' array. + * Throws an error if the length of types and values arrays do not match, or if there are any issues during encoding. + * + * @param types - An array of strings or ParamType objects representing the data types. + * @param values - An array of values corresponding to the types. + * @returns A hex-encoded string representing the encoded ABI data. + */ + encode(types: Array, values: Array): string { if (types.length !== values.length) { errors.throwError('types/values length mismatch', errors.INVALID_ARGUMENT, { count: { types: types.length, values: values.length }, @@ -1504,19 +1510,18 @@ encode(types: Array, values: Array): string { return bufferToHex(new CoderTuple(coders, '_').encode(values)); } - ``` -/** - * Decodes the ABI-encoded data using the provided array of types and returns the corresponding values. - * Each type can be a string or a ParamType object, which includes type information and an optional name. - * The input 'data' should be a valid ABI-encoded Buffer. - * Throws an error if the types and data do not match, or if any decoding issues occur. - * - * @param types - An array of strings or ParamType objects representing the expected types of the decoded data. - * @param data - A Buffer containing the ABI-encoded data to be decoded. - * @returns An array or an object containing the decoded values, with optional keys if names are provided in the types. - */ -``` -decode(types: Array, data: Buffer): any { + /** + * Decodes the ABI-encoded data using the provided array of types and returns the corresponding values. + * Each type can be a string or a ParamType object, which includes type information and an optional name. + * The input 'data' should be a valid ABI-encoded Buffer. + * Throws an error if the types and data do not match, or if any decoding issues occur. + * + * @param types - An array of strings or ParamType objects representing the expected types of the decoded data. + * @param data - A Buffer containing the ABI-encoded data to be decoded. + * @returns An array or an object containing the decoded values, with optional keys if names are provided in the types. + */ + + decode(types: Array, data: Buffer): any { const coders = types.map(type => { if (typeof type === 'string') { type = parseParam(type); diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_abi.ts b/yarn-project/ethereum.js/src/contract/abi/contract_abi.ts index 37526ba0ff1..1512220018a 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_abi.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_abi.ts @@ -10,25 +10,25 @@ import { ContractAbiDefinition, ContractErrorEntry, ContractEventEntry, Contract */ export class ContractAbi { /** - * A list of contract functions. - */ -public functions: ContractFunctionEntry[]; + * A list of contract functions. + */ + public functions: ContractFunctionEntry[]; /** - * An array containing contract event entries. - */ -public events: ContractEventEntry[]; + * An array containing contract event entries. + */ + public events: ContractEventEntry[]; /** - * A collection of error entries in the contract ABI. - */ -public errors: ContractErrorEntry[]; + * A collection of error entries in the contract ABI. + */ + public errors: ContractErrorEntry[]; /** - * The constructor entry for the contract. - */ -public ctor: ContractFunctionEntry; + * The constructor entry for the contract. + */ + public ctor: ContractFunctionEntry; /** - * The fallback function to be executed when no other function matches the provided signature. - */ -public fallback?: ContractFunctionEntry; + * The fallback function to be executed when no other function matches the provided signature. + */ + public fallback?: ContractFunctionEntry; constructor(definition: ContractAbiDefinition) { this.functions = definition.filter(e => e.type === 'function').map(entry => new ContractFunctionEntry(entry)); @@ -43,26 +43,26 @@ public fallback?: ContractFunctionEntry; } /** - * Find the matching event entry for a given log response in the contract ABI. - * This function iterates through the events defined in the ABI and compares their signatures with the log's topic. - * Returns the first matching event entry, or undefined if no match is found. - * - * @param log - The LogResponse object containing the log data to be matched against event signatures. - * @returns A ContractEventEntry instance that matches the log's topic, or undefined if no match is found. - */ -public findEntryForLog(log: LogResponse) { + * Find the matching event entry for a given log response in the contract ABI. + * This function iterates through the events defined in the ABI and compares their signatures with the log's topic. + * Returns the first matching event entry, or undefined if no match is found. + * + * @param log - The LogResponse object containing the log data to be matched against event signatures. + * @returns A ContractEventEntry instance that matches the log's topic, or undefined if no match is found. + */ + public findEntryForLog(log: LogResponse) { return this.events.find(abiDef => abiDef.signature === log.topics[0]); } /** - * Decodes the event log data using the Contract ABI event definitions. - * Finds the matching event signature in the ABI, then decodes the log data accordingly. - * Throws an error if no matching event signature is found for the given log. - * - * @param log - The LogResponse object containing the event log data to be decoded. - * @returns A decoded event object with event name and decoded parameters. - */ -public decodeEvent(log: LogResponse) { + * Decodes the event log data using the Contract ABI event definitions. + * Finds the matching event signature in the ABI, then decodes the log data accordingly. + * Throws an error if no matching event signature is found for the given log. + * + * @param log - The LogResponse object containing the event log data to be decoded. + * @returns A decoded event object with event name and decoded parameters. + */ + public decodeEvent(log: LogResponse) { const event = this.findEntryForLog(log); if (!event) { throw new Error(`Unable to find matching event signature for log: ${log.id}`); @@ -71,14 +71,14 @@ public decodeEvent(log: LogResponse) { } /** - * Decodes the function data from a given buffer and returns the decoded parameters. - * The input 'data' should contain the first 4 bytes as the function signature, followed by the encoded parameters. - * Returns undefined if no matching function is found in the ABI for the provided signature. - * - * @param data - The buffer containing the function signature and encoded parameters. - * @returns An object with the decoded parameters or undefined if no matching function is found. - */ -public decodeFunctionData(data: Buffer) { + * Decodes the function data from a given buffer and returns the decoded parameters. + * The input 'data' should contain the first 4 bytes as the function signature, followed by the encoded parameters. + * Returns undefined if no matching function is found in the ABI for the provided signature. + * + * @param data - The buffer containing the function signature and encoded parameters. + * @returns An object with the decoded parameters or undefined if no matching function is found. + */ + public decodeFunctionData(data: Buffer) { const funcSig = bufferToHex(data.subarray(0, 4)); const func = this.functions.find(f => f.signature === funcSig); return func ? func.decodeParameters(data.slice(4)) : undefined; diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_abi_definition.ts b/yarn-project/ethereum.js/src/contract/abi/contract_abi_definition.ts index e9beed6f792..2c97fd32066 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_abi_definition.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_abi_definition.ts @@ -10,25 +10,25 @@ export type AbiDataTypes = 'bool' | 'string' | 'address' | 'function' | 'uint' | */ export type AbiInput = { /** - * Represents the structure of nested tuple elements. - */ -components?: any; + * Represents the structure of nested tuple elements. + */ + components?: any; /** - * The name identifier for the contract entry. - */ -name: string; + * The name identifier for the contract entry. + */ + name: string; /** - * Represents the type of a Contract Entry in the ABI (Application Binary Interface) definition. - */ -type: AbiDataTypes; + * Represents the type of a Contract Entry in the ABI (Application Binary Interface) definition. + */ + type: AbiDataTypes; /** - * Indicates if the parameter is indexed in events. - */ -indexed?: boolean; + * Indicates if the parameter is indexed in events. + */ + indexed?: boolean; /** - * The internal representation of the data type. - */ -internalType?: string; + * The internal representation of the data type. + */ + internalType?: string; }; /** @@ -36,21 +36,21 @@ internalType?: string; */ export type AbiOutput = { /** - * Nested structure defining the data type components. - */ -components?: any; + * Nested structure defining the data type components. + */ + components?: any; /** - * The name identifier of the contract entry. - */ -name: string; + * The name identifier of the contract entry. + */ + name: string; /** - * The type of contract entry, such as function, constructor, event, fallback, error, or receive. - */ -type: AbiDataTypes; + * The type of contract entry, such as function, constructor, event, fallback, error, or receive. + */ + type: AbiDataTypes; /** - * Represents the internal Solidity type of the input/output. - */ -internalType?: string; + * Represents the internal Solidity type of the input/output. + */ + internalType?: string; }; /** @@ -60,45 +60,45 @@ internalType?: string; */ export interface ContractEntryDefinition { /** - * Indicates if the contract entry is constant (read-only). - */ -constant?: boolean; + * Indicates if the contract entry is constant (read-only). + */ + constant?: boolean; /** - * Indicates whether the contract entry can receive Ether. - */ -payable?: boolean; + * Indicates whether the contract entry can receive Ether. + */ + payable?: boolean; /** - * Indicates if the event is anonymous, omitting event signature from logs. - */ -anonymous?: boolean; + * Indicates if the event is anonymous, omitting event signature from logs. + */ + anonymous?: boolean; /** - * An array of input parameters for the contract function or event. - */ -inputs?: AbiInput[]; + * An array of input parameters for the contract function or event. + */ + inputs?: AbiInput[]; /** - * The identifier for the contract function, event, or variable. - */ -name?: string; + * The identifier for the contract function, event, or variable. + */ + name?: string; /** - * An array of output parameters for the contract function or event. - */ -outputs?: AbiOutput[]; + * An array of output parameters for the contract function or event. + */ + outputs?: AbiOutput[]; /** - * The type of contract entry, representing its purpose and functionality. - */ -type: 'function' | 'constructor' | 'event' | 'fallback' | 'error' | 'receive'; + * The type of contract entry, representing its purpose and functionality. + */ + type: 'function' | 'constructor' | 'event' | 'fallback' | 'error' | 'receive'; /** - * Represents the mutability of a contract's state during function execution. - */ -stateMutability?: 'pure' | 'view' | 'payable' | 'nonpayable'; + * Represents the mutability of a contract's state during function execution. + */ + stateMutability?: 'pure' | 'view' | 'payable' | 'nonpayable'; /** - * The unique function identifier generated from the function's name and input types. - */ -signature?: string; + * The unique function identifier generated from the function's name and input types. + */ + signature?: string; /** - * The estimated gas cost for executing the function. - */ -gas?: number; + * The estimated gas cost for executing the function. + */ + gas?: number; } /** diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts b/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts index b22b3ee0ff0..78ca1b417da 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts @@ -19,13 +19,13 @@ export class ContractEntry { } /** - * Returns a string representation of the ContractEntry instance using ABI encoding. - * This method utilizes the 'abiCoder' module to convert the contract entry definition - * into a readable and formatted string. - * - * @returns A string representation of the ContractEntry instance with ABI encoding. - */ -public asString() { + * Returns a string representation of the ContractEntry instance using ABI encoding. + * This method utilizes the 'abiCoder' module to convert the contract entry definition + * into a readable and formatted string. + * + * @returns A string representation of the ContractEntry instance with ABI encoding. + */ + public asString() { return abiCoder.abiMethodToString(this.entry); } } diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_error_entry.ts b/yarn-project/ethereum.js/src/contract/abi/contract_error_entry.ts index 3559443c3b2..bc3fccf8c17 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_error_entry.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_error_entry.ts @@ -10,9 +10,9 @@ import { ContractEntry } from './contract_entry.js'; */ export class ContractErrorEntry extends ContractEntry { /** - * The encoded function signature for the contract entry. - */ -public readonly signature: Buffer; + * The encoded function signature for the contract entry. + */ + public readonly signature: Buffer; constructor(entry: ContractEntryDefinition) { entry.inputs = entry.inputs || []; @@ -21,27 +21,27 @@ public readonly signature: Buffer; } /** - * Retrieve the number of input arguments for this contract error entry. - * This function returns the length of the 'inputs' array, which represents - * the input arguments required by the entry. If no inputs are defined, - * it returns 0. - * - * @returns The number of input arguments for the contract error entry. - */ -public numArgs() { + * Retrieve the number of input arguments for this contract error entry. + * This function returns the length of the 'inputs' array, which represents + * the input arguments required by the entry. If no inputs are defined, + * it returns 0. + * + * @returns The number of input arguments for the contract error entry. + */ + public numArgs() { return this.entry.inputs ? this.entry.inputs.length : 0; } /** - * Decodes the return value of a contract function call using the ABI output definition. - * If there is only one output, returns the decoded output value directly; otherwise, - * returns an object containing the decoded values with the output names as keys. - * If the input returnValue buffer is empty, returns null. - * - * @param returnValue - The Buffer containing the encoded return value of the contract function call. - * @returns Decoded output value(s) or null if returnValue is empty. - */ -public decodeReturnValue(returnValue: Buffer) { + * Decodes the return value of a contract function call using the ABI output definition. + * If there is only one output, returns the decoded output value directly; otherwise, + * returns an object containing the decoded values with the output names as keys. + * If the input returnValue buffer is empty, returns null. + * + * @param returnValue - The Buffer containing the encoded return value of the contract function call. + * @returns Decoded output value(s) or null if returnValue is empty. + */ + public decodeReturnValue(returnValue: Buffer) { if (!returnValue.length) { return null; } @@ -57,39 +57,39 @@ public decodeReturnValue(returnValue: Buffer) { } /** - * Encodes the ABI (Application Binary Interface) of a function call by concatenating the function's signature - * and encoded input parameters. This resulting buffer can be used for encoding the data field of a transaction. - * The 'args' array should contain values that match the expected input types of the function. - * - * @param args - An array of arguments matching the function's input parameters. - * @returns A Buffer containing the encoded ABI for the function call. - */ -public encodeABI(args: any[]) { + * Encodes the ABI (Application Binary Interface) of a function call by concatenating the function's signature + * and encoded input parameters. This resulting buffer can be used for encoding the data field of a transaction. + * The 'args' array should contain values that match the expected input types of the function. + * + * @param args - An array of arguments matching the function's input parameters. + * @returns A Buffer containing the encoded ABI for the function call. + */ + public encodeABI(args: any[]) { return Buffer.concat([this.signature, this.encodeParameters(args)]); } /** - * Encode the input parameters according to the contract entry inputs. - * This function takes an array of arguments and encodes them into a Buffer - * following the Solidity contract's entry ABI specifications. - * - * @param args - An array of input values matching the contract entry inputs. - * @returns A Buffer containing the encoded parameters. - */ -public encodeParameters(args: any[]) { + * Encode the input parameters according to the contract entry inputs. + * This function takes an array of arguments and encodes them into a Buffer + * following the Solidity contract's entry ABI specifications. + * + * @param args - An array of input values matching the contract entry inputs. + * @returns A Buffer containing the encoded parameters. + */ + public encodeParameters(args: any[]) { return abiCoder.encodeParameters(this.entry.inputs, args); } /** - * Decode the provided bytes buffer into parameters based on the entry inputs. - * This function helps in interpreting the raw bytes buffer received from a contract call - * or an event log, by decoding it based on the ABI input types, and returning the - * decoded values as an object with the input names as keys. - * - * @param bytes - The Buffer containing the encoded parameters to be decoded. - * @returns An object with decoded parameters, keys mapped to the input names defined in the ABI. - */ -public decodeParameters(bytes: Buffer) { + * Decode the provided bytes buffer into parameters based on the entry inputs. + * This function helps in interpreting the raw bytes buffer received from a contract call + * or an event log, by decoding it based on the ABI input types, and returning the + * decoded values as an object with the input names as keys. + * + * @param bytes - The Buffer containing the encoded parameters to be decoded. + * @returns An object with decoded parameters, keys mapped to the input names defined in the ABI. + */ + public decodeParameters(bytes: Buffer) { return abiCoder.decodeParameters(this.entry.inputs, bytes); } } diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_event_entry.ts b/yarn-project/ethereum.js/src/contract/abi/contract_event_entry.ts index c30fbecf21e..71c2cd9ba38 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_event_entry.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_event_entry.ts @@ -8,16 +8,16 @@ import { ContractEntry } from './contract_entry.js'; /** * The ContractEventEntry class represents a single event entry within a smart contract. * It provides functionality to encode and decode event topics and logs, as well as - * handling filter parameters for indexed inputs of the event. This class extends the + * handling filter parameters for indexed inputs of the event. This class extends the * ContractEntry base class, adding specific features for event handling in Ethereum * contracts. By utilizing this class, users can seamlessly interact with events emitted * by a smart contract, making it easier to track and process data related to those events. */ export class ContractEventEntry extends ContractEntry { /** - * The unique event identifier derived from ABI. - */ -public readonly signature: string; + * The unique event identifier derived from ABI. + */ + public readonly signature: string; constructor(entry: ContractEntryDefinition) { super(entry); @@ -25,15 +25,15 @@ public readonly signature: string; } /** - * Generate an array of event topics by encoding the filter values provided for indexed inputs. - * For events which are not anonymous, the first topic will be the event's signature. - * Each subsequent topic corresponds to an indexed input, with null values for missing filters. - * Supports array values for indexed inputs, which will generate multiple topics for that input. - * - * @param filter - An object containing the filter values to encode as event topics. - * @returns An array of encoded event topics (Buffer or Buffer[]), including the event signature if not anonymous. - */ -public getEventTopics(filter: object = {}) { + * Generate an array of event topics by encoding the filter values provided for indexed inputs. + * For events which are not anonymous, the first topic will be the event's signature. + * Each subsequent topic corresponds to an indexed input, with null values for missing filters. + * Supports array values for indexed inputs, which will generate multiple topics for that input. + * + * @param filter - An object containing the filter values to encode as event topics. + * @returns An array of encoded event topics (Buffer or Buffer[]), including the event signature if not anonymous. + */ + public getEventTopics(filter: object = {}) { const topics: (Buffer | Buffer[])[] = []; if (!this.entry.anonymous && this.signature) { @@ -62,14 +62,14 @@ public getEventTopics(filter: object = {}) { } /** - * Decodes an event log response from a contract execution. - * The input 'log' is an object containing data and topics received from the Ethereum transaction receipt. - * This method returns an EventLog object containing the decoded event along with its metadata. - * - * @param log - The LogResponse object containing data and topics from the contract execution. - * @returns An EventLog object with the decoded event, signature, arguments, and raw data. - */ -public decodeEvent(log: LogResponse): EventLog { + * Decodes an event log response from a contract execution. + * The input 'log' is an object containing data and topics received from the Ethereum transaction receipt. + * This method returns an EventLog object containing the decoded event along with its metadata. + * + * @param log - The LogResponse object containing data and topics from the contract execution. + * @returns An EventLog object with the decoded event, signature, arguments, and raw data. + */ + public decodeEvent(log: LogResponse): EventLog { const { data = '', topics = [], ...formattedLog } = log; const { anonymous, inputs = [], name = '' } = this.entry; diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts b/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts index 6515e60729b..a82ec6d96e9 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts @@ -10,9 +10,9 @@ import { ContractEntry } from './contract_entry.js'; */ export class ContractFunctionEntry extends ContractEntry { /** - * The unique identifier of the contract function. - */ -public readonly signature: string; + * The unique identifier of the contract function. + */ + public readonly signature: string; constructor(entry: ContractEntryDefinition) { entry.inputs = entry.inputs || []; @@ -32,27 +32,27 @@ public readonly signature: string; } /** - * Returns the number of input arguments required for the contract function. - * This value is derived from the 'inputs' property of the contract entry definition. - * - * @returns The number of input arguments required for the function. - */ -public numArgs() { + * Returns the number of input arguments required for the contract function. + * This value is derived from the 'inputs' property of the contract entry definition. + * + * @returns The number of input arguments required for the function. + */ + public numArgs() { return this.entry.inputs ? this.entry.inputs.length : 0; } /** - * Decodes the return value of a contract function call. - * This method takes a Buffer containing the raw return value from a contract function call - * and decodes it according to the output parameters defined in the ABI. - * If the decoded result contains only one value, it returns that value directly; - * otherwise, an object with named properties is returned, excluding the '__length__' property. - * - * @param returnValue - The raw return value from a contract function call as a Buffer. - * @returns The decoded value(s) according to the output parameters defined in the ABI, - * either as a single value or an object with named properties. - */ -public decodeReturnValue(returnValue: Buffer) { + * Decodes the return value of a contract function call. + * This method takes a Buffer containing the raw return value from a contract function call + * and decodes it according to the output parameters defined in the ABI. + * If the decoded result contains only one value, it returns that value directly; + * otherwise, an object with named properties is returned, excluding the '__length__' property. + * + * @param returnValue - The raw return value from a contract function call as a Buffer. + * @returns The decoded value(s) according to the output parameters defined in the ABI, + * either as a single value or an object with named properties. + */ + public decodeReturnValue(returnValue: Buffer) { if (!returnValue.length) { return null; } @@ -68,37 +68,37 @@ public decodeReturnValue(returnValue: Buffer) { } /** - * Encodes the function call and its arguments into ABI format (Application Binary Interface). - * This representation is used for interacting with the Ethereum blockchain. - * The encoded result is a Buffer that can be sent as data in a transaction or used to invoke contract functions. - * - * @param args - An array of values representing the arguments to pass in the function call. - * @returns A Buffer containing the encoded function signature and parameters in ABI format. - */ -public encodeABI(args: any[]) { + * Encodes the function call and its arguments into ABI format (Application Binary Interface). + * This representation is used for interacting with the Ethereum blockchain. + * The encoded result is a Buffer that can be sent as data in a transaction or used to invoke contract functions. + * + * @param args - An array of values representing the arguments to pass in the function call. + * @returns A Buffer containing the encoded function signature and parameters in ABI format. + */ + public encodeABI(args: any[]) { return Buffer.concat([hexToBuffer(this.signature), this.encodeParameters(args)]); } /** - * Encode the provided arguments based on the contract function's input parameters. - * This is useful when preparing ABI-encoded data to interact with a smart contract function. - * Throws an error if the provided arguments don't match the expected input parameters. - * - * @param args - An array of values representing the arguments for the contract function. - * @returns A Buffer containing the ABI-encoded parameters. - */ -public encodeParameters(args: any[]) { + * Encode the provided arguments based on the contract function's input parameters. + * This is useful when preparing ABI-encoded data to interact with a smart contract function. + * Throws an error if the provided arguments don't match the expected input parameters. + * + * @param args - An array of values representing the arguments for the contract function. + * @returns A Buffer containing the ABI-encoded parameters. + */ + public encodeParameters(args: any[]) { return abiCoder.encodeParameters(this.entry.inputs, args); } /** - * Decode the parameters from a given buffer using the input types defined in the contract entry. - * This function is useful for unpacking parameters from encoded data or transaction payloads. - * - * @param bytes - The buffer containing the encoded parameters. - * @returns An object with the decoded parameters mapped to their respective names as defined in the contract entry. - */ -public decodeParameters(bytes: Buffer) { + * Decode the parameters from a given buffer using the input types defined in the contract entry. + * This function is useful for unpacking parameters from encoded data or transaction payloads. + * + * @param bytes - The buffer containing the encoded parameters. + * @returns An object with the decoded parameters mapped to their respective names as defined in the contract entry. + */ + public decodeParameters(bytes: Buffer) { return abiCoder.decodeParameters(this.entry.inputs, bytes); } } diff --git a/yarn-project/ethereum.js/src/contract/bytes.ts b/yarn-project/ethereum.js/src/contract/bytes.ts index ebce21459e6..a1e541f62d6 100644 --- a/yarn-project/ethereum.js/src/contract/bytes.ts +++ b/yarn-project/ethereum.js/src/contract/bytes.ts @@ -1,236 +1,66 @@ -/** - * The Bytes class extends the built-in Buffer class in Node.js, providing a convenient and efficient way - * to work with binary data. It is designed for use in various scenarios such as reading/writing files, - * network communication, and cryptographic operations. Each Bytes subclass (Bytes1 to Bytes32) represents - * a specific fixed-length byte array, allowing for optimized memory management and type safety. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes extends Buffer {} -/** - * Bytes1 is a class extending the Buffer, representing a binary data container with a fixed size of 1 byte. - * It provides utility methods to easily manipulate, read, and write single-byte data in a memory-efficient manner. - * Instances of Bytes1 can be used in various applications where precise control over single-byte data is required, - * such as low-level networking, binary file handling or encoding/decoding tasks. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes1 extends Buffer {} -/** - * Represents a Bytes2 class that extends the Buffer class, specifically designed to handle fixed-length byte arrays - * of size 2. This class can be used for various operations related to manipulating and processing binary data. - * Use this class when you need a compact and efficient way of storing and working with 2-byte sequences. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes2 extends Buffer {} -/** - * The Bytes3 class extends the Buffer class, representing a fixed-length binary data container of size 3 bytes. - * This class enables efficient manipulation and storage of 3-byte sequences, commonly used in various data encoding - * and communication protocols. It provides all the functionalities of the Buffer class with a predefined size constraint. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes3 extends Buffer {} -/** - * The Bytes4 class extends the Buffer class to represent a 4-byte (32-bit) sequence of data. - * It is designed to facilitate manipulation and handling of fixed-sized byte arrays, - * commonly used in various data encoding, hashing, and serialization processes. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes4 extends Buffer {} -/** - * Represents a Bytes5 class that extends the functionality of the Buffer class. - * This class can be used to store and manipulate 5-byte binary data, providing - * a convenient way to work with fixed-length byte arrays in various applications. - * The class inherits all methods and properties from the Buffer class, allowing for - * easy manipulation, comparison, and encoding/decoding of the binary data. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes5 extends Buffer {} -/** - * Bytes6 class represents a fixed-length binary data buffer with a length of 6 bytes, extending the functionality - * of the native Buffer class. This can be used for handling data structures that require precise byte lengths. - * The class provides efficient memory allocation and operations for working with 6-byte sequences. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes6 extends Buffer {} -/** - * The Bytes7 class represents a specialized Buffer with a fixed length of 7 bytes. - * This class can be used to handle binary data of specifically 7 bytes length, providing - * an efficient and convenient way to manipulate and manage such data structures. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes7 extends Buffer {} -/** - * The Bytes8 class is a specialized extension of the Buffer class designed to specifically handle - * byte arrays of length 8. It inherits all the properties and methods of the Buffer class, allowing - * for efficient management, manipulation, and encoding/decoding of 8-byte data sequences. - * This class can be particularly helpful when working with fixed-length binary data structures, - * such as 64-bit integers, IPv6 addresses or other 8-byte long data representations. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes8 extends Buffer {} -/** - * Bytes9 represents a fixed-size byte array of length 9, extending the Buffer class. - * It can be used to store and manipulate binary data efficiently in various scenarios, - * such as encoding/decoding, file handling, and networking. The class guarantees that - * the number of bytes will always be exactly 9, ensuring consistency and preventing - * accidental resizing or overflow issues. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes9 extends Buffer {} -/** - * The Bytes10 class is a specialized extension of the Buffer class, specifically designed to handle - * fixed-length byte arrays of size 10. This class provides all the functionality and methods of the - * Buffer class but ensures that the data being managed is always exactly 10 bytes in length. - * It can be useful for scenarios where precise control over byte array sizes is required, - * such as cryptography, hashing, or working with fixed-size data structures. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes10 extends Buffer {} -/** - * The Bytes11 class is an extension of the Buffer class, specifically designed to handle - * fixed binary data with a size of 11 bytes. It provides all the functionality of the Buffer - * class, while enforcing the constraint that the length of the binary data should be exactly 11 bytes. - * This can be useful in scenarios where precise byte-length data is required, such as working with - * certain cryptographic algorithms or data serialization formats. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes11 extends Buffer {} -/** - * Represents a Bytes12 class that extends the Buffer class, specifically designed to handle and manipulate - * 12-byte data sequences. This class provides an efficient way of dealing with binary data of fixed length, - * being especially useful in scenarios like cryptographic hashes, keys, and unique identifiers. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes12 extends Buffer {} -/** - * Represents a Bytes13 class that extends the Buffer class to handle 13-byte binary data. - * This class provides a convenient way to work with fixed-length byte arrays, specifically for - * use cases that require exactly 13 bytes of data. It inherits all methods and properties from - * the Buffer class, allowing easy manipulation and handling of binary data. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes13 extends Buffer {} -/** - * Represents a Bytes14 class that extends the Buffer class, specifically designed - * to handle and manipulate fixed-length 14-byte binary data efficiently. - * Offers built-in functionality via the Buffer class to read and write various - * data types, encode/decode strings, and perform optimized operations on the - * underlying bytes. This class can be used in various applications where - * fixed-sized 14-byte data structures are required, such as cryptographic keys, - * unique identifiers, and other encoding/decoding scenarios. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes14 extends Buffer {} -/** - * The Bytes15 class extends the Buffer class and represents a binary data container with a fixed length of 15 bytes. - * This specific byte array size is useful for handling data structures that require exactly 15-byte long entries, ensuring consistent storage and processing. - * Inherits all methods and properties from the Buffer class, providing additional functionality for manipulation and conversion of binary data. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes15 extends Buffer {} -/** - * Bytes16 represents a fixed-length byte buffer of 16 bytes, extending the native Buffer class. - * This class can be used to store and manipulate binary data efficiently, while maintaining - * the consistency of the fixed-length requirement. Common use cases include handling cryptographic - * hashes, UUIDs, and other fixed-size data structures. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes16 extends Buffer {} -/** - * The Bytes17 class extends the Buffer class and represents a fixed-size binary data container of 17 bytes. - * This class can be used to store and manipulate raw byte sequences efficiently in various applications, - * such as encryption algorithms, file handling, or data transmission processes that require specific byte lengths. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes17 extends Buffer {} -/** - * Bytes18 represents a fixed-sized, 18-byte buffer class that extends the native Node.js Buffer class. - * It is useful in scenarios where precise byte-length data structures are required, - * such as when working with binary protocols or cryptographic algorithms that need - * specific sized inputs. The Bytes18 class ensures proper management and manipulation - * of 18-byte data chunks, providing consistent and efficient handling throughout your application. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes18 extends Buffer {} -/** - * Represents a Bytes19 class, which is a custom extension of the Buffer class. - * This class is specifically designed to handle an array of 19 bytes in length, - * providing additional functionality and constraints related to the management - * of byte arrays with a fixed size of 19. - * - * It can be used for situations where precisely 19 bytes are required, such as - * data storage, cryptographic operations, or communication protocols that have - * specific size requirements. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes19 extends Buffer {} -/** - * The Bytes20 class represents a fixed-length byte array (Buffer) with a length of 20 bytes. - * It is designed to be used for data structures and operations requiring fixed-size byte arrays, - * such as storing Ethereum addresses, which are exactly 20 bytes long. - * Extending the native Buffer class, this class provides all its functionalities while enforcing the specific byte length. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes20 extends Buffer {} -/** - * Represents the Bytes21 class, which is an extension of the Buffer class, specifically designed to handle byte arrays of fixed length 21. - * This class can be used for efficiently storing and manipulating data that requires exactly 21 bytes, such as certain cryptographic keys or hashes. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes21 extends Buffer {} -/** - * Represents the Bytes22 class, which provides a specialized extension of the Buffer class. - * This class is designed for handling byte arrays of length 22 efficiently and conveniently. - * It offers all the functionality provided by the Buffer class while ensuring the fixed size constraint for better optimization. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes22 extends Buffer {} -/** - * The Bytes23 class represents a specialized buffer designed specifically for handling - * 23-byte binary data sequences. It extends the native Node.js Buffer API to provide - * functionality tailored to efficiently store, manipulate, and process fixed-size - * data elements of 23 bytes in length. This class can be particularly useful in applications - * where working with precise byte lengths is vital, such as cryptographic operations, - * network protocols or file systems. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes23 extends Buffer {} -/** - * Represents the Bytes24 class, a fixed-length binary data buffer that extends from Buffer. - * This class provides a 24-byte container for handling binary data in various scenarios, - * such as working with encryption, encoding, compression, or other data manipulation tasks. - * Using fixed-length byte arrays can be useful for efficient memory management and predictable performance. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes24 extends Buffer {} -/** - * The Bytes25 class extends the Buffer class, representing a fixed-length binary data container - * with a size of 25 bytes. It is ideal for storing and manipulating unique data structures that require - * a constant byte size, such as specific cryptographic hashes or addresses. - * The class inherits all methods and properties from the Buffer class to provide an efficient way - * to work with raw binary data while ensuring a maximum length constraint. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes25 extends Buffer {} -/** - * The Bytes26 class extends the Buffer class and represents a fixed-size binary data container with a length of 26 bytes. - * This class can be used for efficient storage, manipulation, and serialization of 26-byte long byte arrays in various applications, - * such as working with cryptographic keys, unique identifiers, or other data structures that require a fixed-length binary representation. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes26 extends Buffer {} -/** - * The Bytes27 class represents a fixed-size 27-byte Buffer, which can be used for handling binary data of specific length. - * It extends the Node.js Buffer class and provides an efficient way to manage raw bytes within a fixed-sized container. - * Common use cases include cryptographic operations, encoding/decoding tasks, and working with structured binary data formats. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes27 extends Buffer {} -/** - * The Bytes28 class represents a fixed-length binary data buffer of 28 bytes, - * extending the built-in Buffer class. It provides efficient and safe manipulation - * of binary data, while ensuring that the size remains constant throughout the lifetime - * of the instance. This can be particularly useful in scenarios where there's a need to - * represent and handle fixed-length byte arrays, such as encoding/decoding operations, - * cryptographic hashing, or data serialization. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes28 extends Buffer {} -/** - * Represents a specialized Bytes class with a fixed buffer size of 29 bytes, extending the native Buffer object. - * This Bytes29 class can be used for handling binary data that requires precisely 29 bytes in length, - * ensuring consistent memory allocation and simplifying data manipulation across different use cases. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes29 extends Buffer {} -/** - * The Bytes30 class extends the Buffer class and represents a fixed-size byte array of length 30. - * It is particularly useful for storing, manipulating, and transmitting various forms of data - * while maintaining a consistent size. This can aid in ensuring compatibility and efficient storage - * within applications that require fixed-length byte arrays, such as cryptographic algorithms, - * encoding schemes, or communication protocols. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes30 extends Buffer {} -/** - * Bytes31 represents a fixed length 31-byte Buffer class that can be used for managing and manipulating binary data. - * This class extends the built-in Node.js Buffer, providing all its functionalities while ensuring a constant byte size - * of 31 throughout the application. This can be especially useful in scenarios where fixed-length data structures are required, - * such as cryptography, hashing algorithms, or serialization protocols. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes31 extends Buffer {} -/** - * The Bytes32 class extends the Buffer class in Node.js and represents a fixed-size byte array of 32 bytes. - * This can be particularly useful for handling data structures that require a fixed-length input, such as cryptographic - * hash functions, digital signatures or keys. By using a dedicated class like Bytes32, it ensures proper handling, - * validation, and manipulation of these crucial data elements within various applications. - */ +// eslint-disable-next-line jsdoc/require-jsdoc export class Bytes32 extends Buffer {} diff --git a/yarn-project/ethereum.js/src/contract/constructor_interaction.ts b/yarn-project/ethereum.js/src/contract/constructor_interaction.ts index a34873399aa..e6fe13698ac 100644 --- a/yarn-project/ethereum.js/src/contract/constructor_interaction.ts +++ b/yarn-project/ethereum.js/src/contract/constructor_interaction.ts @@ -21,14 +21,14 @@ export class ConstructorInteraction extends FunctionInteraction { } /** - * Sends a transaction with the encoded contract bytecode and constructor arguments, creating a new deployment of the contract. - * Returns a SentDeployContractTx instance that can be used to track the transaction status and retrieve the deployed contract address. - * The 'options' parameter can be used to customize the transaction, such as specifying gas price, gas limit, or value to send. - * - * @param options - An object containing optional parameters for customizing the transaction. - * @returns A SentDeployContractTx instance representing the sent transaction. - */ -public send(options: SendOptions): SentTx { + * Sends a transaction with the encoded contract bytecode and constructor arguments, creating a new deployment of the contract. + * Returns a SentDeployContractTx instance that can be used to track the transaction status and retrieve the deployed contract address. + * The 'options' parameter can be used to customize the transaction, such as specifying gas price, gas limit, or value to send. + * + * @param options - An object containing optional parameters for customizing the transaction. + * @returns A SentDeployContractTx instance representing the sent transaction. + */ + public send(options: SendOptions): SentTx { const sentTx = super.send(options); return new SentDeployContractTx(this.eth, this.contractAbi, sentTx.getTxHash(), this.onDeployed); } diff --git a/yarn-project/ethereum.js/src/contract/contract.test.ts b/yarn-project/ethereum.js/src/contract/contract.test.ts index 17de0047956..04299483770 100644 --- a/yarn-project/ethereum.js/src/contract/contract.test.ts +++ b/yarn-project/ethereum.js/src/contract/contract.test.ts @@ -562,12 +562,12 @@ describe('contract', () => { const signature = sha3('mySend(address,uint256)').slice(0, 10); /** - * Sets up the initial state for the mock Ethereum provider by resolving the required RPC calls. - * This function helps prepare the test environment before executing test cases related to contract methods. - * The bootstrap function configures the responses for eth_sendTransaction, eth_blockNumber, - * and eth_getTransactionReceipt in the mock Ethereum provider. - */ -function bootstrap() { + * Sets up the initial state for the mock Ethereum provider by resolving the required RPC calls. + * This function helps prepare the test environment before executing test cases related to contract methods. + * The bootstrap function configures the responses for eth_sendTransaction, eth_blockNumber, + * and eth_getTransactionReceipt in the mock Ethereum provider. + */ + function bootstrap() { // eth_sendTransaction mockEthereumProvider.request.mockResolvedValueOnce( '0x1234000000000000000000000000000000000000000000000000000000056789', diff --git a/yarn-project/ethereum.js/src/contract/contract.ts b/yarn-project/ethereum.js/src/contract/contract.ts index 94f8d5b2b19..224bae07cab 100644 --- a/yarn-project/ethereum.js/src/contract/contract.ts +++ b/yarn-project/ethereum.js/src/contract/contract.ts @@ -11,17 +11,17 @@ import { ConstructorInteraction } from './constructor_interaction.js'; */ export interface ContractOptions { /** - * The Ethereum address initiating the contract interaction. - */ -from?: EthAddress; + * The Ethereum address initiating the contract interaction. + */ + from?: EthAddress; /** - * Gas price for executing contract transactions. - */ -gasPrice?: string | number; + * Gas price for executing contract transactions. + */ + gasPrice?: string | number; /** - * The maximum amount of gas units allowed for the contract execution. - */ -gas?: number; + * The maximum amount of gas units allowed for the contract execution. + */ + gas?: number; } /** @@ -31,17 +31,17 @@ gas?: number; */ interface ContractDefinition { /** - * Collection of named functions to interact with the contract methods. - */ -methods: any; + * Collection of named functions to interact with the contract methods. + */ + methods: any; /** - * Collection of contract event definitions for ease of interaction. - */ -events?: any; + * Collection of contract event definitions for ease of interaction. + */ + events?: any; /** - * A collection of event logs for the contract. - */ -eventLogs?: any; + * A collection of event logs for the contract. + */ + eventLogs?: any; } /** @@ -98,9 +98,9 @@ type GetContractMethods = T extends ContractDefinition */ export class Contract { /** - * Collection of named functions for interacting with the contract methods. - */ -public readonly methods: GetContractMethods; + * Collection of named functions for interacting with the contract methods. + */ + public readonly methods: GetContractMethods; // public readonly events: GetContractEvents; private linkTable: { [name: string]: EthAddress } = {}; @@ -108,9 +108,9 @@ public readonly methods: GetContractMethods; private eth: EthereumRpc, private contractAbi: ContractAbi, /** - * Ethereum contract address for interaction. - */ -public address = EthAddress.ZERO, + * Ethereum contract address for interaction. + */ + public address = EthAddress.ZERO, private defaultOptions: ContractOptions = {}, ) { this.methods = this.buildMethods(); @@ -154,60 +154,60 @@ public address = EthAddress.ZERO, } /** - * Retrieves event logs from the contract based on the specified event and options. - * If 'allevents' is passed as the event, it will return logs for all events in the contract. - * Otherwise, it returns logs for the specific event name or signature provided. - * The LogRequest options allow filtering, such as setting a block range or topics to search for logs. - * - * @param event - The event name, signature, or 'allevents' to retrieve logs for. - * @param options - Optional LogRequest object to filter the log results. - * @returns An array of EventLog objects for the specified event(s) and filtered based on the provided options. - */ -public async getLogs>( + * Retrieves event logs from the contract based on the specified event and options. + * If 'allevents' is passed as the event, it will return logs for all events in the contract. + * Otherwise, it returns logs for the specific event name or signature provided. + * The LogRequest options allow filtering, such as setting a block range or topics to search for logs. + * + * @param event - The event name, signature, or 'allevents' to retrieve logs for. + * @param options - Optional LogRequest object to filter the log results. + * @returns An array of EventLog objects for the specified event(s) and filtered based on the provided options. + */ + public async getLogs>( event: Event, options: LogRequest>, ): Promise[]>; /** - * Retrieves event logs for the specified event or all events emitted by the contract. - * This function takes an event name and optional log request options as parameters, then - * fetches the matching event logs from the Ethereum blockchain. If the event name is 'allevents', - * it will retrieve logs for all events emitted by the contract. The resulting event logs are - * decoded according to the contract's ABI before being returned as an array. - * - * @param event - The name of the event or 'allevents' to retrieve logs for all events. - * @param options - Optional log request options such as filter, address, and topics. - * @returns An array of decoded event logs matching the specified event name and options. - */ -public async getLogs(event: 'allevents', options: LogRequest): Promise[]>; + * Retrieves event logs for the specified event or all events emitted by the contract. + * This function takes an event name and optional log request options as parameters, then + * fetches the matching event logs from the Ethereum blockchain. If the event name is 'allevents', + * it will retrieve logs for all events emitted by the contract. The resulting event logs are + * decoded according to the contract's ABI before being returned as an array. + * + * @param event - The name of the event or 'allevents' to retrieve logs for all events. + * @param options - Optional log request options such as filter, address, and topics. + * @returns An array of decoded event logs matching the specified event name and options. + */ + public async getLogs(event: 'allevents', options: LogRequest): Promise[]>; /** - * Fetches event logs from the blockchain based on the given event and options. - * This function can either retrieve logs for a specific event or all events in a contract. - * It returns an array of decoded event logs based on the ContractDefinition type parameter. - * The `eventName` parameter should be the name or signature of the event, or 'allevents' to fetch - * logs for all events in a contract. The `options` parameter allows filtering logs by block range, - * address, and other criteria. - * - * @param eventName - The name, signature, or 'allevents' string representing the event(s) to fetch logs for. - * @param options - A LogRequest object with optional properties to filter event logs. - * @returns A Promise that resolves to an array of decoded event logs. - */ -public async getLogs(event: Events & 'allevents', options: LogRequest = {}): Promise[]> { + * Fetches event logs from the blockchain based on the given event and options. + * This function can either retrieve logs for a specific event or all events in a contract. + * It returns an array of decoded event logs based on the ContractDefinition type parameter. + * The `eventName` parameter should be the name or signature of the event, or 'allevents' to fetch + * logs for all events in a contract. The `options` parameter allows filtering logs by block range, + * address, and other criteria. + * + * @param eventName - The name, signature, or 'allevents' string representing the event(s) to fetch logs for. + * @param options - A LogRequest object with optional properties to filter event logs. + * @returns A Promise that resolves to an array of decoded event logs. + */ + public async getLogs(event: Events & 'allevents', options: LogRequest = {}): Promise[]> { const logOptions = this.getLogOptions(event, options); const result = await this.eth.getLogs(logOptions); return result.map(log => this.contractAbi.decodeEvent(log)); } /** - * Retrieves a contract method by name and input/output types as an executor factory. - * The method can be called with the specified arguments to create a FunctionInteraction instance. - * Throws an error if no contract address is available or if there is no matching method with the provided arguments length. - * - * @param name - The name of the contract method. - * @param inputTypes - An array of input data types for the method. - * @param outputTypes - An array of output data types for the method. - * @returns A TxFactory instance representing the contract method. - */ -public getMethod(name: string, inputTypes: AbiDataTypes[], outputTypes: AbiDataTypes[]) { + * Retrieves a contract method by name and input/output types as an executor factory. + * The method can be called with the specified arguments to create a FunctionInteraction instance. + * Throws an error if no contract address is available or if there is no matching method with the provided arguments length. + * + * @param name - The name of the contract method. + * @param inputTypes - An array of input data types for the method. + * @param outputTypes - An array of output data types for the method. + * @returns A TxFactory instance representing the contract method. + */ + public getMethod(name: string, inputTypes: AbiDataTypes[], outputTypes: AbiDataTypes[]) { const abiEntry: ContractEntryDefinition = { inputs: inputTypes.map((type, i) => ({ name: `a${i}`, type })), name, @@ -244,14 +244,14 @@ public getMethod(name: string, inputTypes: AbiDataTypes[], outputTypes: AbiDataT } /** - * Generates a collection of named functions on the public `methods` property based on the contract ABI. - * It groups and assigns contract functions to their respective method names. - * In case of function overloads, it will create an executor factory for all matching functions. - * - * @private - * @returns An object containing the generated methods mapped to their respective names. - */ -private buildMethods() { + * Generates a collection of named functions on the public `methods` property based on the contract ABI. + * It groups and assigns contract functions to their respective method names. + * In case of function overloads, it will create an executor factory for all matching functions. + * + * @private + * @returns An object containing the generated methods mapped to their respective names. + */ + private buildMethods() { const methods: any = {}; this.contractAbi.functions.forEach(f => { @@ -273,15 +273,15 @@ private buildMethods() { } /** - * Generates a LogRequest object for the specified event and request options. - * This is used to filter and retrieve logs related to a contract event. - * Throws an error if no contract address is available or the specified event is not found in the ABI. - * - * @param eventName - The name or signature of the contract event. - * @param options - A LogRequest object containing filter and topic options for the log query. - * @returns A LogRequest object with the specified event and request options combined. - */ -private getLogOptions(eventName = 'allevents', options: LogRequest): LogRequest { + * Generates a LogRequest object for the specified event and request options. + * This is used to filter and retrieve logs related to a contract event. + * Throws an error if no contract address is available or the specified event is not found in the ABI. + * + * @param eventName - The name or signature of the contract event. + * @param options - A LogRequest object containing filter and topic options for the log query. + * @returns A LogRequest object with the specified event and request options combined. + */ + private getLogOptions(eventName = 'allevents', options: LogRequest): LogRequest { if (!this.address) { throw new Error('No contract address.'); } diff --git a/yarn-project/ethereum.js/src/contract/contract_tx_receipt.ts b/yarn-project/ethereum.js/src/contract/contract_tx_receipt.ts index 34e80f4c0fd..45ea4ec6d0f 100644 --- a/yarn-project/ethereum.js/src/contract/contract_tx_receipt.ts +++ b/yarn-project/ethereum.js/src/contract/contract_tx_receipt.ts @@ -3,89 +3,95 @@ import { LogResponse, TransactionReceipt, TxHash } from '../eth_rpc/index.js'; import { DecodedError } from './decode_error.js'; /** - * Represents a parsed Ethereum event log specific to Aztec contracts. + * Represents a parsed Ethereum event log specific to Ethereum contracts. * Contains information about the event, such as its name, address, arguments, block data, and signature. * Useful for tracking contract interactions and state changes on the blockchain. */ export interface EventLog { /** - * A unique identifier for the event log. - */ -id: string | null; + * A unique identifier for the event log. + */ + id: string | null; /** - * Indicates whether the event log has been removed due to a chain reorganization. - */ -removed?: boolean; + * Indicates whether the event log has been removed due to a chain reorganization. + */ + removed?: boolean; /** - * The name of the emitted event. - */ -event: Name; + * The name of the emitted event. + */ + event: Name; /** - * The Ethereum address of the contract emitting the event. - */ -address: EthAddress; + * The Ethereum address of the contract emitting the event. + */ + address: EthAddress; /** - * Arguments associated with the emitted event. - */ -args: Args; + * Arguments associated with the emitted event. + */ + args: Args; /** - * The index position of the log entry in the block. - */ -logIndex: number | null; + * The index position of the log entry in the block. + */ + logIndex: number | null; /** - * The index of the transaction within the block containing it. - */ -transactionIndex: number | null; + * The index of the transaction within the block containing it. + */ + transactionIndex: number | null; /** - * The unique identifier of the transaction. - */ -transactionHash: TxHash | null; + * The unique identifier of the transaction. + */ + transactionHash: TxHash | null; /** - * The hash of the block containing this event. - */ -blockHash: string | null; + * The hash of the block containing this event. + */ + blockHash: string | null; /** - * The block number containing the event. - */ -blockNumber: number | null; + * The block number containing the event. + */ + blockNumber: number | null; /** - * Raw event data and topics emitted by the contract. - */ -raw: { /** - * The raw hexadecimal representation of the event data. - */ -data: string; /** - * An array of indexed event arguments encoded as hexadecimal strings. - */ -topics: string[] }; + * Raw event data and topics emitted by the contract. + */ + raw: { + /** + * The raw hexadecimal representation of the event data. + */ + data: string; + /** + * An array of indexed event arguments encoded as hexadecimal strings. + */ + topics: string[]; + }; /** - * The unique identifier of the event signature. - */ -signature: string | null; + * The unique identifier of the event signature. + */ + signature: string | null; } /** - * Represents a contract transaction receipt in the Aztec network. + * Represents a contract transaction receipt in the Ethereum network. * Extends the standard transaction receipt with additional information about anonymous logs and * decoded events specific to the contract. It also includes optional error details in case of a failed transaction. */ export interface ContractTxReceipt extends TransactionReceipt { /** - * An array of logs without specific event signatures. - */ -anonymousLogs: LogResponse[]; + * An array of logs without specific event signatures. + */ + anonymousLogs: LogResponse[]; /** - * An object containing arrays of various event logs, keyed by their respective event names. - */ -events: Events extends void ? { [eventName: string]: EventLog[] } : Events; + * An object containing arrays of various event logs, keyed by their respective event names. + */ + events: Events extends void ? { [eventName: string]: EventLog[] } : Events; /** - * An optional field containing error information, including a message and decodedError if available. - */ -error?: { /** - * The human-readable error message. - */ -message: string; /** - * Decoded information from a failing transaction error. - */ -decodedError?: DecodedError }; + * An optional field containing error information, including a message and decodedError if available. + */ + error?: { + /** + * The human-readable error message. + */ + message: string; + /** + * Decoded information from a failing transaction error. + */ + decodedError?: DecodedError; + }; } diff --git a/yarn-project/ethereum.js/src/contract/decode_error.ts b/yarn-project/ethereum.js/src/contract/decode_error.ts index c12d28e747d..58afd99ae44 100644 --- a/yarn-project/ethereum.js/src/contract/decode_error.ts +++ b/yarn-project/ethereum.js/src/contract/decode_error.ts @@ -9,19 +9,19 @@ import { ContractAbi } from './abi/contract_abi.js'; */ export interface DecodedError { /** - * The name of the decoded error. - */ -name?: string; - ``` -/** - * An array of decoded error parameters. - */ -``` -params?: any[]; + * The name of the decoded error. + */ + name?: string; + /** - * A human-readable description of the error. - */ -message: string; + * An array of decoded error parameters. + */ + + params?: any[]; + /** + * A human-readable description of the error. + */ + message: string; } /** diff --git a/yarn-project/ethereum.js/src/contract/function_interaction.ts b/yarn-project/ethereum.js/src/contract/function_interaction.ts index a7167f33a30..1b95081c597 100644 --- a/yarn-project/ethereum.js/src/contract/function_interaction.ts +++ b/yarn-project/ethereum.js/src/contract/function_interaction.ts @@ -18,21 +18,21 @@ import { SentContractTx } from './sent_contract_tx.js'; */ export interface Options { /** - * The Ethereum address initiating the transaction. - */ -from?: EthAddress; + * The Ethereum address initiating the transaction. + */ + from?: EthAddress; /** - * The maximum fee per gas unit for the transaction. - */ -maxFeePerGas?: bigint; + * The maximum fee per gas unit for the transaction. + */ + maxFeePerGas?: bigint; /** - * The maximum priority fee per gas unit for the transaction. - */ -maxPriorityFeePerGas?: bigint; + * The maximum priority fee per gas unit for the transaction. + */ + maxPriorityFeePerGas?: bigint; /** - * The maximum amount of gas units to be used for the transaction. - */ -gas?: number; + * The maximum amount of gas units to be used for the transaction. + */ + gas?: number; } /** @@ -42,9 +42,9 @@ gas?: number; */ export interface CallOptions extends Options { /** - * The amount of ether (in wei) to transfer during the transaction. - */ -value?: bigint; + * The amount of ether (in wei) to transfer during the transaction. + */ + value?: bigint; } /** @@ -53,9 +53,9 @@ value?: bigint; */ export interface SendOptions extends CallOptions { /** - * The nonce value representing the number of transactions sent from the sender's address. - */ -nonce?: number; + * The nonce value representing the number of transactions sent from the sender's address. + */ + nonce?: number; } /** @@ -96,15 +96,15 @@ export class FunctionInteraction implements TxCall, TxSend { ) {} /** - * Estimate the amount of gas required to perform a transaction for the function interaction. - * The gas estimation is based on the provided 'options' object, which can include parameters such as 'from', 'maxFeePerGas', 'maxPriorityFeePerGas', and 'gas'. - * If the transaction execution fails or there's an error in the call, it attempts to handle the error gracefully by providing a meaningful message. - * - * @param options - An optional object containing transaction parameters and overrides for the function interaction. - * @returns A Promise that resolves to the estimated gas amount required for the transaction. - * @throws Will throw an error if the call fails with a decoded error message, or a generic error message if decoding fails. - */ -public async estimateGas(options: CallOptions = {}) { + * Estimate the amount of gas required to perform a transaction for the function interaction. + * The gas estimation is based on the provided 'options' object, which can include parameters such as 'from', 'maxFeePerGas', 'maxPriorityFeePerGas', and 'gas'. + * If the transaction execution fails or there's an error in the call, it attempts to handle the error gracefully by providing a meaningful message. + * + * @param options - An optional object containing transaction parameters and overrides for the function interaction. + * @returns A Promise that resolves to the estimated gas amount required for the transaction. + * @throws Will throw an error if the call fails with a decoded error message, or a generic error message if decoding fails. + */ + public async estimateGas(options: CallOptions = {}) { try { return await this.eth.estimateGas(this.getCallRequest(options)); } catch (err: any) { @@ -113,16 +113,16 @@ public async estimateGas(options: CallOptions = {}) { } /** - * Executes a read-only contract function call, returning the decoded result. - * This interaction does not require a transaction on the blockchain and is thus gas-free. - * If the call encounters an error, it attempts to decode the error message from the contract - * and throws an error with a meaningful message. Otherwise, it throws the original error. - * - * @param options - Optional settings specifying "from", "value", "maxFeePerGas", "maxPriorityFeePerGas" and "gas". - * @param block - Optional specification of the block number or tag at which the call must be executed. - * @returns The return value of the contract function call after successful decoding. - */ -public async call(options: CallOptions = {}, block?: NumberOrTag) { + * Executes a read-only contract function call, returning the decoded result. + * This interaction does not require a transaction on the blockchain and is thus gas-free. + * If the call encounters an error, it attempts to decode the error message from the contract + * and throws an error with a meaningful message. Otherwise, it throws the original error. + * + * @param options - Optional settings specifying "from", "value", "maxFeePerGas", "maxPriorityFeePerGas" and "gas". + * @param block - Optional specification of the block number or tag at which the call must be executed. + * @returns The return value of the contract function call after successful decoding. + */ + public async call(options: CallOptions = {}, block?: NumberOrTag) { try { const result = await this.eth.call(this.getCallRequest(options), block); return this.contractEntry.decodeReturnValue(result); @@ -132,14 +132,14 @@ public async call(options: CallOptions = {}, block?: NumberOrTag) { } /** - * Sends a transaction to the specified contract method with given options. - * It returns a SentTx instance containing the transaction receipt and decoded return value (if any). - * Throws an error if the from address is not specified or attempting to send value to a non-payable method. - * - * @param options - An object containing optional parameters: from, nonce, value, maxFeePerGas, maxPriorityFeePerGas, and gas. - * @returns A SentTx instance representing the sent transaction. - */ -public send(options: SendOptions): SentTx { + * Sends a transaction to the specified contract method with given options. + * It returns a SentTx instance containing the transaction receipt and decoded return value (if any). + * Throws an error if the from address is not specified or attempting to send value to a non-payable method. + * + * @param options - An object containing optional parameters: from, nonce, value, maxFeePerGas, maxPriorityFeePerGas, and gas. + * @returns A SentTx instance representing the sent transaction. + */ + public send(options: SendOptions): SentTx { const tx = this.getTxRequest(options); if (!this.contractEntry.payable && tx.value !== undefined && tx.value > 0) { @@ -152,26 +152,26 @@ public send(options: SendOptions): SentTx { } /** - * Encodes the ABI (Application Binary Interface) for the function interaction with the provided arguments. - * The encoded ABI is a serialized representation of the function's signature and its arguments, which can be used - * by the Ethereum client to process the method call or transaction. This is useful for encoding contract function - * calls when interacting with the Ethereum blockchain. - * - * @returns A Buffer containing the encoded ABI for the function interaction. - */ -public encodeABI() { + * Encodes the ABI (Application Binary Interface) for the function interaction with the provided arguments. + * The encoded ABI is a serialized representation of the function's signature and its arguments, which can be used + * by the Ethereum client to process the method call or transaction. This is useful for encoding contract function + * calls when interacting with the Ethereum blockchain. + * + * @returns A Buffer containing the encoded ABI for the function interaction. + */ + public encodeABI() { return this.contractEntry.encodeABI(this.args); } /** - * Construct a transaction request object by merging the provided send options with the default options, `from` address, contract address, and encoded ABI data. - * This transaction request object is used for sending transactions to the Ethereum network. - * Throws an error if the `from` address is not specified. - * - * @param options - The send options containing information required for constructing the transaction request object. - * @returns A TransactionRequest instance with all necessary data for sending the transaction. - */ -private getTxRequest(options: SendOptions = {}): TransactionRequest { + * Construct a transaction request object by merging the provided send options with the default options, `from` address, contract address, and encoded ABI data. + * This transaction request object is used for sending transactions to the Ethereum network. + * Throws an error if the `from` address is not specified. + * + * @param options - The send options containing information required for constructing the transaction request object. + * @returns A TransactionRequest instance with all necessary data for sending the transaction. + */ + private getTxRequest(options: SendOptions = {}): TransactionRequest { const from = options.from || this.defaultOptions.from; if (!from) { throw new Error('You must specify a from address to send a tx.'); @@ -186,16 +186,16 @@ private getTxRequest(options: SendOptions = {}): TransactionRequest { } /** - * Constructs and returns a CallRequest object for the current contract function interaction. - * The CallRequest object combines the provided options with the default options and includes - * the encoded ABI data of the function call. This object can be used to perform various - * interactions such as estimating gas, making calls, or sending transactions. - * - * @param options - An optional CallOptions object containing values such as from address, - * maxFeePerGas, maxPriorityFeePerGas, gas, and value. - * @returns A CallRequest object with the necessary information for further interactions. - */ -private getCallRequest(options: CallOptions = {}): CallRequest { + * Constructs and returns a CallRequest object for the current contract function interaction. + * The CallRequest object combines the provided options with the default options and includes + * the encoded ABI data of the function call. This object can be used to perform various + * interactions such as estimating gas, making calls, or sending transactions. + * + * @param options - An optional CallOptions object containing values such as from address, + * maxFeePerGas, maxPriorityFeePerGas, gas, and value. + * @returns A CallRequest object with the necessary information for further interactions. + */ + private getCallRequest(options: CallOptions = {}): CallRequest { return { ...this.defaultOptions, ...options, @@ -205,14 +205,14 @@ private getCallRequest(options: CallOptions = {}): CallRequest { } /** - * Handles errors occurring during the execution of a contract function call. - * If the error data contains a decodable error message, throws an error with a decoded message. - * Otherwise, throws the original error with its message. - * - * @param err - The error object caught during the contract function call execution. - * @throws {Error} An error with either the decoded error message or the original error message. - */ -private handleError(err: any): never { + * Handles errors occurring during the execution of a contract function call. + * If the error data contains a decodable error message, throws an error with a decoded message. + * Otherwise, throws the original error with its message. + * + * @param err - The error object caught during the contract function call execution. + * @throws {Error} An error with either the decoded error message or the original error message. + */ + private handleError(err: any): never { if (err.data && err.data.length > 2) { const decoded = decodeErrorFromContract(this.contractAbi, hexToBuffer(err.data)); if (decoded) { diff --git a/yarn-project/ethereum.js/src/contract/gen_def/index.ts b/yarn-project/ethereum.js/src/contract/gen_def/index.ts index dee077f761f..af3751aa681 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/index.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/index.ts @@ -632,7 +632,7 @@ function makeAbiExport(name: string) { } /** - * Generate TypeScript source code as AST nodes for a Contract based on the provided ABI and initialization data. + * Generate TypeScript source code as AST nodes for a Contract based on the provided ABI and initialization data. * The generated code includes imports, event types, event log interfaces, events interface, transaction receipt interface, * methods interface, definition interface, contract class, and ABI export. * diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/config.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/config.ts index 32dbce789e8..ada755b63dc 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/config.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/config.ts @@ -14,21 +14,21 @@ import { ContractAbiDefinition } from '../../abi/index.js'; */ interface FileSource { /** - * The origin of contract configuration data. - */ -source: 'files'; + * The origin of contract configuration data. + */ + source: 'files'; /** - * The unique identifier for the contract configuration. - */ -name: string; + * The unique identifier for the contract configuration. + */ + name: string; /** - * Path to the contract's ABI file. - */ -abiFile: string; + * Path to the contract's ABI file. + */ + abiFile: string; /** - * Optional file containing initialization data for the contract. - */ -initDataFile?: string; + * Optional file containing initialization data for the contract. + */ + initDataFile?: string; } /** @@ -37,21 +37,21 @@ initDataFile?: string; */ interface EtherscanSource { /** - * The source from which the contract definition is obtained. - */ -source: 'etherscan'; + * The source from which the contract definition is obtained. + */ + source: 'etherscan'; /** - * The unique identifier for the contract. - */ -name: string; + * The unique identifier for the contract. + */ + name: string; /** - * The Ethereum network identifier. - */ -net: string; + * The Ethereum network identifier. + */ + net: string; /** - * The Ethereum contract address. - */ -address: string; + * The Ethereum contract address. + */ + address: string; } /** @@ -61,17 +61,17 @@ address: string; */ interface TruffleSource { /** - * The origin of contract information. - */ -source: 'truffle'; + * The origin of contract information. + */ + source: 'truffle'; /** - * The unique identifier for the contract. - */ -name: string; + * The unique identifier for the contract. + */ + name: string; /** - * The path to the build file containing contract information. - */ -buildFile: string; + * The path to the build file containing contract information. + */ + buildFile: string; } /** @@ -80,17 +80,17 @@ buildFile: string; */ interface FoundrySource { /** - * The origin of the contract configuration data. - */ -source: 'foundry'; + * The origin of the contract configuration data. + */ + source: 'foundry'; /** - * The unique identifier for a contract. - */ -name: string; + * The unique identifier for a contract. + */ + name: string; /** - * The path to the build file containing contract information. - */ -buildFile: string; + * The path to the build file containing contract information. + */ + buildFile: string; } /** @@ -99,21 +99,21 @@ buildFile: string; */ interface InlineSource { /** - * The origin of contract ABI and initialization data. - */ -source: 'inline'; + * The origin of contract ABI and initialization data. + */ + source: 'inline'; /** - * The name identifier for the contract. - */ -name: string; + * The name identifier for the contract. + */ + name: string; /** - * The contract's Application Binary Interface (ABI) definition. - */ -abi: ContractAbiDefinition; + * The contract's Application Binary Interface (ABI) definition. + */ + abi: ContractAbiDefinition; /** - * Initialization data for contract deployment. - */ -initData?: string; + * Initialization data for contract deployment. + */ + initData?: string; } /** @@ -127,15 +127,15 @@ export type ContractConfig = FileSource | EtherscanSource | TruffleSource | Inli */ export interface Config { /** - * The path to import contracts from. - */ -importPath?: string; + * The path to import contracts from. + */ + importPath?: string; /** - * The destination path for generated output files. - */ -outputPath?: string; + * The destination path for generated output files. + */ + outputPath?: string; /** - * An array of contract configurations for various sources. - */ -contracts: ContractConfig[]; + * An array of contract configurations for various sources. + */ + contracts: ContractConfig[]; } diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/index.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/index.ts index 6c7db0d6372..13ac2a48165 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/index.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/index.ts @@ -18,13 +18,13 @@ import { getFromTruffle } from './source-truffle.js'; */ export interface ContractBuildData { /** - * The Application Binary Interface (ABI) for a smart contract. - */ -abi: ContractAbiDefinition; + * The Application Binary Interface (ABI) for a smart contract. + */ + abi: ContractAbiDefinition; /** - * Initial deployment data for the contract. - */ -initData?: string; + * Initial deployment data for the contract. + */ + initData?: string; } const { ETHERSCAN_API_KEY = '', ETHEREUM_HOST = '' } = process.env; diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-foundry.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-foundry.ts index 5963173c67d..bebc30ca6e6 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-foundry.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-foundry.ts @@ -16,13 +16,16 @@ import { ContractAbiDefinition } from '../../abi/index.js'; * @param buildFile - The path to the foundry build file containing the ABI and bytecode information. * @returns An object containing the contract ABI definition and optional initialization data as properties. */ -export function getFromFoundry(buildFile: string): { /** - * The contract's Application Binary Interface. - */ -abi: ContractAbiDefinition; /** - * The bytecode object representing the contract's initial state. - */ -initData?: string } { +export function getFromFoundry(buildFile: string): { + /** + * The contract's Application Binary Interface. + */ + abi: ContractAbiDefinition; + /** + * The bytecode object representing the contract's initial state. + */ + initData?: string; +} { const { abi, bytecode: { object: initData }, diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-truffle.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-truffle.ts index 240d283cc9d..05648b7ee2a 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-truffle.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-truffle.ts @@ -10,19 +10,22 @@ import { ContractAbiDefinition } from '../../abi/index.js'; /** * Extracts Contract ABI (Application Binary Interface) and initialization data from a Truffle build file. - * The function reads the specified JSON build file and returns an object containing the ABI and initData. + * The function reads the specified JSON build file and returns an object containing the ABI and initData. * This can be utilized for deploying and interacting with smart contracts through web3x library. * * @param buildFile - The path to the Truffle build file in JSON format. * @returns An object containing the contract ABI and optional initData (bytecode). */ -export function getFromTruffle(buildFile: string): { /** - * The JSON representation of a smart contract's interface. - */ -abi: ContractAbiDefinition; /** - * The initialization bytecode for contract deployment. - */ -initData?: string } { +export function getFromTruffle(buildFile: string): { + /** + * The JSON representation of a smart contract's interface. + */ + abi: ContractAbiDefinition; + /** + * The initialization bytecode for contract deployment. + */ + initData?: string; +} { const { abi, bytecode: initData } = JSON.parse(fs.readFileSync(buildFile).toString()); return { abi, initData }; } diff --git a/yarn-project/ethereum.js/src/contract/sent_contract_tx.ts b/yarn-project/ethereum.js/src/contract/sent_contract_tx.ts index e5af9aacb64..2e3d8f4afdd 100644 --- a/yarn-project/ethereum.js/src/contract/sent_contract_tx.ts +++ b/yarn-project/ethereum.js/src/contract/sent_contract_tx.ts @@ -17,19 +17,19 @@ export class SentContractTx extends SentTransaction { } /** - * Processes the transaction receipt by decoding events, handling errors, and populating anonymous logs. - * The function takes a TransactionReceipt, a ContractAbi, and an EthereumRpc as its input parameters, - * and returns a Promise that resolves to a ContractTxReceipt containing the processed data. - * It separates logs into anonymousLogs (emitted by external contract calls) and decodes events - * according to the contract's ABI. If the transaction status is falsy, it attempts to decode - * the error using the provided ABI and includes it in the resulting ContractTxReceipt. - * - * @param receipt - The TransactionReceipt to be processed. - * @param contractAbi - The ContractAbi instance used for event decoding and error handling. - * @param ethRpc - The EthereumRpc instance used for interacting with the Ethereum network. - * @returns A Promise that resolves to a ContractTxReceipt object containing anonymousLogs, decoded events, and optional error information. - */ -protected async handleReceipt(throwOnError = true, receipt: TransactionReceipt) { + * Processes the transaction receipt by decoding events, handling errors, and populating anonymous logs. + * The function takes a TransactionReceipt, a ContractAbi, and an EthereumRpc as its input parameters, + * and returns a Promise that resolves to a ContractTxReceipt containing the processed data. + * It separates logs into anonymousLogs (emitted by external contract calls) and decodes events + * according to the contract's ABI. If the transaction status is falsy, it attempts to decode + * the error using the provided ABI and includes it in the resulting ContractTxReceipt. + * + * @param receipt - The TransactionReceipt to be processed. + * @param contractAbi - The ContractAbi instance used for event decoding and error handling. + * @param ethRpc - The EthereumRpc instance used for interacting with the Ethereum network. + * @returns A Promise that resolves to a ContractTxReceipt object containing anonymousLogs, decoded events, and optional error information. + */ + protected async handleReceipt(throwOnError = true, receipt: TransactionReceipt) { const result = await handleReceipt(receipt, this.contractAbi, this.ethRpc); if (result.error && throwOnError) { throw new Error(`Receipt indicates transaction failed: ${result.error.message}`); diff --git a/yarn-project/ethereum.js/src/contract/sent_deploy_contract_tx.ts b/yarn-project/ethereum.js/src/contract/sent_deploy_contract_tx.ts index 90b61ed51e2..a460f9fcffe 100644 --- a/yarn-project/ethereum.js/src/contract/sent_deploy_contract_tx.ts +++ b/yarn-project/ethereum.js/src/contract/sent_deploy_contract_tx.ts @@ -19,15 +19,15 @@ export class SentDeployContractTx extends SentContractTx { } /** - * Handles the transaction receipt for a contract deployment, executing a callback - * with the deployed contract address when it is available in the receipt. - * Extends the base class method to include the onDeployed callback execution. - * - * @param throwOnError - A boolean flag indicating whether to throw an error on non-zero exit status. - * @param receipt - The transaction receipt object containing the contract address and other details. - * @returns A Promise resolving to a ContractTxReceipt instance containing transaction receipt data. - */ -protected async handleReceipt(throwOnError = true, receipt: TransactionReceipt): Promise { + * Handles the transaction receipt for a contract deployment, executing a callback + * with the deployed contract address when it is available in the receipt. + * Extends the base class method to include the onDeployed callback execution. + * + * @param throwOnError - A boolean flag indicating whether to throw an error on non-zero exit status. + * @param receipt - The transaction receipt object containing the contract address and other details. + * @returns A Promise resolving to a ContractTxReceipt instance containing transaction receipt data. + */ + protected async handleReceipt(throwOnError = true, receipt: TransactionReceipt): Promise { if (receipt.contractAddress) { this.onDeployed(receipt.contractAddress); } diff --git a/yarn-project/ethereum.js/src/eth_account/eth_account.ts b/yarn-project/ethereum.js/src/eth_account/eth_account.ts index 454faa2dc85..49805e7a120 100644 --- a/yarn-project/ethereum.js/src/eth_account/eth_account.ts +++ b/yarn-project/ethereum.js/src/eth_account/eth_account.ts @@ -19,18 +19,20 @@ const secp256k1 = new elliptic.ec('secp256k1'); */ export class EthAccount { /** - * The Ethereum address associated with the account. - */ -public readonly address: EthAddress; + * The Ethereum address associated with the account. + */ + public readonly address: EthAddress; /** - * The public key associated with the Ethereum account. - */ -public readonly publicKey: Buffer; + * The public key associated with the Ethereum account. + */ + public readonly publicKey: Buffer; - constructor(/** - * The private key of the Ethereum account. - */ -public readonly privateKey: Buffer) { + constructor( + /** + * The private key of the Ethereum account. + */ + public readonly privateKey: Buffer, + ) { const ecKey = secp256k1.keyFromPrivate(privateKey); this.publicKey = Buffer.from(ecKey.getPublic(false, 'hex'), 'hex'); // Why discarding first byte? @@ -39,15 +41,15 @@ public readonly privateKey: Buffer) { } /** - * Create a new EthAccount instance using optional entropy. - * This function generates a random private key, optionally combined with the provided entropy, - * and creates an EthAccount instance with the corresponding address and public key. - * Throws an error if the generated private key is invalid. - * - * @param entropy - Optional buffer containing entropy to be combined with the randomly generated private key. Default is a 32-byte random buffer. - * @returns A new EthAccount instance with the generated private key, address, and public key. - */ -public static create(entropy: Buffer = randomBytes(32)) { + * Create a new EthAccount instance using optional entropy. + * This function generates a random private key, optionally combined with the provided entropy, + * and creates an EthAccount instance with the corresponding address and public key. + * Throws an error if the generated private key is invalid. + * + * @param entropy - Optional buffer containing entropy to be combined with the randomly generated private key. Default is a 32-byte random buffer. + * @returns A new EthAccount instance with the generated private key, address, and public key. + */ + public static create(entropy: Buffer = randomBytes(32)) { const innerHex = keccak256(Buffer.concat([randomBytes(32), entropy])); const middleHex = Buffer.concat([randomBytes(32), innerHex, randomBytes(32)]); const outerHex = keccak256(middleHex); @@ -55,31 +57,31 @@ public static create(entropy: Buffer = randomBytes(32)) { } /** - * Creates an EthAccount instance from a mnemonic phrase and a derivation path. - * The mnemonic is used to generate the seed, which is then used with the provided derivation path - * to derive the private key for the account. This function is useful when working with - * Hierarchical Deterministic (HD) wallets. - * - * @param mnemonic - The mnemonic phrase representing the seed for the HD wallet. - * @param derivationPath - The derivation path to generate the EthAccount's private key. - * @returns An EthAccount instance with the derived private key. - */ -public static fromMnemonicAndPath(mnemonic: string, derivationPath: string) { + * Creates an EthAccount instance from a mnemonic phrase and a derivation path. + * The mnemonic is used to generate the seed, which is then used with the provided derivation path + * to derive the private key for the account. This function is useful when working with + * Hierarchical Deterministic (HD) wallets. + * + * @param mnemonic - The mnemonic phrase representing the seed for the HD wallet. + * @param derivationPath - The derivation path to generate the EthAccount's private key. + * @returns An EthAccount instance with the derived private key. + */ + public static fromMnemonicAndPath(mnemonic: string, derivationPath: string) { const seed = mnemonicToSeedSync(mnemonic); return EthAccount.fromSeedAndPath(seed, derivationPath); } /** - * Create an EthAccount instance from a seed and derivation path. - * The function takes a Buffer containing the seed and a string with the derivation path, - * and generates the corresponding private key by following the BIP32 HD wallet standard. - * It then creates and returns an EthAccount object using the derived private key. - * - * @param seed - A Buffer containing the seed for the HD wallet. - * @param derivationPath - A string representing the BIP32 derivation path. - * @returns An EthAccount instance with the derived private key. - */ -public static fromSeedAndPath(seed: Buffer, derivationPath: string) { + * Create an EthAccount instance from a seed and derivation path. + * The function takes a Buffer containing the seed and a string with the derivation path, + * and generates the corresponding private key by following the BIP32 HD wallet standard. + * It then creates and returns an EthAccount object using the derived private key. + * + * @param seed - A Buffer containing the seed for the HD wallet. + * @param derivationPath - A string representing the BIP32 derivation path. + * @returns An EthAccount instance with the derived private key. + */ + public static fromSeedAndPath(seed: Buffer, derivationPath: string) { const root = hdkey.fromMasterSeed(seed); const addrNode = root.derive(derivationPath); const privateKey = addrNode.privateKey; @@ -87,43 +89,43 @@ public static fromSeedAndPath(seed: Buffer, derivationPath: string) { } /** - * Create an EthAccount instance from a KeyStoreJson object. - * This method decrypts the encrypted private key in the v3 keystore with the provided password, - * and initializes the EthAccount instance with the decrypted private key. - * Throws an error if the password is incorrect or the decryption process fails. - * - * @param v3Keystore - The KeyStoreJson object representing the Ethereum keystore (v3 format). - * @param password - The password used to encrypt the private key in the keystore. - * @returns A Promise that resolves to an EthAccount instance. - */ -public static async fromKeyStoreJson(v3Keystore: KeyStoreJson, password: string) { + * Create an EthAccount instance from a KeyStoreJson object. + * This method decrypts the encrypted private key in the v3 keystore with the provided password, + * and initializes the EthAccount instance with the decrypted private key. + * Throws an error if the password is incorrect or the decryption process fails. + * + * @param v3Keystore - The KeyStoreJson object representing the Ethereum keystore (v3 format). + * @param password - The password used to encrypt the private key in the keystore. + * @returns A Promise that resolves to an EthAccount instance. + */ + public static async fromKeyStoreJson(v3Keystore: KeyStoreJson, password: string) { return new EthAccount(await decryptFromKeyStoreJson(v3Keystore, password)); } /** - * Sign an Ethereum transaction using the account's private key. - * This method generates a digital signature for the provided transaction object - * by leveraging the private key of the account instance. The signed transaction can then - * be broadcasted to the Ethereum network for execution. - * - * @param tx - The EthTransaction object representing the details of the transaction to be signed. - * @returns An EthSignature object containing the generated signature for the transaction. - */ -public signTransaction(tx: EthTransaction) { + * Sign an Ethereum transaction using the account's private key. + * This method generates a digital signature for the provided transaction object + * by leveraging the private key of the account instance. The signed transaction can then + * be broadcasted to the Ethereum network for execution. + * + * @param tx - The EthTransaction object representing the details of the transaction to be signed. + * @returns An EthSignature object containing the generated signature for the transaction. + */ + public signTransaction(tx: EthTransaction) { return signTransaction(tx, this.privateKey); } /** - * Checks if a signed Ethereum transaction matches the expected address. - * The function takes an unsigned Ethereum transaction and its corresponding signature, - * then recovers the signer's Ethereum address from the signature and compares it - * to the current EthAccount instance's address. - * - * @param tx - The unsigned Ethereum transaction object. - * @param signature - The Ethereum signature object for the given transaction. - * @returns A boolean indicating whether the recovered address matches the EthAccount's address. - */ -public signedTransaction(tx: EthTransaction, signature: EthSignature) { + * Checks if a signed Ethereum transaction matches the expected address. + * The function takes an unsigned Ethereum transaction and its corresponding signature, + * then recovers the signer's Ethereum address from the signature and compares it + * to the current EthAccount instance's address. + * + * @param tx - The unsigned Ethereum transaction object. + * @param signature - The Ethereum signature object for the given transaction. + * @returns A boolean indicating whether the recovered address matches the EthAccount's address. + */ + public signedTransaction(tx: EthTransaction, signature: EthSignature) { return signedTransaction(tx, signature).equals(this.address); } @@ -145,40 +147,40 @@ public signedTransaction(tx: EthTransaction, signature: EthSignature) { } /** - * Sign the typed data by first getting its hashed digest using the provided 'data' parameter, - * and then signing the resulting 32-byte digest with the account's private key. - * This function is useful for signing structured data according to EIP-712 standard. - * - * @param data - A TypedData object containing the type information and values to be signed. - * @returns An EthSignature representing the signature of the hashed typed data. - */ -public signTypedData(data: TypedData) { + * Sign the typed data by first getting its hashed digest using the provided 'data' parameter, + * and then signing the resulting 32-byte digest with the account's private key. + * This function is useful for signing structured data according to EIP-712 standard. + * + * @param data - A TypedData object containing the type information and values to be signed. + * @returns An EthSignature representing the signature of the hashed typed data. + */ + public signTypedData(data: TypedData) { return this.signDigest(getTypedDataHash(data)); } /** - * Verifies if the given signature corresponds to the message signed by this EthAccount instance. - * It hashes the input message with the Ethereum Signed Message preamble, recovers the signer's address - * from the signature, and compares it against the EthAccount's address. - * - * @param message - The Buffer containing the message to be verified. - * @param signature - The EthSignature instance representing the signature of the message. - * @returns A boolean value indicating whether the signature corresponds to the message signed by this EthAccount. - */ -public signedMessage(message: Buffer, signature: EthSignature) { + * Verifies if the given signature corresponds to the message signed by this EthAccount instance. + * It hashes the input message with the Ethereum Signed Message preamble, recovers the signer's address + * from the signature, and compares it against the EthAccount's address. + * + * @param message - The Buffer containing the message to be verified. + * @param signature - The EthSignature instance representing the signature of the message. + * @returns A boolean value indicating whether the signature corresponds to the message signed by this EthAccount. + */ + public signedMessage(message: Buffer, signature: EthSignature) { return recoverFromSignature(hashMessage(message), signature).equals(this.address); } /** - * Encrypts the EthAccount's private key into a KeyStore JSON format using the provided password. - * The KeyStore JSON can be stored securely and used later to recreate the EthAccount instance. - * The optional 'options' parameter can be used to customize the encryption process. - * - * @param password - The password used for encrypting the private key. - * @param options - Optional configuration object for the encryption process. - * @returns A KeyStoreJson instance representing the encrypted private key. - */ -public toKeyStoreJson(password: string, options?: any) { + * Encrypts the EthAccount's private key into a KeyStore JSON format using the provided password. + * The KeyStore JSON can be stored securely and used later to recreate the EthAccount instance. + * The optional 'options' parameter can be used to customize the encryption process. + * + * @param password - The password used for encrypting the private key. + * @param options - Optional configuration object for the encryption process. + * @returns A KeyStoreJson instance representing the encrypted private key. + */ + public toKeyStoreJson(password: string, options?: any) { return encryptToKeyStoreJson(this.privateKey, this.address, password, options); } } diff --git a/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts b/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts index 0cd3e868e8d..9f84e1871be 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts @@ -36,26 +36,26 @@ export class EthereumRpc { constructor(private provider: EthereumProvider) {} /** - * Retrieves the currently implemented Ethereum protocol version. - * The returned value follows the semantic versioning specification (semver). - * This may be useful for determining compatibility between client and server implementations. - * - * @returns A Promise that resolves to a number representing the Ethereum protocol version. - */ -public async protocolVersion() { + * Retrieves the currently implemented Ethereum protocol version. + * The returned value follows the semantic versioning specification (semver). + * This may be useful for determining compatibility between client and server implementations. + * + * @returns A Promise that resolves to a number representing the Ethereum protocol version. + */ + public async protocolVersion() { const result = await this.provider.request({ method: 'eth_protocolVersion' }); return Number(result); } /** - * Retrieves the syncing status of the connected Ethereum node. - * When the node is not syncing, returns false. If syncing, returns an object containing - * startingBlock, currentBlock, and highestBlock which represent the block numbers of - * the syncing process's start point, current progress, and end point respectively. - * - * @returns A Promise that resolves to either false or an object with syncing status data. - */ -public async syncing() { + * Retrieves the syncing status of the connected Ethereum node. + * When the node is not syncing, returns false. If syncing, returns an object containing + * startingBlock, currentBlock, and highestBlock which represent the block numbers of + * the syncing process's start point, current progress, and end point respectively. + * + * @returns A Promise that resolves to either false or an object with syncing status data. + */ + public async syncing() { const result = await this.provider.request({ method: 'eth_syncing' }); return { startingBlock: Number(result.startingBlock), @@ -65,27 +65,27 @@ public async syncing() { } /** - * Retrieve the currently configured chain ID of the Ethereum network. - * The chain ID is a unique identifier for each Ethereum network, allowing clients to distinguish - * between multiple networks and ensuring transaction replay protection. - * - * @returns A number representing the current chain ID. - */ -public async getChainId() { + * Retrieve the currently configured chain ID of the Ethereum network. + * The chain ID is a unique identifier for each Ethereum network, allowing clients to distinguish + * between multiple networks and ensuring transaction replay protection. + * + * @returns A number representing the current chain ID. + */ + public async getChainId() { const result = await this.provider.request({ method: 'eth_chainId' }); return Number(result); } /** - * Retrieve the contract code of a given `address` at a specific block number or block tag. - * The function allows querying the Ethereum blockchain for smart contract bytecode. - * Results are returned as a Buffer containing the bytecode in hexadecimal format. - * - * @param address - The EthAddress instance representing the Ethereum address of the smart contract. - * @param numberOrTag - Optional parameter specifying the block number or block tag (default is 'latest'). - * @returns A Promise that resolves to a Buffer containing the contract code in hexadecimal format. - */ -public async getCode(address: EthAddress, numberOrTag: NumberOrTag = 'latest') { + * Retrieve the contract code of a given `address` at a specific block number or block tag. + * The function allows querying the Ethereum blockchain for smart contract bytecode. + * Results are returned as a Buffer containing the bytecode in hexadecimal format. + * + * @param address - The EthAddress instance representing the Ethereum address of the smart contract. + * @param numberOrTag - Optional parameter specifying the block number or block tag (default is 'latest'). + * @returns A Promise that resolves to a Buffer containing the contract code in hexadecimal format. + */ + public async getCode(address: EthAddress, numberOrTag: NumberOrTag = 'latest') { const result = await this.provider.request({ method: 'eth_getCode', params: [address.toString(), numberOrTagToHex(numberOrTag)], @@ -94,13 +94,13 @@ public async getCode(address: EthAddress, numberOrTag: NumberOrTag = 'latest') { } /** - * Retrieves a list of Ethereum accounts available on the connected node. - * Each account is represented by an EthAddress instance. Useful for - * querying and interacting with accounts managed by the connected Ethereum node. - * - * @returns An array of EthAddress instances representing the available accounts. - */ -public async getAccounts() { + * Retrieves a list of Ethereum accounts available on the connected node. + * Each account is represented by an EthAddress instance. Useful for + * querying and interacting with accounts managed by the connected Ethereum node. + * + * @returns An array of EthAddress instances representing the available accounts. + */ + public async getAccounts() { const result: string[] = await this.provider.request({ method: 'eth_accounts', }); @@ -108,14 +108,14 @@ public async getAccounts() { } /** - * Retrieves the number of transactions sent from the specified Ethereum address. - * This function sends a request to the 'eth_getTransactionCount' method with the address and 'latest' as parameters. - * The response is then converted to a Number before being returned. - * - * @param addr - The EthAddress instance representing the Ethereum address. - * @returns The number of transactions sent from the given address. - */ -public async getTransactionCount(addr: EthAddress) { + * Retrieves the number of transactions sent from the specified Ethereum address. + * This function sends a request to the 'eth_getTransactionCount' method with the address and 'latest' as parameters. + * The response is then converted to a Number before being returned. + * + * @param addr - The EthAddress instance representing the Ethereum address. + * @returns The number of transactions sent from the given address. + */ + public async getTransactionCount(addr: EthAddress) { const result = await this.provider.request({ method: 'eth_getTransactionCount', params: [addr.toString(), 'latest'], @@ -124,13 +124,13 @@ public async getTransactionCount(addr: EthAddress) { } /** - * Retrieves the current balance of the given Ethereum address. - * The balance is returned as a BigInt representing the amount of wei held by the address. - * - * @param addr - The EthAddress instance representing the Ethereum address to fetch the balance for. - * @returns A BigInt representing the balance of the given address in wei. - */ -public async getBalance(addr: EthAddress) { + * Retrieves the current balance of the given Ethereum address. + * The balance is returned as a BigInt representing the amount of wei held by the address. + * + * @param addr - The EthAddress instance representing the Ethereum address to fetch the balance for. + * @returns A BigInt representing the balance of the given address in wei. + */ + public async getBalance(addr: EthAddress) { const result = await this.provider.request({ method: 'eth_getBalance', params: [addr.toString(), 'latest'], @@ -139,13 +139,13 @@ public async getBalance(addr: EthAddress) { } /** - * Retrieves a transaction by its hash. - * The function returns the transaction details such as block hash, block number, from/to addresses, etc., by querying the Ethereum blockchain. - * - * @param txHash - The transaction hash of the target transaction. - * @returns A Promise that resolves to the transaction details in a human-readable format. - */ -public async getTransactionByHash(txHash: TxHash) { + * Retrieves a transaction by its hash. + * The function returns the transaction details such as block hash, block number, from/to addresses, etc., by querying the Ethereum blockchain. + * + * @param txHash - The transaction hash of the target transaction. + * @returns A Promise that resolves to the transaction details in a human-readable format. + */ + public async getTransactionByHash(txHash: TxHash) { const result = await this.provider.request({ method: 'eth_getTransactionByHash', params: [txHash.toString()], @@ -154,15 +154,15 @@ public async getTransactionByHash(txHash: TxHash) { } /** - * Retrieves the transaction receipt for the given transaction hash. - * The transaction receipt contains information about the execution of a transaction, - * such as the status, gas used, and logs generated by the transaction. - * Returns undefined if the transaction hash is not found or the transaction is pending. - * - * @param txHash - The TxHash object representing the transaction hash. - * @returns A Promise that resolves to an object containing transaction receipt details or undefined if not found. - */ -public async getTransactionReceipt(txHash: TxHash) { + * Retrieves the transaction receipt for the given transaction hash. + * The transaction receipt contains information about the execution of a transaction, + * such as the status, gas used, and logs generated by the transaction. + * Returns undefined if the transaction hash is not found or the transaction is pending. + * + * @param txHash - The TxHash object representing the transaction hash. + * @returns A Promise that resolves to an object containing transaction receipt details or undefined if not found. + */ + public async getTransactionReceipt(txHash: TxHash) { const result = await this.provider.request({ method: 'eth_getTransactionReceipt', params: [txHash.toString()], @@ -171,12 +171,12 @@ public async getTransactionReceipt(txHash: TxHash) { } /** - * Retrieves the current block number from the Ethereum blockchain. - * The result is a decimal representation of the latest mined block number. - * - * @returns A Promise that resolves to the current block number as a Number. - */ -public async blockNumber() { + * Retrieves the current block number from the Ethereum blockchain. + * The result is a decimal representation of the latest mined block number. + * + * @returns A Promise that resolves to the current block number as a Number. + */ + public async blockNumber() { const result = await this.provider.request({ method: 'eth_blockNumber', params: [], @@ -185,15 +185,15 @@ public async blockNumber() { } /** - * Retrieve the block information by its block number or block tag. - * The block information includes data such as block hash, parent hash, miner, difficulty, etc. - * The transactions in the block can be optionally fetched in full detail by setting 'fullTxs' to true. - * - * @param numberOrTag - The block number or block tag ('earliest', 'latest', 'pending') to fetch the block information for. - * @param fullTxs - If set to true, the block information will include full transaction details. Defaults to false. - * @returns An object containing the detailed block information or undefined if the block is not found. - */ -public async getBlockByNumber(numberOrTag: NumberOrTag, fullTxs = false) { + * Retrieve the block information by its block number or block tag. + * The block information includes data such as block hash, parent hash, miner, difficulty, etc. + * The transactions in the block can be optionally fetched in full detail by setting 'fullTxs' to true. + * + * @param numberOrTag - The block number or block tag ('earliest', 'latest', 'pending') to fetch the block information for. + * @param fullTxs - If set to true, the block information will include full transaction details. Defaults to false. + * @returns An object containing the detailed block information or undefined if the block is not found. + */ + public async getBlockByNumber(numberOrTag: NumberOrTag, fullTxs = false) { const result = await this.provider.request({ method: 'eth_getBlockByNumber', params: [numberOrTagToHex(numberOrTag), fullTxs], @@ -202,14 +202,14 @@ public async getBlockByNumber(numberOrTag: NumberOrTag, fullTxs = false) { } /** - * Sign a message with the specified Ethereum address using the 'eth_sign' JSON-RPC method. - * The resulting signature can be used to verify that the message was signed by the owner of the provided address. - * - * @param address - The EthAddress instance representing the Ethereum address to sign the message with. - * @param message - The Buffer instance representing the message to be signed. - * @returns A Promise that resolves to an EthSignature instance representing the signed message. - */ -public async sign(address: EthAddress, message: Buffer) { + * Sign a message with the specified Ethereum address using the 'eth_sign' JSON-RPC method. + * The resulting signature can be used to verify that the message was signed by the owner of the provided address. + * + * @param address - The EthAddress instance representing the Ethereum address to sign the message with. + * @param message - The Buffer instance representing the message to be signed. + * @returns A Promise that resolves to an EthSignature instance representing the signed message. + */ + public async sign(address: EthAddress, message: Buffer) { const result = await this.provider.request({ method: 'eth_sign', params: [address.toString(), `0x${message.toString('hex')}`], @@ -218,15 +218,15 @@ public async sign(address: EthAddress, message: Buffer) { } /** - * Sign a message using the 'personal_sign' Ethereum JSON-RPC method with a specified Ethereum address. - * The provided message should be a Buffer, and the Ethereum address should be an EthAddress instance. - * This method is commonly used for signing messages to verify the ownership of an Ethereum account. - * - * @param message - The message to be signed as a Buffer. - * @param address - The EthAddress instance representing the Ethereum account used to sign the message. - * @returns An EthSignature instance containing the signed message from the provided Ethereum address. - */ -public async personalSign(message: Buffer, address: EthAddress) { + * Sign a message using the 'personal_sign' Ethereum JSON-RPC method with a specified Ethereum address. + * The provided message should be a Buffer, and the Ethereum address should be an EthAddress instance. + * This method is commonly used for signing messages to verify the ownership of an Ethereum account. + * + * @param message - The message to be signed as a Buffer. + * @param address - The EthAddress instance representing the Ethereum account used to sign the message. + * @returns An EthSignature instance containing the signed message from the provided Ethereum address. + */ + public async personalSign(message: Buffer, address: EthAddress) { const result = await this.provider.request({ method: 'personal_sign', params: [`0x${message.toString('hex')}`, address.toString()], @@ -235,16 +235,16 @@ public async personalSign(message: Buffer, address: EthAddress) { } /** - * Sign typed data using the EIP-712 Typed Data v4 standard. - * This function sends an 'eth_signTypedData_v4' JSON-RPC request to the Ethereum provider - * with the given address and data. The result is a signature in hex format which can be - * used to verify the signer of the typed data. - * - * @param address - The EthAddress of the signer. - * @param data - The TypedData object representing the structured data to be signed. - * @returns An EthSignature instance representing the signed message. - */ -public async signTypedDataV4(address: EthAddress, data: TypedData) { + * Sign typed data using the EIP-712 Typed Data v4 standard. + * This function sends an 'eth_signTypedData_v4' JSON-RPC request to the Ethereum provider + * with the given address and data. The result is a signature in hex format which can be + * used to verify the signer of the typed data. + * + * @param address - The EthAddress of the signer. + * @param data - The TypedData object representing the structured data to be signed. + * @returns An EthSignature instance representing the signed message. + */ + public async signTypedDataV4(address: EthAddress, data: TypedData) { const result = await this.provider.request({ method: 'eth_signTypedData_v4', params: [address.toString(), data], @@ -253,17 +253,17 @@ public async signTypedDataV4(address: EthAddress, data: TypedData) { } /** - * Estimate the amount of gas needed for a given transaction to succeed. - * The 'estimateGas' function sends a simulated call request to the Ethereum network - * and returns the estimated gas required for the transaction to be executed. - * This is useful for determining the gas limit to set when sending a real transaction, - * helping to ensure that transactions are executed successfully and avoiding - * unnecessary gas consumption. - * - * @param tx - The CallRequest object containing transaction details. - * @returns A number representing the estimated gas required for the transaction. - */ -public async estimateGas(tx: CallRequest) { + * Estimate the amount of gas needed for a given transaction to succeed. + * The 'estimateGas' function sends a simulated call request to the Ethereum network + * and returns the estimated gas required for the transaction to be executed. + * This is useful for determining the gas limit to set when sending a real transaction, + * helping to ensure that transactions are executed successfully and avoiding + * unnecessary gas consumption. + * + * @param tx - The CallRequest object containing transaction details. + * @returns A number representing the estimated gas required for the transaction. + */ + public async estimateGas(tx: CallRequest) { const result = await this.provider.request({ method: 'eth_estimateGas', params: [toRawEstimateRequest(tx)], @@ -272,15 +272,15 @@ public async estimateGas(tx: CallRequest) { } /** - * Executes a call to a smart contract function without modifying the blockchain state. - * The 'call' function returns the result of the executed code, and any gas used during execution is not deducted from the account. - * Useful for querying information from the blockchain or testing if a transaction would succeed without actually sending it. - * - * @param tx - The transaction request object containing information such as 'from', 'to', 'gas', 'gasPrice', 'value', and 'data'. - * @param numberOrTag - (Optional) A block number or one of the string tags "latest", "earliest", or "pending". Default is "latest". - * @returns A Buffer containing the return value of the executed function, if any. - */ -public async call(tx: CallRequest, numberOrTag: NumberOrTag = 'latest') { + * Executes a call to a smart contract function without modifying the blockchain state. + * The 'call' function returns the result of the executed code, and any gas used during execution is not deducted from the account. + * Useful for querying information from the blockchain or testing if a transaction would succeed without actually sending it. + * + * @param tx - The transaction request object containing information such as 'from', 'to', 'gas', 'gasPrice', 'value', and 'data'. + * @param numberOrTag - (Optional) A block number or one of the string tags "latest", "earliest", or "pending". Default is "latest". + * @returns A Buffer containing the return value of the executed function, if any. + */ + public async call(tx: CallRequest, numberOrTag: NumberOrTag = 'latest') { const data = await this.provider.request({ method: 'eth_call', params: [toRawCallRequest(tx), numberOrTagToHex(numberOrTag)], @@ -289,15 +289,15 @@ public async call(tx: CallRequest, numberOrTag: NumberOrTag = 'latest') { } /** - * Sends a signed transaction to the Ethereum network and returns a SentTx instance. - * The 'sendTransaction' method takes a TransactionRequest object as input, converts it to a raw transaction, - * and sends it to the network using the 'eth_sendTransaction' JSON-RPC method. It then returns a SentTx instance - * which can be used to track the status of the submitted transaction, such as fetching the transaction receipt. - * - * @param tx - The TransactionRequest object containing the details of the transaction to be sent. - * @returns A SentTx instance for tracking the submitted transaction's status. - */ -public sendTransaction(tx: TransactionRequest): SentTx { + * Sends a signed transaction to the Ethereum network and returns a SentTx instance. + * The 'sendTransaction' method takes a TransactionRequest object as input, converts it to a raw transaction, + * and sends it to the network using the 'eth_sendTransaction' JSON-RPC method. It then returns a SentTx instance + * which can be used to track the status of the submitted transaction, such as fetching the transaction receipt. + * + * @param tx - The TransactionRequest object containing the details of the transaction to be sent. + * @returns A SentTx instance for tracking the submitted transaction's status. + */ + public sendTransaction(tx: TransactionRequest): SentTx { const txHashPromise = this.provider.request({ method: 'eth_sendTransaction', params: [toRawTransactionRequest(tx)], @@ -306,14 +306,14 @@ public sendTransaction(tx: TransactionRequest): SentTx { } /** - * Sign a given Ethereum transaction using the specified private key. - * The 'TransactionRequest' object contains necessary information to sign the transaction such as nonce, gas price, gas limit, etc. - * Returns a Promise that resolves with a Buffer containing the signed transaction in raw bytes format. - * - * @param tx - The TransactionRequest object containing information required to sign the transaction. - * @returns A Promise that resolves with a raw signed transaction in buffer format. - */ -public async signTransaction(tx: TransactionRequest) { + * Sign a given Ethereum transaction using the specified private key. + * The 'TransactionRequest' object contains necessary information to sign the transaction such as nonce, gas price, gas limit, etc. + * Returns a Promise that resolves with a Buffer containing the signed transaction in raw bytes format. + * + * @param tx - The TransactionRequest object containing information required to sign the transaction. + * @returns A Promise that resolves with a raw signed transaction in buffer format. + */ + public async signTransaction(tx: TransactionRequest) { const result = await this.provider.request({ method: 'eth_signTransaction', params: [toRawTransactionRequest(tx)], @@ -322,14 +322,14 @@ public async signTransaction(tx: TransactionRequest) { } /** - * Retrieve logs from Ethereum nodes based on the log request provided. - * This function queries the Ethereum node using JSON-RPC and returns an array of logs matching - * the given filters specified in the logRequest object. - * - * @param logRequest - An object containing the filter parameters for the logs to be retrieved. - * @returns An array of log objects matching the filter parameters. - */ -public async getLogs(logRequest: LogRequest) { + * Retrieve logs from Ethereum nodes based on the log request provided. + * This function queries the Ethereum node using JSON-RPC and returns an array of logs matching + * the given filters specified in the logRequest object. + * + * @param logRequest - An object containing the filter parameters for the logs to be retrieved. + * @returns An array of log objects matching the filter parameters. + */ + public async getLogs(logRequest: LogRequest) { const result: RawLogResponse[] = await this.provider.request({ method: 'eth_getLogs', params: [toRawLogRequest(logRequest)], diff --git a/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts b/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts index 3030871d92c..cc70f990c25 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts @@ -29,29 +29,29 @@ export class SentTransaction implements SentTx { constructor(protected ethRpc: EthereumRpc, protected txHashPromise: Promise) {} /** - * Retrieve the transaction hash of the sent transaction. - * This function returns a promise that resolves with the TxHash of the transaction. - * Useful in tracking the status or obtaining the receipt of the transaction on the blockchain. - * - * @returns A Promise that resolves with the TxHash of the sent transaction. - */ -public async getTxHash(): Promise { + * Retrieve the transaction hash of the sent transaction. + * This function returns a promise that resolves with the TxHash of the transaction. + * Useful in tracking the status or obtaining the receipt of the transaction on the blockchain. + * + * @returns A Promise that resolves with the TxHash of the sent transaction. + */ + public async getTxHash(): Promise { return await this.txHashPromise; } /** - * Retrieve the transaction receipt for a given SentTx instance. - * This function will wait until the transaction has at least 'numConfirmations' confirmations before - * returning the receipt. If 'throwOnError' is set to true, it will throw an error if the receipt - * indicates that the transaction failed. Allows setting a 'timeout' and custom polling 'interval'. - * - * @param {boolean} throwOnError - Whether to throw an error if the receipt status indicates failure. - * @param {number} numConfirmations - The minimum number of confirmations required before returning the receipt. - * @param {number} timeout - The maximum time in seconds to wait for the receipt before giving up. A value of 0 disables the timeout. - * @param {number} interval - The time in seconds between polling attempts to fetch the receipt. - * @returns {Promise} A promise that resolves to the fetched transaction receipt. - */ -public async getReceipt( + * Retrieve the transaction receipt for a given SentTx instance. + * This function will wait until the transaction has at least 'numConfirmations' confirmations before + * returning the receipt. If 'throwOnError' is set to true, it will throw an error if the receipt + * indicates that the transaction failed. Allows setting a 'timeout' and custom polling 'interval'. + * + * @param {boolean} throwOnError - Whether to throw an error if the receipt status indicates failure. + * @param {number} numConfirmations - The minimum number of confirmations required before returning the receipt. + * @param {number} timeout - The maximum time in seconds to wait for the receipt before giving up. A value of 0 disables the timeout. + * @param {number} interval - The time in seconds between polling attempts to fetch the receipt. + * @returns {Promise} A promise that resolves to the fetched transaction receipt. + */ + public async getReceipt( throwOnError = true, numConfirmations = 1, timeout = 0, @@ -67,15 +67,15 @@ public async getReceipt( } /** - * Handles the transaction receipt based on the provided parameters. - * If throwOnError is true and the receipt status is false, an error will be thrown. - * Otherwise, returns the received transaction receipt as a resolved promise. - * - * @param throwOnError - A boolean flag indicating whether to throw an error if receipt status is false. - * @param receipt - The TransactionReceipt object received from the Ethereum network. - * @returns A Promise resolving to the given TransactionReceipt. - */ -protected handleReceipt(throwOnError = true, receipt: TransactionReceipt) { + * Handles the transaction receipt based on the provided parameters. + * If throwOnError is true and the receipt status is false, an error will be thrown. + * Otherwise, returns the received transaction receipt as a resolved promise. + * + * @param throwOnError - A boolean flag indicating whether to throw an error if receipt status is false. + * @param receipt - The TransactionReceipt object received from the Ethereum network. + * @returns A Promise resolving to the given TransactionReceipt. + */ + protected handleReceipt(throwOnError = true, receipt: TransactionReceipt) { if (throwOnError && !receipt.status) { throw new Error('Receipt indicates transaction failed. Try a call() to determine cause of failure.'); } diff --git a/yarn-project/ethereum.js/src/eth_rpc/tx_hash.ts b/yarn-project/ethereum.js/src/eth_rpc/tx_hash.ts index 4d06c92d0ce..870c23d0da6 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/tx_hash.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/tx_hash.ts @@ -14,84 +14,84 @@ export class TxHash { } /** - * Create a TxHash instance from a given buffer. - * The input 'buffer' should be a Buffer with exactly 32 bytes length. - * Throws an error if the input buffer length is invalid. - * - * @param buffer - The Buffer representing the transaction hash. - * @returns A TxHash instance. - */ -static fromBuffer(buffer: Buffer) { + * Create a TxHash instance from a given buffer. + * The input 'buffer' should be a Buffer with exactly 32 bytes length. + * Throws an error if the input buffer length is invalid. + * + * @param buffer - The Buffer representing the transaction hash. + * @returns A TxHash instance. + */ + static fromBuffer(buffer: Buffer) { return new TxHash(buffer); } /** - * Deserialize a Buffer into a TxHash instance starting at the specified offset. - * The function takes a buffer and an optional offset as input, slices the buffer - * from the offset to offset + 32 bytes, and creates a new TxHash object using this slice. - * Returns an object containing the created TxHash instance ('elem') and the number - * of bytes advanced in the buffer ('adv'), which is always 32 for a valid deserialization. - * - * @param buffer - The input Buffer containing the serialized TxHash data. - * @param offset - The optional starting position within the buffer to begin deserialization. Defaults to 0. - * @returns An object with properties 'elem' (TxHash instance) and 'adv' (number of bytes advanced). - */ -static deserialize(buffer: Buffer, offset: number) { + * Deserialize a Buffer into a TxHash instance starting at the specified offset. + * The function takes a buffer and an optional offset as input, slices the buffer + * from the offset to offset + 32 bytes, and creates a new TxHash object using this slice. + * Returns an object containing the created TxHash instance ('elem') and the number + * of bytes advanced in the buffer ('adv'), which is always 32 for a valid deserialization. + * + * @param buffer - The input Buffer containing the serialized TxHash data. + * @param offset - The optional starting position within the buffer to begin deserialization. Defaults to 0. + * @returns An object with properties 'elem' (TxHash instance) and 'adv' (number of bytes advanced). + */ + static deserialize(buffer: Buffer, offset: number) { return { elem: new TxHash(buffer.slice(offset, offset + 32)), adv: 32 }; } /** - * Create a TxHash instance from a hex-encoded string. - * The input 'hash' should be prefixed with '0x' or not, and have exactly 64 hex characters. - * Throws an error if the input length is invalid or the hash value is out of range. - * - * @param hash - The hex-encoded string representing the transaction hash. - * @returns A TxHash instance. - */ -public static fromString(hash: string) { + * Create a TxHash instance from a hex-encoded string. + * The input 'hash' should be prefixed with '0x' or not, and have exactly 64 hex characters. + * Throws an error if the input length is invalid or the hash value is out of range. + * + * @param hash - The hex-encoded string representing the transaction hash. + * @returns A TxHash instance. + */ + public static fromString(hash: string) { return new TxHash(Buffer.from(hash.replace(/^0x/i, ''), 'hex')); } /** - * Generate a random TxHash instance with a buffer of 32 random bytes. - * This function utilizes the 'randomBytes' function from the crypto library to generate - * a buffer filled with cryptographically secure random bytes, which is then used to create - * the new TxHash instance. - * - * @returns A random TxHash instance. - */ -public static random() { + * Generate a random TxHash instance with a buffer of 32 random bytes. + * This function utilizes the 'randomBytes' function from the crypto library to generate + * a buffer filled with cryptographically secure random bytes, which is then used to create + * the new TxHash instance. + * + * @returns A random TxHash instance. + */ + public static random() { return new TxHash(randomBytes(32)); } /** - * Compares the current TxHash instance with the provided TxHash instance. - * Returns true if their buffer contents are equal, otherwise returns false. - * - * @param rhs - The TxHash instance to compare with the current instance. - * @returns A boolean indicating whether the two TxHash instances have identical buffer contents. - */ -equals(rhs: TxHash) { + * Compares the current TxHash instance with the provided TxHash instance. + * Returns true if their buffer contents are equal, otherwise returns false. + * + * @param rhs - The TxHash instance to compare with the current instance. + * @returns A boolean indicating whether the two TxHash instances have identical buffer contents. + */ + equals(rhs: TxHash) { return this.toBuffer().equals(rhs.toBuffer()); } /** - * Converts the current TxHash instance to a Buffer. - * The resulting buffer will have a length of 32 bytes. - * - * @returns A Buffer representation of the transaction hash. - */ -toBuffer() { + * Converts the current TxHash instance to a Buffer. + * The resulting buffer will have a length of 32 bytes. + * + * @returns A Buffer representation of the transaction hash. + */ + toBuffer() { return this.buffer; } /** - * Converts the TxHash instance to a hex-encoded string representation. - * The resulting string is prefixed with '0x' and contains exactly 64 hex characters. - * - * @returns A string representing the TxHash in hex format. - */ -toString() { + * Converts the TxHash instance to a hex-encoded string representation. + * The resulting string is prefixed with '0x' and contains exactly 64 hex characters. + * + * @returns A string representing the TxHash in hex format. + */ + toString() { return `0x${this.toBuffer().toString('hex')}`; } } diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/block_response.ts b/yarn-project/ethereum.js/src/eth_rpc/types/block_response.ts index 324fc03604f..ffcef1b655c 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/block_response.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/block_response.ts @@ -21,69 +21,69 @@ import { */ export interface RawBlockHeaderResponse { /** - * The unique identifier of a block. - */ -hash: string | null; + * The unique identifier of a block. + */ + hash: string | null; /** - * The parent block's hash value. - */ -parentHash: string; + * The parent block's hash value. + */ + parentHash: string; /** - * The Keccak-256 hash of the uncles data in the block. - */ -sha3Uncles: string; + * The Keccak-256 hash of the uncles data in the block. + */ + sha3Uncles: string; /** - * The Ethereum address of the block miner. - */ -miner: string; + * The Ethereum address of the block miner. + */ + miner: string; /** - * The root hash of the Ethereum state trie. - */ -stateRoot: string; + * The root hash of the Ethereum state trie. + */ + stateRoot: string; /** - * The root hash of the merkle tree representing all transactions in the block. - */ -transactionsRoot: string; + * The root hash of the merkle tree representing all transactions in the block. + */ + transactionsRoot: string; /** - * The root hash of the trie structure containing all transaction receipts in the block. - */ -receiptsRoot: string; + * The root hash of the trie structure containing all transaction receipts in the block. + */ + receiptsRoot: string; /** - * Bloom filter containing logs for all transactions in the block. - */ -logsBloom: string | null; + * Bloom filter containing logs for all transactions in the block. + */ + logsBloom: string | null; /** - * The computational effort required to mine a new block. - */ -difficulty: string; + * The computational effort required to mine a new block. + */ + difficulty: string; /** - * The block number in the blockchain. - */ -number: string | null; + * The block number in the blockchain. + */ + number: string | null; /** - * The maximum amount of gas allowed in the block. - */ -gasLimit: string; + * The maximum amount of gas allowed in the block. + */ + gasLimit: string; /** - * The total amount of gas consumed by all transactions in the block. - */ -gasUsed: string; + * The total amount of gas consumed by all transactions in the block. + */ + gasUsed: string; /** - * Unix timestamp representing the block creation time. - */ -timestamp: string; + * Unix timestamp representing the block creation time. + */ + timestamp: string; /** - * Extra arbitrary metadata included in the block. - */ -extraData: string; + * Extra arbitrary metadata included in the block. + */ + extraData: string; /** - * A unique number used to prevent double-spending and ensure the validity of a transaction. - */ -nonce: string | null; + * A unique number used to prevent double-spending and ensure the validity of a transaction. + */ + nonce: string | null; /** - * The base fee per gas for each block, used in EIP-1559. - */ -baseFeePerGas: string | null; + * The base fee per gas for each block, used in EIP-1559. + */ + baseFeePerGas: string | null; } /** @@ -92,21 +92,21 @@ baseFeePerGas: string | null; */ export interface RawBlockResponse extends RawBlockHeaderResponse { /** - * The total accumulated difficulty of the blockchain up to this block. - */ -totalDifficulty: string; + * The total accumulated difficulty of the blockchain up to this block. + */ + totalDifficulty: string; /** - * Size of the block in bytes. - */ -size: string; + * Size of the block in bytes. + */ + size: string; /** - * A list of transactions included within the block. - */ -transactions: (RawTransactionResponse | string)[]; + * A list of transactions included within the block. + */ + transactions: (RawTransactionResponse | string)[]; /** - * An array of uncle blocks in the blockchain. - */ -uncles: string[]; + * An array of uncle blocks in the blockchain. + */ + uncles: string[]; } /** @@ -115,69 +115,69 @@ uncles: string[]; */ export interface BlockHeaderResponse { /** - * The hash representing the unique identifier of a block. - */ -hash: Buffer | null; + * The hash representing the unique identifier of a block. + */ + hash: Buffer | null; /** - * The hash of the parent block in the blockchain. - */ -parentHash: Buffer; + * The hash of the parent block in the blockchain. + */ + parentHash: Buffer; /** - * The Keccak-256 hash of the uncle blocks included in the block. - */ -sha3Uncles: Buffer; + * The Keccak-256 hash of the uncle blocks included in the block. + */ + sha3Uncles: Buffer; /** - * The Ethereum address of the miner who successfully mined the block. - */ -miner: EthAddress; + * The Ethereum address of the miner who successfully mined the block. + */ + miner: EthAddress; /** - * The root hash of the state trie after applying transactions. - */ -stateRoot: Buffer; + * The root hash of the state trie after applying transactions. + */ + stateRoot: Buffer; /** - * The root hash of the Merkle tree containing all transaction hashes in the block. - */ -transactionsRoot: Buffer; + * The root hash of the Merkle tree containing all transaction hashes in the block. + */ + transactionsRoot: Buffer; /** - * The root hash of the Merkle tree containing transaction receipts. - */ -receiptsRoot: Buffer; + * The root hash of the Merkle tree containing transaction receipts. + */ + receiptsRoot: Buffer; /** - * A compressed representation of logs' topics and data for efficient filtering. - */ -logsBloom: Buffer | null; + * A compressed representation of logs' topics and data for efficient filtering. + */ + logsBloom: Buffer | null; /** - * The computational effort required to mine a new block. - */ -difficulty: bigint; + * The computational effort required to mine a new block. + */ + difficulty: bigint; /** - * The block number within the blockchain. - */ -number: number | null; + * The block number within the blockchain. + */ + number: number | null; /** - * The maximum amount of gas allowed in a block. - */ -gasLimit: number; + * The maximum amount of gas allowed in a block. + */ + gasLimit: number; /** - * The total amount of gas consumed by all transactions in the block. - */ -gasUsed: number; + * The total amount of gas consumed by all transactions in the block. + */ + gasUsed: number; /** - * The UNIX timestamp when the block was mined. - */ -timestamp: number; + * The UNIX timestamp when the block was mined. + */ + timestamp: number; /** - * Arbitrary data included by the block miner. - */ -extraData: Buffer; + * Arbitrary data included by the block miner. + */ + extraData: Buffer; /** - * A unique value used to prevent duplicate transactions and secure block mining. - */ -nonce: Buffer | null; + * A unique value used to prevent duplicate transactions and secure block mining. + */ + nonce: Buffer | null; /** - * The base fee per gas for the block, used in EIP-1559 transactions. - */ -baseFeePerGas: bigint | null; + * The base fee per gas for the block, used in EIP-1559 transactions. + */ + baseFeePerGas: bigint | null; } /** @@ -186,21 +186,21 @@ baseFeePerGas: bigint | null; */ export interface BlockResponse extends BlockHeaderResponse { /** - * The cumulative proof-of-work difficulty of the blockchain up to this block. - */ -totalDifficulty: bigint; + * The cumulative proof-of-work difficulty of the blockchain up to this block. + */ + totalDifficulty: bigint; /** - * The byte size of the block. - */ -size: number; + * The byte size of the block. + */ + size: number; /** - * Array of transactions included in the block. - */ -transactions: T[]; + * Array of transactions included in the block. + */ + transactions: T[]; /** - * Uncles are stale blocks included in the main chain to provide a reward for partially mined blocks. - */ -uncles: string[]; + * Uncles are stale blocks included in the main chain to provide a reward for partially mined blocks. + */ + uncles: string[]; } /** diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/call_request.ts b/yarn-project/ethereum.js/src/eth_rpc/types/call_request.ts index 1aef5005db5..5628b0c159d 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/call_request.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/call_request.ts @@ -15,33 +15,33 @@ import { */ export interface CallRequest { /** - * The sender's Ethereum address. - */ -from?: EthAddress; + * The sender's Ethereum address. + */ + from?: EthAddress; /** - * The destination Ethereum address for the call request. - */ -to?: EthAddress; + * The destination Ethereum address for the call request. + */ + to?: EthAddress; /** - * The maximum amount of gas units to be used for the transaction execution. - */ -gas?: number; + * The maximum amount of gas units to be used for the transaction execution. + */ + gas?: number; /** - * Maximum fee per gas unit for transaction processing. - */ -maxFeePerGas?: bigint; + * Maximum fee per gas unit for transaction processing. + */ + maxFeePerGas?: bigint; /** - * Maximum fee per gas for transaction priority. - */ -maxPriorityFeePerGas?: bigint; + * Maximum fee per gas for transaction priority. + */ + maxPriorityFeePerGas?: bigint; /** - * The amount of Ether (in wei) to be transferred with the call. - */ -value?: bigint; + * The amount of Ether (in wei) to be transferred with the call. + */ + value?: bigint; /** - * The input data to be executed by the called contract. - */ -data?: Buffer; + * The input data to be executed by the called contract. + */ + data?: Buffer; } /** @@ -51,33 +51,33 @@ data?: Buffer; */ export interface RawCallRequest { /** - * The Ethereum address initiating the call. - */ -from?: string; + * The Ethereum address initiating the call. + */ + from?: string; /** - * The destination Ethereum address for the call request. - */ -to?: string; + * The destination Ethereum address for the call request. + */ + to?: string; /** - * The maximum amount of gas allowed for executing the transaction. - */ -gas?: string; + * The maximum amount of gas allowed for executing the transaction. + */ + gas?: string; /** - * Maximum fee per gas unit for transaction processing. - */ -maxFeePerGas?: string; + * Maximum fee per gas unit for transaction processing. + */ + maxFeePerGas?: string; /** - * The maximum fee per gas unit prioritized for transaction inclusion. - */ -maxPriorityFeePerGas?: string; + * The maximum fee per gas unit prioritized for transaction inclusion. + */ + maxPriorityFeePerGas?: string; /** - * The amount of Ether to be transferred in the transaction, represented as a bigint. - */ -value?: string; + * The amount of Ether to be transferred in the transaction, represented as a bigint. + */ + value?: string; /** - * The encoded function call data for the contract method. - */ -data?: string; + * The encoded function call data for the contract method. + */ + data?: string; } /** diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/estimate_gas_request.ts b/yarn-project/ethereum.js/src/eth_rpc/types/estimate_gas_request.ts index d08f7ee325f..9b1f54a9f2b 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/estimate_gas_request.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/estimate_gas_request.ts @@ -15,33 +15,33 @@ import { */ export interface EstimateRequest { /** - * The Ethereum address of the transaction sender. - */ -from?: EthAddress; + * The Ethereum address of the transaction sender. + */ + from?: EthAddress; /** - * The destination Ethereum address for the transaction. - */ -to?: EthAddress; + * The destination Ethereum address for the transaction. + */ + to?: EthAddress; /** - * The maximum amount of gas units allowed for the transaction execution. - */ -gas?: number; + * The maximum amount of gas units allowed for the transaction execution. + */ + gas?: number; /** - * The maximum fee per gas unit for the transaction. - */ -maxFeePerGas?: bigint; + * The maximum fee per gas unit for the transaction. + */ + maxFeePerGas?: bigint; /** - * The maximum fee per gas unit for transaction prioritization. - */ -maxPriorityFeePerGas?: bigint; + * The maximum fee per gas unit for transaction prioritization. + */ + maxPriorityFeePerGas?: bigint; /** - * The amount of Ether to be sent in the transaction, represented as a bigint. - */ -value?: bigint; + * The amount of Ether to be sent in the transaction, represented as a bigint. + */ + value?: bigint; /** - * The byte array of the transaction's input data. - */ -data?: Buffer; + * The byte array of the transaction's input data. + */ + data?: Buffer; } /** @@ -51,33 +51,33 @@ data?: Buffer; */ export interface RawEstimateRequest { /** - * The Ethereum address initiating the transaction. - */ -from?: string; + * The Ethereum address initiating the transaction. + */ + from?: string; /** - * The destination Ethereum address for the transaction. - */ -to?: string; + * The destination Ethereum address for the transaction. + */ + to?: string; /** - * The maximum amount of gas units to be used for the transaction. - */ -gas?: string; + * The maximum amount of gas units to be used for the transaction. + */ + gas?: string; /** - * Maximum fee per gas unit for the transaction. - */ -maxFeePerGas?: string; + * Maximum fee per gas unit for the transaction. + */ + maxFeePerGas?: string; /** - * The maximum fee per gas unit to prioritize transaction processing. - */ -maxPriorityFeePerGas?: string; + * The maximum fee per gas unit to prioritize transaction processing. + */ + maxPriorityFeePerGas?: string; /** - * The amount of Ether to be transferred in the transaction, represented as a BigInt. - */ -value?: string; + * The amount of Ether to be transferred in the transaction, represented as a BigInt. + */ + value?: string; /** - * The transaction's input data as a Buffer. - */ -data?: string; + * The transaction's input data as a Buffer. + */ + data?: string; } /** diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/log_request.ts b/yarn-project/ethereum.js/src/eth_rpc/types/log_request.ts index 8d65c0cfb5d..28cb3b9aa2c 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/log_request.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/log_request.ts @@ -8,25 +8,25 @@ import { NumberOrTag, numberOrTagToHex } from './number_or_tag.js'; */ export interface LogRequest { /** - * Filter object for specifying event fields to be matched in logs. - */ -filter?: Partial; + * Filter object for specifying event fields to be matched in logs. + */ + filter?: Partial; /** - * The block number or block tag to end the log search. - */ -toBlock?: NumberOrTag; + * The block number or block tag to end the log search. + */ + toBlock?: NumberOrTag; /** - * The starting block number or identifier to fetch logs from. - */ -fromBlock?: NumberOrTag; + * The starting block number or identifier to fetch logs from. + */ + fromBlock?: NumberOrTag; /** - * Ethereum address or array of addresses to filter logs by. - */ -address?: EthAddress | EthAddress[]; + * Ethereum address or array of addresses to filter logs by. + */ + address?: EthAddress | EthAddress[]; /** - * An array of topic filters for log events, allowing the selection of specific events or a combination thereof. - */ -topics?: (Buffer | Buffer[] | null)[]; + * An array of topic filters for log events, allowing the selection of specific events or a combination thereof. + */ + topics?: (Buffer | Buffer[] | null)[]; } /** @@ -35,21 +35,21 @@ topics?: (Buffer | Buffer[] | null)[]; */ export interface RawLogRequest { /** - * The block number or tag until which logs should be fetched, inclusive. - */ -toBlock?: string; + * The block number or tag until which logs should be fetched, inclusive. + */ + toBlock?: string; /** - * The starting block for the log search, inclusive. - */ -fromBlock?: string; + * The starting block for the log search, inclusive. + */ + fromBlock?: string; /** - * Ethereum address or an array of addresses, used as a filter for the logs. - */ -address?: string | string[]; + * Ethereum address or an array of addresses, used as a filter for the logs. + */ + address?: string | string[]; /** - * An array of topics used for filtering specific event logs. - */ -topics?: ((string | null) | (string | null)[])[]; + * An array of topics used for filtering specific event logs. + */ + topics?: ((string | null) | (string | null)[])[]; } /** diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/log_response.ts b/yarn-project/ethereum.js/src/eth_rpc/types/log_response.ts index 386987c2e30..a9e8c842d43 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/log_response.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/log_response.ts @@ -9,45 +9,45 @@ import { TxHash } from '../tx_hash.js'; */ export interface RawLogResponse { /** - * Unique identifier for a log event. - */ -id?: string; + * Unique identifier for a log event. + */ + id?: string; /** - * Indicates if the log entry has been removed due to a chain reorganization. - */ -removed?: boolean; + * Indicates if the log entry has been removed due to a chain reorganization. + */ + removed?: boolean; /** - * The index of the log entry within its corresponding block. - */ -logIndex: string | null; + * The index of the log entry within its corresponding block. + */ + logIndex: string | null; /** - * The block number where the log was generated. - */ -blockNumber: string | null; + * The block number where the log was generated. + */ + blockNumber: string | null; /** - * The unique identifier (hash) of the block containing the log event. - */ -blockHash: string | null; + * The unique identifier (hash) of the block containing the log event. + */ + blockHash: string | null; /** - * The unique hash identifying a specific transaction. - */ -transactionHash: string | null; + * The unique hash identifying a specific transaction. + */ + transactionHash: string | null; /** - * The index position of the transaction within a block. - */ -transactionIndex: string | null; + * The index position of the transaction within a block. + */ + transactionIndex: string | null; /** - * The Ethereum address associated with the log event. - */ -address: string; + * The Ethereum address associated with the log event. + */ + address: string; /** - * The hexadecimal encoded data associated with the log event. - */ -data: string; + * The hexadecimal encoded data associated with the log event. + */ + data: string; /** - * An array of indexed event parameters. - */ -topics: string[]; + * An array of indexed event parameters. + */ + topics: string[]; } /** @@ -57,50 +57,50 @@ topics: string[]; */ export interface LogResponse { /** - * Unique identifier for the log event. - */ -id: string | null; + * Unique identifier for the log event. + */ + id: string | null; /** - * Indicates whether the log entry has been removed due to a chain reorganization. - */ -removed?: boolean; + * Indicates whether the log entry has been removed due to a chain reorganization. + */ + removed?: boolean; /** - * The index position of the log entry within the block. - */ -logIndex: number | null; + * The index position of the log entry within the block. + */ + logIndex: number | null; /** - * The block number in which the log was generated. - */ -blockNumber: number | null; + * The block number in which the log was generated. + */ + blockNumber: number | null; /** - * The unique hash identifier of the block containing the log entry. - */ -blockHash: string | null; + * The unique hash identifier of the block containing the log entry. + */ + blockHash: string | null; /** - * The unique identifier of the transaction in the blockchain. - */ -transactionHash: TxHash | null; + * The unique identifier of the transaction in the blockchain. + */ + transactionHash: TxHash | null; /** - * The index position of the transaction within the block. - */ -transactionIndex: number | null; + * The index position of the transaction within the block. + */ + transactionIndex: number | null; /** - * The Ethereum address associated with the log event. - */ -address: EthAddress; + * The Ethereum address associated with the log event. + */ + address: EthAddress; /** - * The data field of a logged event in the Ethereum contract. - */ -data: string; + * The data field of a logged event in the Ethereum contract. + */ + data: string; /** - * An array of indexed event arguments. - */ -topics: string[]; + * An array of indexed event arguments. + */ + topics: string[]; } /** * Converts a RawLogResponse object into a LogResponse object. - * The function generates a custom log id, if not provided, by concatenating the blockHash, transactionHash, and logIndex values after removing the '0x' prefix. + * The function generates a custom log id, if not provided, by concatenating the blockHash, transactionHash, and logIndex values after removing the '0x' prefix. * It also converts string representations of blockNumber, transactionIndex, and logIndex to their corresponding numeric values. * Additionally, it creates EthAddress and TxHash instances for address and transactionHash fields, respectively. * diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_receipt.ts b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_receipt.ts index 4b85dd5c076..c61e221a4cf 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_receipt.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_receipt.ts @@ -10,49 +10,49 @@ import { TxHash } from '../tx_hash.js'; */ export interface RawTransactionReceipt { /** - * The unique identifier of the transaction. - */ -transactionHash: string; + * The unique identifier of the transaction. + */ + transactionHash: string; /** - * The index of the transaction within the block. - */ -transactionIndex: string; + * The index of the transaction within the block. + */ + transactionIndex: string; /** - * The hash identifier of the block containing the transaction. - */ -blockHash: string; + * The hash identifier of the block containing the transaction. + */ + blockHash: string; /** - * The block number in which the transaction was included. - */ -blockNumber: string; + * The block number in which the transaction was included. + */ + blockNumber: string; /** - * The Ethereum address of the transaction sender. - */ -from: string; + * The Ethereum address of the transaction sender. + */ + from: string; /** - * The destination Ethereum address involved in the transaction. - */ -to: string | null; + * The destination Ethereum address involved in the transaction. + */ + to: string | null; /** - * The total amount of gas used by all transactions in the block up to and including this transaction. - */ -cumulativeGasUsed: string; + * The total amount of gas used by all transactions in the block up to and including this transaction. + */ + cumulativeGasUsed: string; /** - * The amount of gas consumed by the transaction. - */ -gasUsed: string; + * The amount of gas consumed by the transaction. + */ + gasUsed: string; /** - * Address of the deployed contract, if applicable. - */ -contractAddress: string | null; + * Address of the deployed contract, if applicable. + */ + contractAddress: string | null; /** - * An array of event logs emitted by the smart contract during the transaction execution. - */ -logs: RawLogResponse[]; + * An array of event logs emitted by the smart contract during the transaction execution. + */ + logs: RawLogResponse[]; /** - * The transaction success status, where 'true' indicates success and 'false' indicates failure. - */ -status: string; + * The transaction success status, where 'true' indicates success and 'false' indicates failure. + */ + status: string; } /** @@ -61,49 +61,49 @@ status: string; */ export interface TransactionReceipt { /** - * The unique hash identifier of the transaction. - */ -transactionHash: TxHash; + * The unique hash identifier of the transaction. + */ + transactionHash: TxHash; /** - * The index of the transaction within its containing block. - */ -transactionIndex: number; + * The index of the transaction within its containing block. + */ + transactionIndex: number; /** - * The unique identifier of the block containing the transaction. - */ -blockHash: string; + * The unique identifier of the block containing the transaction. + */ + blockHash: string; /** - * The block number containing the transaction. - */ -blockNumber: number; + * The block number containing the transaction. + */ + blockNumber: number; /** - * The Ethereum address of the transaction sender. - */ -from: EthAddress; + * The Ethereum address of the transaction sender. + */ + from: EthAddress; /** - * The destination Ethereum address involved in the transaction. - */ -to?: EthAddress; + * The destination Ethereum address involved in the transaction. + */ + to?: EthAddress; /** - * The total amount of gas used by all transactions up to and including this one in the block. - */ -cumulativeGasUsed: number; + * The total amount of gas used by all transactions up to and including this one in the block. + */ + cumulativeGasUsed: number; /** - * The amount of gas utilized during the transaction execution. - */ -gasUsed: number; + * The amount of gas utilized during the transaction execution. + */ + gasUsed: number; /** - * The Ethereum address of the deployed smart contract, if applicable. - */ -contractAddress?: EthAddress; + * The Ethereum address of the deployed smart contract, if applicable. + */ + contractAddress?: EthAddress; /** - * An array of log events emitted by the transaction. - */ -logs: LogResponse[]; + * An array of log events emitted by the transaction. + */ + logs: LogResponse[]; /** - * The transaction execution status; true if successful, false otherwise. - */ -status: boolean; + * The transaction execution status; true if successful, false otherwise. + */ + status: boolean; } /** diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts index 6b606c56e98..30dcff20ae2 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_request.ts @@ -14,37 +14,37 @@ import { */ export interface TransactionRequest { /** - * The Ethereum address initiating the transaction. - */ -from: EthAddress; + * The Ethereum address initiating the transaction. + */ + from: EthAddress; /** - * The destination Ethereum address for the transaction. - */ -to?: EthAddress; + * The destination Ethereum address for the transaction. + */ + to?: EthAddress; /** - * The maximum amount of gas units allowed for the transaction execution. - */ -gas?: number; + * The maximum amount of gas units allowed for the transaction execution. + */ + gas?: number; /** - * The maximum fee per gas unit for the transaction. - */ -maxFeePerGas?: bigint; + * The maximum fee per gas unit for the transaction. + */ + maxFeePerGas?: bigint; /** - * The maximum fee per gas unit that the sender is willing to pay for transaction priority. - */ -maxPriorityFeePerGas?: bigint; + * The maximum fee per gas unit that the sender is willing to pay for transaction priority. + */ + maxPriorityFeePerGas?: bigint; /** - * The amount of Ether to be transferred in the transaction. - */ -value?: bigint; + * The amount of Ether to be transferred in the transaction. + */ + value?: bigint; /** - * The encoded contract function call data. - */ -data?: Buffer; + * The encoded contract function call data. + */ + data?: Buffer; /** - * A unique number that prevents double-spending in transactions. - */ -nonce?: number; + * A unique number that prevents double-spending in transactions. + */ + nonce?: number; } /** diff --git a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_response.ts b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_response.ts index 2598ef6d48d..d07a1771995 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/types/transaction_response.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/types/transaction_response.ts @@ -14,73 +14,73 @@ import { */ export interface RawTransactionResponse { /** - * The hash of the block containing the transaction. - */ -blockHash: string | null; + * The hash of the block containing the transaction. + */ + blockHash: string | null; /** - * The block number in which the transaction is included. - */ -blockNumber: string | null; + * The block number in which the transaction is included. + */ + blockNumber: string | null; /** - * The originating Ethereum address of the transaction. - */ -from: string; + * The originating Ethereum address of the transaction. + */ + from: string; /** - * The amount of gas required for the transaction execution. - */ -gas: string; + * The amount of gas required for the transaction execution. + */ + gas: string; /** - * The price per unit of gas in the transaction. - */ -gasPrice: string; + * The price per unit of gas in the transaction. + */ + gasPrice: string; /** - * Maximum fee per gas unit for a transaction. - */ -maxFeePerGas?: string; + * Maximum fee per gas unit for a transaction. + */ + maxFeePerGas?: string; /** - * The maximum fee per gas unit for transaction prioritization. - */ -maxPriorityFeePerGas?: string; + * The maximum fee per gas unit for transaction prioritization. + */ + maxPriorityFeePerGas?: string; /** - * The unique identifier of the transaction. - */ -hash: string; + * The unique identifier of the transaction. + */ + hash: string; /** - * Raw input data of the transaction. - */ -input: string; + * Raw input data of the transaction. + */ + input: string; /** - * A unique transaction counter for the sender. - */ -nonce: string; + * A unique transaction counter for the sender. + */ + nonce: string; /** - * The destination Ethereum address involved in the transaction. - */ -to: string | null; + * The destination Ethereum address involved in the transaction. + */ + to: string | null; /** - * The index of the transaction within its containing block. - */ -transactionIndex: string | null; + * The index of the transaction within its containing block. + */ + transactionIndex: string | null; /** - * The Ethereum transaction type identifier. - */ -type: string; + * The Ethereum transaction type identifier. + */ + type: string; /** - * The amount of Ether transferred in the transaction. - */ -value: string; + * The amount of Ether transferred in the transaction. + */ + value: string; /** - * The recovery identifier of the transaction signature. - */ -v: string; + * The recovery identifier of the transaction signature. + */ + v: string; /** - * The 'r' value of the transaction's ECDSA signature. - */ -r: string; + * The 'r' value of the transaction's ECDSA signature. + */ + r: string; /** - * Signature component for transaction verification. - */ -s: string; + * Signature component for transaction verification. + */ + s: string; } /** @@ -89,73 +89,73 @@ s: string; */ export interface TransactionResponse { /** - * The hash of the block containing the transaction. - */ -blockHash: string | null; + * The hash of the block containing the transaction. + */ + blockHash: string | null; /** - * The block number containing the transaction, or null if not yet mined. - */ -blockNumber: number | null; + * The block number containing the transaction, or null if not yet mined. + */ + blockNumber: number | null; /** - * The originating Ethereum address of the transaction. - */ -from: EthAddress; + * The originating Ethereum address of the transaction. + */ + from: EthAddress; /** - * Amount of gas units required for executing the transaction. - */ -gas: number; + * Amount of gas units required for executing the transaction. + */ + gas: number; /** - * The amount of Ether paid per unit of gas for the transaction. - */ -gasPrice: bigint; + * The amount of Ether paid per unit of gas for the transaction. + */ + gasPrice: bigint; /** - * The maximum fee per gas unit for the transaction. - */ -maxFeePerGas?: bigint; + * The maximum fee per gas unit for the transaction. + */ + maxFeePerGas?: bigint; /** - * The maximum fee per gas a user is willing to pay for transaction priority. - */ -maxPriorityFeePerGas?: bigint; + * The maximum fee per gas a user is willing to pay for transaction priority. + */ + maxPriorityFeePerGas?: bigint; /** - * The unique identifier of the transaction. - */ -hash: string; + * The unique identifier of the transaction. + */ + hash: string; /** - * Raw binary data representing smart contract method calls and parameters. - */ -input: Buffer; + * Raw binary data representing smart contract method calls and parameters. + */ + input: Buffer; /** - * An integer value representing the number of transactions sent by the sender. - */ -nonce: number; + * An integer value representing the number of transactions sent by the sender. + */ + nonce: number; /** - * The destination Ethereum address for the transaction. - */ -to: EthAddress | null; + * The destination Ethereum address for the transaction. + */ + to: EthAddress | null; /** - * The position of the transaction within the block. - */ -transactionIndex: number | null; + * The position of the transaction within the block. + */ + transactionIndex: number | null; /** - * Transaction type identifier. - */ -type: number; + * Transaction type identifier. + */ + type: number; /** - * The value transferred in the transaction, represented as a bigint. - */ -value: bigint; + * The value transferred in the transaction, represented as a bigint. + */ + value: bigint; /** - * The recovery identifier of the ECDSA signature. - */ -v: string; + * The recovery identifier of the ECDSA signature. + */ + v: string; /** - * The 'r' value of the ECDSA signature. - */ -r: string; + * The 'r' value of the ECDSA signature. + */ + r: string; /** - * Signature recovery value for ECDSA. - */ -s: string; + * Signature recovery value for ECDSA. + */ + s: string; } /** diff --git a/yarn-project/ethereum.js/src/eth_sign/sign.ts b/yarn-project/ethereum.js/src/eth_sign/sign.ts index d105aff6790..b743eb79119 100644 --- a/yarn-project/ethereum.js/src/eth_sign/sign.ts +++ b/yarn-project/ethereum.js/src/eth_sign/sign.ts @@ -13,60 +13,62 @@ const secp256k1 = new elliptic.ec('secp256k1'); * Ethereum transactions that require signing and validation processes. */ export class EthSignature { - constructor(/** - * The 'r' value of an ECDSA signature. - */ -public r: Buffer, /** - * The 's' value of the ECDSA signature. - */ -public s: Buffer, /** - * The recovery parameter used in ECDSA signatures. - */ -public v: number) {} + constructor( + /** + * The 'r' value of an ECDSA signature. + */ + public r: Buffer, + /** + * The 's' value of the ECDSA signature. + */ public s: Buffer, + /** + * The recovery parameter used in ECDSA signatures. + */ public v: number, + ) {} /** - * Create an EthSignature instance from a given buffer. - * The input 'buf' should be a Buffer containing the 'r', 's', and 'v' values of the signature. - * 'r' and 's' values are each 32 bytes long, while 'v' is a single byte. - * Throws an error if the input buffer length is not exactly 65 bytes. - * - * @param buf - The Buffer containing the 'r', 's', and 'v' values of the signature. - * @returns An EthSignature instance. - */ -static fromBuffer(buf: Buffer) { + * Create an EthSignature instance from a given buffer. + * The input 'buf' should be a Buffer containing the 'r', 's', and 'v' values of the signature. + * 'r' and 's' values are each 32 bytes long, while 'v' is a single byte. + * Throws an error if the input buffer length is not exactly 65 bytes. + * + * @param buf - The Buffer containing the 'r', 's', and 'v' values of the signature. + * @returns An EthSignature instance. + */ + static fromBuffer(buf: Buffer) { return new EthSignature(buf.subarray(0, 32), buf.subarray(32, 64), buf[64]); } /** - * Create an EthSignature instance from a hex-encoded string. - * The input 'hex' should be prefixed with '0x', followed by 128 hex characters (for r, s) and 2 hex characters for the `v` value. - * Throws an error if the input length is invalid or any of the r, s, v values are out of range. - * - * @param hex - The hex-encoded string representing the Ethereum signature. - * @returns An EthSignature instance. - */ -static fromString(hex: string) { + * Create an EthSignature instance from a hex-encoded string. + * The input 'hex' should be prefixed with '0x', followed by 128 hex characters (for r, s) and 2 hex characters for the `v` value. + * Throws an error if the input length is invalid or any of the r, s, v values are out of range. + * + * @param hex - The hex-encoded string representing the Ethereum signature. + * @returns An EthSignature instance. + */ + static fromString(hex: string) { return EthSignature.fromBuffer(hexToBuffer(hex)); } /** - * Converts the EthSignature instance to a Buffer representation. - * The resulting buffer contains the concatenated 'r', 's', and 'v' values of the signature. - * This function is useful when working with raw binary data or when storing the signature. - * - * @returns A Buffer containing the concatenated 'r', 's', and 'v' values of the EthSignature instance. - */ -toBuffer() { + * Converts the EthSignature instance to a Buffer representation. + * The resulting buffer contains the concatenated 'r', 's', and 'v' values of the signature. + * This function is useful when working with raw binary data or when storing the signature. + * + * @returns A Buffer containing the concatenated 'r', 's', and 'v' values of the EthSignature instance. + */ + toBuffer() { return Buffer.concat([this.r, this.s, numToUInt8(this.v)]); } /** - * Convert the EthSignature instance into a hex-encoded string. - * The resulting string is prefixed with '0x' and represents the concatenated r, s, and v values of the signature. - * - * @returns A hex-encoded string representing the EthSignature instance. - */ -toString() { + * Convert the EthSignature instance into a hex-encoded string. + * The resulting string is prefixed with '0x' and represents the concatenated r, s, and v values of the signature. + * + * @returns A hex-encoded string representing the EthSignature instance. + */ + toString() { return '0x' + this.toBuffer().toString('hex'); } } diff --git a/yarn-project/ethereum.js/src/eth_transaction/eth_transaction.ts b/yarn-project/ethereum.js/src/eth_transaction/eth_transaction.ts index f229731040e..4b9df724248 100644 --- a/yarn-project/ethereum.js/src/eth_transaction/eth_transaction.ts +++ b/yarn-project/ethereum.js/src/eth_transaction/eth_transaction.ts @@ -7,35 +7,35 @@ import { EthAddress } from '@aztec/foundation'; */ export interface EthTransaction { /** - * The unique identifier for the Ethereum network. - */ -chainId: number; + * The unique identifier for the Ethereum network. + */ + chainId: number; /** - * The destination Ethereum address for the transaction. - */ -to?: EthAddress; + * The destination Ethereum address for the transaction. + */ + to?: EthAddress; /** - * The maximum amount of gas units allocated for the execution of the transaction. - */ -gas: number; + * The maximum amount of gas units allocated for the execution of the transaction. + */ + gas: number; /** - * The maximum fee per gas unit for the transaction, expressed in Gwei. - */ -maxFeePerGas: bigint; + * The maximum fee per gas unit for the transaction, expressed in Gwei. + */ + maxFeePerGas: bigint; /** - * Maximum fee per gas unit to prioritize the transaction inclusion. - */ -maxPriorityFeePerGas: bigint; + * Maximum fee per gas unit to prioritize the transaction inclusion. + */ + maxPriorityFeePerGas: bigint; /** - * The amount of Ether to be transferred in the transaction. - */ -value: bigint; + * The amount of Ether to be transferred in the transaction. + */ + value: bigint; /** - * The input data for the transaction execution. - */ -data?: Buffer; + * The input data for the transaction execution. + */ + data?: Buffer; /** - * A unique value representing the number of transactions sent from a specific address. - */ -nonce: number; + * A unique value representing the number of transactions sent from a specific address. + */ + nonce: number; } diff --git a/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts b/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts index 146b0b9d1ac..c6fc41e0bfa 100644 --- a/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts +++ b/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts @@ -10,17 +10,17 @@ import { numToUInt8 } from '../serialize/index.js'; */ export interface SignedEthTransaction { /** - * The cryptographic signature of the transaction. - */ -signature: EthSignature; + * The cryptographic signature of the transaction. + */ + signature: EthSignature; /** - * The Keccak-256 hash of the signed transaction message. - */ -messageHash: Buffer; + * The Keccak-256 hash of the signed transaction message. + */ + messageHash: Buffer; /** - * The serialized raw Ethereum transaction in RLP-encoded format. - */ -rawTransaction: Buffer; + * The serialized raw Ethereum transaction in RLP-encoded format. + */ + rawTransaction: Buffer; } /** diff --git a/yarn-project/ethereum.js/src/eth_typed_data/typed_data.ts b/yarn-project/ethereum.js/src/eth_typed_data/typed_data.ts index bc38fb76f3f..8454f586768 100644 --- a/yarn-project/ethereum.js/src/eth_typed_data/typed_data.ts +++ b/yarn-project/ethereum.js/src/eth_typed_data/typed_data.ts @@ -5,42 +5,47 @@ */ export interface TypedData { /** - * Represents EIP-712 domain data containing application-specific information for signing typed data. - */ -domain: { + * Represents EIP-712 domain data containing application-specific information for signing typed data. + */ + domain: { /** - * The identifying name of the domain. - */ -name: string; + * The identifying name of the domain. + */ + name: string; /** - * Version identifier for the domain. - */ -version: string; + * Version identifier for the domain. + */ + version: string; /** - * The unique identifier of the blockchain network. - */ -chainId: number; + * The unique identifier of the blockchain network. + */ + chainId: number; /** - * The address of the contract responsible for data verification. - */ -verifyingContract: string; + * The address of the contract responsible for data verification. + */ + verifyingContract: string; }; /** - * An object containing structured data types for EIP-712 signing. - */ -types: { [key: string]: { /** - * The name of the domain in which the TypedData is structured. - */ -name: string; /** - * A mapping of data types with their corresponding properties, including name and type. - */ -type: string }[] }; + * An object containing structured data types for EIP-712 signing. + */ + types: { + [key: string]: { + /** + * The name of the domain in which the TypedData is structured. + */ + name: string; + /** + * A mapping of data types with their corresponding properties, including name and type. + */ + type: string; + }[]; + }; /** - * The specific structured data to be signed and verified. - */ -message: any; + * The specific structured data to be signed and verified. + */ + message: any; /** - * The main type used for structuring and verifying the EIP-712 typed data. - */ -primaryType: string; + * The main type used for structuring and verifying the EIP-712 typed data. + */ + primaryType: string; } diff --git a/yarn-project/ethereum.js/src/eth_wallet/eth_wallet.ts b/yarn-project/ethereum.js/src/eth_wallet/eth_wallet.ts index 7957049ccfe..2b5ea5dbdc9 100644 --- a/yarn-project/ethereum.js/src/eth_wallet/eth_wallet.ts +++ b/yarn-project/ethereum.js/src/eth_wallet/eth_wallet.ts @@ -10,28 +10,28 @@ import { decryptFromKeyStoreJson, KeyStoreEncryptOptions, KeyStoreJson } from '. */ export class EthWallet { /** - * The total number of accounts stored in the wallet. - */ -public length = 0; + * The total number of accounts stored in the wallet. + */ + public length = 0; /** - * Array containing Ethereum accounts in the wallet. - */ -public accounts: EthAccount[] = []; + * Array containing Ethereum accounts in the wallet. + */ + public accounts: EthAccount[] = []; constructor(numberOfAccounts = 0) { this.create(numberOfAccounts); } /** - * Create an EthWallet instance from a mnemonic string for the specified number of accounts. - * The mnemonic should be a BIP-39 compliant seed phrase containing a series of words, used for generating deterministic keys. - * This function generates EthAccounts based on the given mnemonic and adds them to the wallet. - * - * @param mnemonic - The BIP-39 compliant seed phrase as a string. - * @param numberOfAccounts - The number of accounts to generate and add to the wallet. - * @returns An EthWallet instance containing the generated accounts. - */ -public static fromMnemonic(mnemonic: string, numberOfAccounts: number) { + * Create an EthWallet instance from a mnemonic string for the specified number of accounts. + * The mnemonic should be a BIP-39 compliant seed phrase containing a series of words, used for generating deterministic keys. + * This function generates EthAccounts based on the given mnemonic and adds them to the wallet. + * + * @param mnemonic - The BIP-39 compliant seed phrase as a string. + * @param numberOfAccounts - The number of accounts to generate and add to the wallet. + * @returns An EthWallet instance containing the generated accounts. + */ + public static fromMnemonic(mnemonic: string, numberOfAccounts: number) { const wallet = new EthWallet(); for (let i = 0; i < numberOfAccounts; ++i) { const path = `m/44'/60'/0'/0/${i}`; @@ -41,15 +41,15 @@ public static fromMnemonic(mnemonic: string, numberOfAccounts: number) { } /** - * Create an EthWallet instance from a provided seed Buffer and number of accounts. - * The function generates the specified number of EthAccounts using the seed and - * BIP44 derivation path, then adds them to the newly created EthWallet. - * - * @param seed - A Buffer containing the seed for generating the HD wallet. - * @param numberOfAccounts - The number of EthAccounts to generate using the seed. - * @returns An EthWallet instance containing the generated EthAccounts. - */ -public static fromSeed(seed: Buffer, numberOfAccounts: number) { + * Create an EthWallet instance from a provided seed Buffer and number of accounts. + * The function generates the specified number of EthAccounts using the seed and + * BIP44 derivation path, then adds them to the newly created EthWallet. + * + * @param seed - A Buffer containing the seed for generating the HD wallet. + * @param numberOfAccounts - The number of EthAccounts to generate using the seed. + * @returns An EthWallet instance containing the generated EthAccounts. + */ + public static fromSeed(seed: Buffer, numberOfAccounts: number) { const wallet = new EthWallet(); for (let i = 0; i < numberOfAccounts; ++i) { const path = `m/44'/60'/0'/0/${i}`; @@ -59,31 +59,31 @@ public static fromSeed(seed: Buffer, numberOfAccounts: number) { } /** - * Create an EthWallet instance from an array of KeyStoreJson objects. - * Decrypts each keystore using the provided password, adds the accounts to the wallet, - * and returns the wallet with decrypted accounts. Throws an error if decryption fails - * due to an incorrect password or other issues. - * - * @param keyStores - An array of KeyStoreJson objects representing encrypted Ethereum accounts. - * @param password - The password used for decrypting the keystores. - * @returns A Promise that resolves to an EthWallet instance with decrypted accounts. - */ -public static async fromKeystores(keyStores: KeyStoreJson[], password: string) { + * Create an EthWallet instance from an array of KeyStoreJson objects. + * Decrypts each keystore using the provided password, adds the accounts to the wallet, + * and returns the wallet with decrypted accounts. Throws an error if decryption fails + * due to an incorrect password or other issues. + * + * @param keyStores - An array of KeyStoreJson objects representing encrypted Ethereum accounts. + * @param password - The password used for decrypting the keystores. + * @returns A Promise that resolves to an EthWallet instance with decrypted accounts. + */ + public static async fromKeystores(keyStores: KeyStoreJson[], password: string) { const wallet = new EthWallet(); await wallet.decrypt(keyStores, password); return wallet; } /** - * Create a specified number of Ethereum accounts and add them to the wallet. - * Generates new Ethereum accounts using an optional entropy buffer for randomness. - * Returns an array of the created EthAccount instances. - * - * @param numberOfAccounts - The number of accounts to create. - * @param entropy - Optional buffer containing entropy bytes for creating accounts. - * @returns An array of created EthAccount instances. - */ -public create(numberOfAccounts: number, entropy?: Buffer): EthAccount[] { + * Create a specified number of Ethereum accounts and add them to the wallet. + * Generates new Ethereum accounts using an optional entropy buffer for randomness. + * Returns an array of the created EthAccount instances. + * + * @param numberOfAccounts - The number of accounts to create. + * @param entropy - Optional buffer containing entropy bytes for creating accounts. + * @returns An array of created EthAccount instances. + */ + public create(numberOfAccounts: number, entropy?: Buffer): EthAccount[] { for (let i = 0; i < numberOfAccounts; ++i) { this.add(EthAccount.create(entropy).privateKey); } @@ -91,14 +91,14 @@ public create(numberOfAccounts: number, entropy?: Buffer): EthAccount[] { } /** - * Retrieve an EthAccount instance from the wallet using either an Ethereum address or a numeric index. - * The function searches for an account based on the provided input and returns it if found. - * If multiple accounts are present, use the address or index to specify a unique account. - * - * @param addressOrIndex - An EthAddress instance or a number representing the account's index in the wallet. - * @returns The EthAccount instance corresponding to the provided address or index, or undefined if not found. - */ -public getAccount(addressOrIndex: EthAddress | number) { + * Retrieve an EthAccount instance from the wallet using either an Ethereum address or a numeric index. + * The function searches for an account based on the provided input and returns it if found. + * If multiple accounts are present, use the address or index to specify a unique account. + * + * @param addressOrIndex - An EthAddress instance or a number representing the account's index in the wallet. + * @returns The EthAccount instance corresponding to the provided address or index, or undefined if not found. + */ + public getAccount(addressOrIndex: EthAddress | number) { if (addressOrIndex instanceof EthAddress) { return this.accounts.find(a => a && a.address.equals(addressOrIndex)); } @@ -106,14 +106,14 @@ public getAccount(addressOrIndex: EthAddress | number) { } /** - * Retrieve the index of an account in the wallet based on the provided address or index. - * If the input is an EthAddress, this function searches for an account with a matching address and returns its index. - * If the input is a number, it directly returns the input number as the index. Returns -1 if no matching account is found. - * - * @param addressOrIndex - An EthAddress object representing the Ethereum address or a number representing the account index. - * @returns The index of the account within the wallet or -1 if not found. - */ -public getAccountIndex(addressOrIndex: EthAddress | number) { + * Retrieve the index of an account in the wallet based on the provided address or index. + * If the input is an EthAddress, this function searches for an account with a matching address and returns its index. + * If the input is a number, it directly returns the input number as the index. Returns -1 if no matching account is found. + * + * @param addressOrIndex - An EthAddress object representing the Ethereum address or a number representing the account index. + * @returns The index of the account within the wallet or -1 if not found. + */ + public getAccountIndex(addressOrIndex: EthAddress | number) { if (addressOrIndex instanceof EthAddress) { return this.accounts.findIndex(a => a && a.address.equals(addressOrIndex)); } @@ -121,35 +121,35 @@ public getAccountIndex(addressOrIndex: EthAddress | number) { } /** - * Get an array of the indices of all EthAccounts stored in the wallet. - * The returned indices can be used to access EthAccount instances through the 'getAccount' function. - * - * @returns An array of integers representing the indices of the EthAccounts in the wallet. - */ -public getAccountIndicies() { + * Get an array of the indices of all EthAccounts stored in the wallet. + * The returned indices can be used to access EthAccount instances through the 'getAccount' function. + * + * @returns An array of integers representing the indices of the EthAccounts in the wallet. + */ + public getAccountIndicies() { return Object.keys(this.accounts).map(key => +key); } /** - * Retrieve the Ethereum addresses of all accounts in the wallet. - * This function maps the accounts to their corresponding addresses - * and returns an array of EthAddress instances. - * - * @returns An array of EthAddress instances representing the Ethereum addresses of the accounts in the wallet. - */ -public getAccountAddresses() { + * Retrieve the Ethereum addresses of all accounts in the wallet. + * This function maps the accounts to their corresponding addresses + * and returns an array of EthAddress instances. + * + * @returns An array of EthAddress instances representing the Ethereum addresses of the accounts in the wallet. + */ + public getAccountAddresses() { return this.accounts.map(account => account.address); } /** - * Add an EthAccount instance or a private key to the wallet. - * If an account with the same address already exists in the wallet, it returns the existing account. - * Otherwise, it adds the new account at a safe index and increments the wallet length. - * - * @param accountOrKey - An EthAccount instance or a Buffer containing the private key. - * @returns The added or existing EthAccount instance. - */ -public add(accountOrKey: Buffer | EthAccount): EthAccount { + * Add an EthAccount instance or a private key to the wallet. + * If an account with the same address already exists in the wallet, it returns the existing account. + * Otherwise, it adds the new account at a safe index and increments the wallet length. + * + * @param accountOrKey - An EthAccount instance or a Buffer containing the private key. + * @returns The added or existing EthAccount instance. + */ + public add(accountOrKey: Buffer | EthAccount): EthAccount { const account = Buffer.isBuffer(accountOrKey) ? new EthAccount(accountOrKey) : accountOrKey; const existing = this.getAccount(account.address); @@ -165,14 +165,14 @@ public add(accountOrKey: Buffer | EthAccount): EthAccount { } /** - * Removes an account from the wallet based on the provided address or index. - * If the given address or index matches one of the existing accounts in the wallet, the account will be removed, - * and the function returns true. If the address or index is not found in the wallet, the function returns false. - * - * @param addressOrIndex - The EthAddress or index number of the account to be removed from the wallet. - * @returns A boolean value indicating whether the removal was successful. - */ -public remove(addressOrIndex: number | EthAddress) { + * Removes an account from the wallet based on the provided address or index. + * If the given address or index matches one of the existing accounts in the wallet, the account will be removed, + * and the function returns true. If the address or index is not found in the wallet, the function returns false. + * + * @param addressOrIndex - The EthAddress or index number of the account to be removed from the wallet. + * @returns A boolean value indicating whether the removal was successful. + */ + public remove(addressOrIndex: number | EthAddress) { const index = this.getAccountIndex(addressOrIndex); if (index === -1) { @@ -186,36 +186,36 @@ public remove(addressOrIndex: number | EthAddress) { } /** - * Clears all the accounts stored in the EthWallet instance. - * The length of EthWallet will be set to 0 and the accounts array will become empty. - */ -public clear() { + * Clears all the accounts stored in the EthWallet instance. + * The length of EthWallet will be set to 0 and the accounts array will become empty. + */ + public clear() { this.accounts = []; this.length = 0; } /** - * Encrypts the account private keys in the wallet using the provided password and returns an array of KeyStoreJson objects. - * The KeyStoreJson objects follow the Ethereum keystore format (UTC / JSON) standard and can be later used to decrypt the accounts. - * The optional 'options' parameter allows customizing the encryption process, such as the number of iterations or salt. - * - * @param password - The user-defined password to use for encrypting the account private keys. - * @param options - Optional KeyStoreEncryptOptions object for customizing the encryption process. - * @returns A Promise that resolves to an array of encrypted KeyStoreJson objects. - */ -public encrypt(password: string, options?: KeyStoreEncryptOptions) { + * Encrypts the account private keys in the wallet using the provided password and returns an array of KeyStoreJson objects. + * The KeyStoreJson objects follow the Ethereum keystore format (UTC / JSON) standard and can be later used to decrypt the accounts. + * The optional 'options' parameter allows customizing the encryption process, such as the number of iterations or salt. + * + * @param password - The user-defined password to use for encrypting the account private keys. + * @param options - Optional KeyStoreEncryptOptions object for customizing the encryption process. + * @returns A Promise that resolves to an array of encrypted KeyStoreJson objects. + */ + public encrypt(password: string, options?: KeyStoreEncryptOptions) { return Promise.all(this.getAccountIndicies().map(index => this.accounts[index].toKeyStoreJson(password, options))); } /** - * Decrypts an array of KeyStoreJson objects using the provided password and adds the decrypted accounts to the wallet. - * If any of the accounts cannot be decrypted, it will throw an error with a message indicating that the password might be wrong. - * - * @param encryptedWallet - Array of KeyStoreJson objects representing the encrypted wallet. - * @param password - The password used to decrypt the encrypted wallet. - * @returns An array of EthAccount instances stored in the wallet after successful decryption. - */ -public async decrypt(encryptedWallet: KeyStoreJson[], password: string) { + * Decrypts an array of KeyStoreJson objects using the provided password and adds the decrypted accounts to the wallet. + * If any of the accounts cannot be decrypted, it will throw an error with a message indicating that the password might be wrong. + * + * @param encryptedWallet - Array of KeyStoreJson objects representing the encrypted wallet. + * @param password - The password used to decrypt the encrypted wallet. + * @returns An array of EthAccount instances stored in the wallet after successful decryption. + */ + public async decrypt(encryptedWallet: KeyStoreJson[], password: string) { const decrypted = await Promise.all(encryptedWallet.map(keystore => decryptFromKeyStoreJson(keystore, password))); decrypted.forEach(account => { if (!account) { @@ -229,13 +229,13 @@ public async decrypt(encryptedWallet: KeyStoreJson[], password: string) { } /** - * Find an available index to safely add a new account in the accounts array. - * The method iterates through the accounts array, incrementing the pointer until it finds an empty position. - * - * @param pointer - Optional starting index for the search. Default value is 0. - * @returns The index of the first empty position in the accounts array. - */ -private findSafeIndex(pointer = 0) { + * Find an available index to safely add a new account in the accounts array. + * The method iterates through the accounts array, incrementing the pointer until it finds an empty position. + * + * @param pointer - Optional starting index for the search. Default value is 0. + * @returns The index of the first empty position in the accounts array. + */ + private findSafeIndex(pointer = 0) { while (this.accounts[pointer]) { ++pointer; } diff --git a/yarn-project/ethereum.js/src/keystore/index.test.ts b/yarn-project/ethereum.js/src/keystore/index.test.ts index e0d5a759016..b5afe016de2 100644 --- a/yarn-project/ethereum.js/src/keystore/index.test.ts +++ b/yarn-project/ethereum.js/src/keystore/index.test.ts @@ -1,16 +1,20 @@ import { decryptFromKeyStoreJson, encryptToKeyStoreJson, KeyStoreJson } from './index.js'; import { EthAddress } from '@aztec/foundation'; -const staticTests: { /** - * A JSON representation of the encrypted key store for an Ethereum account. - */ -json: KeyStoreJson; /** - * The password used to encrypt and decrypt the keystore file. - */ -password: string; /** - * The private key associated with the Ethereum address. - */ -priv: string }[] = [ +const staticTests: { + /** + * A JSON representation of the encrypted key store for an Ethereum account. + */ + json: KeyStoreJson; + /** + * The password used to encrypt and decrypt the keystore file. + */ + password: string; + /** + * The private key associated with the Ethereum address. + */ + priv: string; +}[] = [ { json: { crypto: { diff --git a/yarn-project/ethereum.js/src/keystore/index.ts b/yarn-project/ethereum.js/src/keystore/index.ts index cfc230042bf..086eaca66b2 100644 --- a/yarn-project/ethereum.js/src/keystore/index.ts +++ b/yarn-project/ethereum.js/src/keystore/index.ts @@ -9,25 +9,25 @@ import { pbkdf2, scrypt, keccak256, randomBytes } from '../crypto/index.js'; */ interface ScryptKdfParams { /** - * The desired output key length in bytes. - */ -dklen: number; + * The desired output key length in bytes. + */ + dklen: number; /** - * The cost factor for scrypt key derivation function. - */ -n: number; + * The cost factor for scrypt key derivation function. + */ + n: number; /** - * The parallelization factor for the scrypt key derivation function. - */ -p: number; + * The parallelization factor for the scrypt key derivation function. + */ + p: number; /** - * The CPU/memory cost factor for scrypt key derivation. - */ -r: number; + * The CPU/memory cost factor for scrypt key derivation. + */ + r: number; /** - * A cryptographic element used to enhance password security. - */ -salt: string; + * A cryptographic element used to enhance password security. + */ + salt: string; } /** @@ -36,21 +36,21 @@ salt: string; */ interface PbKdf2Params { /** - * The desired length of the derived key in bytes. - */ -dklen: number; + * The desired length of the derived key in bytes. + */ + dklen: number; /** - * The iteration count for the PBKDF2 key derivation function. - */ -c: number; + * The iteration count for the PBKDF2 key derivation function. + */ + c: number; /** - * Pseudorandom function (PRF) used for key derivation. - */ -prf: string; + * Pseudorandom function (PRF) used for key derivation. + */ + prf: string; /** - * A random sequence of bytes used as an additional input for the key derivation function. - */ -salt: string; + * A random sequence of bytes used as an additional input for the key derivation function. + */ + salt: string; } /** @@ -59,51 +59,51 @@ salt: string; */ export interface KeyStoreJson { /** - * Ethereum address associated with the keystore. - */ -address?: string; + * Ethereum address associated with the keystore. + */ + address?: string; /** - * Cryptographic configurations and encrypted data. - */ -crypto: { + * Cryptographic configurations and encrypted data. + */ + crypto: { /** - * The encryption algorithm used to secure the private key. - */ -cipher: string; + * The encryption algorithm used to secure the private key. + */ + cipher: string; /** - * The encrypted private key in hexadecimal format. - */ -ciphertext: string; + * The encrypted private key in hexadecimal format. + */ + ciphertext: string; /** - * Parameters required for cipher initialization. - */ -cipherparams: { + * Parameters required for cipher initialization. + */ + cipherparams: { /** - * Initialization vector for the cipher algorithm. - */ -iv: string; + * Initialization vector for the cipher algorithm. + */ + iv: string; }; /** - * Key derivation function used for encryption. - */ -kdf: string; + * Key derivation function used for encryption. + */ + kdf: string; /** - * Key derivation function parameters for password-based key generation. - */ -kdfparams: ScryptKdfParams | PbKdf2Params; + * Key derivation function parameters for password-based key generation. + */ + kdfparams: ScryptKdfParams | PbKdf2Params; /** - * Message authentication code generated from encrypted data. - */ -mac: string; + * Message authentication code generated from encrypted data. + */ + mac: string; }; /** - * Unique identifier for the keystore object. - */ -id: string; + * Unique identifier for the keystore object. + */ + id: string; /** - * The version of the key store format. - */ -version: number; + * The version of the key store format. + */ + version: number; } /** @@ -165,45 +165,45 @@ export async function decryptFromKeyStoreJson(v3Keystore: KeyStoreJson, password */ export interface KeyStoreEncryptOptions { /** - * Cipher algorithm used for encryption. - */ -cipher?: string; + * Cipher algorithm used for encryption. + */ + cipher?: string; /** - * A random value used to ensure unique derived encryption keys. - */ -salt?: Buffer; + * A random value used to ensure unique derived encryption keys. + */ + salt?: Buffer; /** - * Initialization Vector for the AES cipher. - */ -iv?: Buffer; + * Initialization Vector for the AES cipher. + */ + iv?: Buffer; /** - * Key derivation function used for encryption/decryption. - */ -kdf?: 'scrypt' | 'pbkdf2'; + * Key derivation function used for encryption/decryption. + */ + kdf?: 'scrypt' | 'pbkdf2'; /** - * Unique identifier for the key store. - */ -id?: string; + * Unique identifier for the key store. + */ + id?: string; /** - * The iteration count for the PBKDF2 key derivation function. - */ -c?: number; + * The iteration count for the PBKDF2 key derivation function. + */ + c?: number; /** - * Length of the derived key in bytes. - */ -dklen?: number; + * Length of the derived key in bytes. + */ + dklen?: number; /** - * The cost factor determining the CPU/memory complexity of the scrypt key derivation function. - */ -n?: number; + * The cost factor determining the CPU/memory complexity of the scrypt key derivation function. + */ + n?: number; /** - * The scrypt memory cost factor. - */ -r?: number; + * The scrypt memory cost factor. + */ + r?: number; /** - * The parallelization factor for the scrypt key derivation function. - */ -p?: number; + * The parallelization factor for the scrypt key derivation function. + */ + p?: number; } /** diff --git a/yarn-project/ethereum.js/src/log/console.ts b/yarn-project/ethereum.js/src/log/console.ts index 0f758af3a87..6315a10e0e7 100644 --- a/yarn-project/ethereum.js/src/log/console.ts +++ b/yarn-project/ethereum.js/src/log/console.ts @@ -1,17 +1,13 @@ - export type Logger = (...args: any[]) => void; - class ConsoleLogger { constructor(private prefix: string, private logger: (...args: any[]) => void = console.log) {} - -public log(...args: any[]) { + public log(...args: any[]) { this.logger(`${this.prefix}:`, ...args); } } - export function createLogger(prefix: string): Logger { if (prefix) { const logger = new ConsoleLogger(prefix, console.log); diff --git a/yarn-project/ethereum.js/src/log/debug.ts b/yarn-project/ethereum.js/src/log/debug.ts index f0dc7fd0ead..812554cb762 100644 --- a/yarn-project/ethereum.js/src/log/debug.ts +++ b/yarn-project/ethereum.js/src/log/debug.ts @@ -3,7 +3,6 @@ import debug from 'debug'; let preLogHook: ((...args: any[]) => void) | undefined; let postLogHook: ((...args: any[]) => void) | undefined; - function theFunctionThroughWhichAllLogsPass(logger: any, ...args: any[]) { if (!debug.enabled(logger.namespace)) { return; @@ -17,28 +16,23 @@ function theFunctionThroughWhichAllLogsPass(logger: any, ...args: any[]) { } } - export function createDebugLogger(name: string): any { const logger = debug(name); return (...args: any[]) => theFunctionThroughWhichAllLogsPass(logger, ...args); } - export function setPreDebugLogHook(fn: (...args: any[]) => void) { preLogHook = fn; } - export function setPostDebugLogHook(fn: (...args: any[]) => void) { postLogHook = fn; } - export function enableLogs(str: string) { debug.enable(str); } - export function isLogEnabled(str: string) { return debug.enabled(str); } diff --git a/yarn-project/ethereum.js/src/provider/ethereum_provider.ts b/yarn-project/ethereum.js/src/provider/ethereum_provider.ts index eb6264e15d0..b49a2cb081a 100644 --- a/yarn-project/ethereum.js/src/provider/ethereum_provider.ts +++ b/yarn-project/ethereum.js/src/provider/ethereum_provider.ts @@ -12,13 +12,13 @@ export enum ProviderError { */ export interface ProviderMessage { /** - * The type of provider notification event. - */ -readonly type: string; + * The type of provider notification event. + */ + readonly type: string; /** - * Arbitrary data associated with the provider message. - */ -readonly data: unknown; + * Arbitrary data associated with the provider message. + */ + readonly data: unknown; } /** @@ -27,13 +27,13 @@ readonly data: unknown; */ export interface RequestArguments { /** - * The JSON-RPC method to be called. - */ -readonly method: string; + * The JSON-RPC method to be called. + */ + readonly method: string; /** - * An optional array of method-specific parameters. - */ -readonly params?: any[]; + * An optional array of method-specific parameters. + */ + readonly params?: any[]; } /** @@ -43,17 +43,17 @@ readonly params?: any[]; */ export interface ProviderRpcError extends Error { /** - * Represents a provider-specific message, typically used for communicating events or updates. - */ -message: string; + * Represents a provider-specific message, typically used for communicating events or updates. + */ + message: string; /** - * The error code representing the type of provider error. - */ -code: ProviderError | number; + * The error code representing the type of provider error. + */ + code: ProviderError | number; /** - * An arbitrary data payload related to the corresponding provider event or error. - */ -data?: unknown; + * An arbitrary data payload related to the corresponding provider event or error. + */ + data?: unknown; } /** @@ -62,9 +62,9 @@ data?: unknown; */ export interface ProviderConnectInfo { /** - * The unique identifier for the connected blockchain network. - */ -readonly chainId: string; + * The unique identifier for the connected blockchain network. + */ + readonly chainId: string; } /** diff --git a/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts b/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts index b1f025019c5..261e878e5c7 100644 --- a/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts +++ b/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts @@ -16,16 +16,16 @@ export class JsonRpcProvider implements EthereumProvider { constructor(private host: string, private netMustSucceed = true) {} /** - * Sends a JSON-RPC request to the Ethereum provider with the given method and parameters. - * The 'method' should be a valid Ethereum JSON-RPC method, and 'params' should be an array of inputs required for that method. - * Returns a promise which resolves to the result of the request, or rejects with an error if the request fails. - * - * @param {RequestArguments} requestArguments - An object containing 'method' and 'params' properties. - * @param {string} requestArguments.method - The Ethereum JSON-RPC method to call. - * @param {Array} requestArguments.params - The parameters required for the called method. - * @returns {Promise} A promise resolving to the result of the request, or rejecting with an error if the request fails. - */ -public async request({ method, params }: RequestArguments): Promise { + * Sends a JSON-RPC request to the Ethereum provider with the given method and parameters. + * The 'method' should be a valid Ethereum JSON-RPC method, and 'params' should be an array of inputs required for that method. + * Returns a promise which resolves to the result of the request, or rejects with an error if the request fails. + * + * @param {RequestArguments} requestArguments - An object containing 'method' and 'params' properties. + * @param {string} requestArguments.method - The Ethereum JSON-RPC method to call. + * @param {Array} requestArguments.params - The parameters required for the called method. + * @returns {Promise} A promise resolving to the result of the request, or rejecting with an error if the request fails. + */ + public async request({ method, params }: RequestArguments): Promise { const body = { jsonrpc: '2.0', id: this.id++, @@ -42,37 +42,37 @@ public async request({ method, params }: RequestArguments): Promise { } /** - * Registers an event listener for the specified event on the JsonRpcProvider instance. - * This method is not supported in the current implementation and will throw an error when called. - * - * @throws {Error} An error indicating that events are not supported by the JsonRpcProvider. - * @returns {this} The current JsonRpcProvider instance. - */ -on(): this { + * Registers an event listener for the specified event on the JsonRpcProvider instance. + * This method is not supported in the current implementation and will throw an error when called. + * + * @throws {Error} An error indicating that events are not supported by the JsonRpcProvider. + * @returns {this} The current JsonRpcProvider instance. + */ + on(): this { throw new Error('Events not supported.'); } /** - * Remove an event listener from the Ethereum provider. This method is not supported by JsonRpcProvider - * and will throw an error when called. To use event handling, consider using a different provider implementation. - * - * @throws {Error} Throws an error indicating that events are not supported by this provider. - * @returns {this} Returns the current instance of the class for chaining purposes. - */ -removeListener(): this { + * Remove an event listener from the Ethereum provider. This method is not supported by JsonRpcProvider + * and will throw an error when called. To use event handling, consider using a different provider implementation. + * + * @throws {Error} Throws an error indicating that events are not supported by this provider. + * @returns {this} Returns the current instance of the class for chaining purposes. + */ + removeListener(): this { throw new Error('Events not supported.'); } /** - * Send a JSON-RPC request to the Ethereum node and return the parsed response. - * The 'body' parameter contains the JSON-RPC request payload, including method, id, and params. - * If 'netMustSucceed' is true, the function will be retried until the request succeeds. - * Throws an error if the response status is not ok or if the response body cannot be parsed as JSON. - * - * @param body - The JSON-RPC request payload containing the method, id, and params. - * @returns A Promise resolving to the parsed JSON-RPC response object. - */ -private async fetch(body: any) { + * Send a JSON-RPC request to the Ethereum node and return the parsed response. + * The 'body' parameter contains the JSON-RPC request payload, including method, id, and params. + * If 'netMustSucceed' is true, the function will be retried until the request succeeds. + * Throws an error if the response status is not ok or if the response body cannot be parsed as JSON. + * + * @param body - The JSON-RPC request payload containing the method, id, and params. + * @returns A Promise resolving to the parsed JSON-RPC response object. + */ + private async fetch(body: any) { const fn = async () => { const resp = await fetch(this.host, { method: 'POST', diff --git a/yarn-project/ethereum.js/src/provider/wallet_provider.ts b/yarn-project/ethereum.js/src/provider/wallet_provider.ts index 5f20d02d96a..430e643df29 100644 --- a/yarn-project/ethereum.js/src/provider/wallet_provider.ts +++ b/yarn-project/ethereum.js/src/provider/wallet_provider.ts @@ -21,129 +21,129 @@ export class WalletProvider implements EthereumProvider { constructor(private provider: EthereumProvider, private wallet = new EthWallet()) {} /** - * Create a WalletProvider instance using the given Ethereum host and an optional EthWallet instance. - * This function initializes a JsonRpcProvider with the provided Ethereum host and then - * creates a WalletProvider using the initialized JsonRpcProvider and the provided wallet. - * If no wallet is provided, a new EthWallet instance will be created. - * - * @param ethereumHost - The Ethereum host URL used to initialize the JsonRpcProvider. - * @param wallet - (Optional) An EthWallet instance to be used as the local wallet. - * @returns A WalletProvider instance with the initialized JsonRpcProvider and the given wallet. - */ -public static fromHost(ethereumHost: string, wallet = new EthWallet()) { + * Create a WalletProvider instance using the given Ethereum host and an optional EthWallet instance. + * This function initializes a JsonRpcProvider with the provided Ethereum host and then + * creates a WalletProvider using the initialized JsonRpcProvider and the provided wallet. + * If no wallet is provided, a new EthWallet instance will be created. + * + * @param ethereumHost - The Ethereum host URL used to initialize the JsonRpcProvider. + * @param wallet - (Optional) An EthWallet instance to be used as the local wallet. + * @returns A WalletProvider instance with the initialized JsonRpcProvider and the given wallet. + */ + public static fromHost(ethereumHost: string, wallet = new EthWallet()) { const provider = new JsonRpcProvider(ethereumHost); return new WalletProvider(provider, wallet); } /** - * Adds an account to the wallet using a private key. - * The input 'privateKey' should be a Buffer containing the private key bytes of the account. - * Returns the corresponding EthAddress of the added account. - * - * @param privateKey - The Buffer containing the private key bytes of the account. - * @returns An EthAddress instance. - */ -public addAccount(privateKey: Buffer) { + * Adds an account to the wallet using a private key. + * The input 'privateKey' should be a Buffer containing the private key bytes of the account. + * Returns the corresponding EthAddress of the added account. + * + * @param privateKey - The Buffer containing the private key bytes of the account. + * @returns An EthAddress instance. + */ + public addAccount(privateKey: Buffer) { return this.wallet.add(privateKey).address; } /** - * Add multiple accounts to the wallet using a mnemonic phrase and the specified number of accounts. - * The accounts will be generated based on the provided BIP32 account index and indexed from 0 to (num-1). - * This function is useful for importing a set of accounts that were derived from a single mnemonic. - * - * @param mnemonic - The mnemonic phrase used to generate the accounts. - * @param num - The number of accounts to add to the wallet. - * @param bip32Account - The BIP32 account index to derive the accounts from, default is 0. - */ -public addAccountsFromMnemonic(mnemonic: string, num: number, bip32Account = 0) { + * Add multiple accounts to the wallet using a mnemonic phrase and the specified number of accounts. + * The accounts will be generated based on the provided BIP32 account index and indexed from 0 to (num-1). + * This function is useful for importing a set of accounts that were derived from a single mnemonic. + * + * @param mnemonic - The mnemonic phrase used to generate the accounts. + * @param num - The number of accounts to add to the wallet. + * @param bip32Account - The BIP32 account index to derive the accounts from, default is 0. + */ + public addAccountsFromMnemonic(mnemonic: string, num: number, bip32Account = 0) { for (let i = 0; i < num; ++i) { this.addAccountFromMnemonicAndPath(mnemonic, `m/44'/60'/${bip32Account}'/0/${i}`); } } /** - * Adds an account to the wallet using a mnemonic and a specified BIP32 derivation path. - * The generated account is derived from the given mnemonic using the provided path, - * following the BIP32 hierarchical deterministic key generation standard. - * Returns the Ethereum address of the added account. - * - * @param mnemonic - The seed phrase used to generate the private key for the account. - * @param path - The BIP32 derivation path used to derive the account from the mnemonic. - * @returns The Ethereum address of the added account. - */ -public addAccountFromMnemonicAndPath(mnemonic: string, path: string) { + * Adds an account to the wallet using a mnemonic and a specified BIP32 derivation path. + * The generated account is derived from the given mnemonic using the provided path, + * following the BIP32 hierarchical deterministic key generation standard. + * Returns the Ethereum address of the added account. + * + * @param mnemonic - The seed phrase used to generate the private key for the account. + * @param path - The BIP32 derivation path used to derive the account from the mnemonic. + * @returns The Ethereum address of the added account. + */ + public addAccountFromMnemonicAndPath(mnemonic: string, path: string) { return this.wallet.add(EthAccount.fromMnemonicAndPath(mnemonic, path)).address; } /** - * Adds an account to the wallet provider by loading a keystore file and decrypting the private key using the provided password. - * The keystore file should follow the JSON format defined in Ethereum Improvement Proposal 55 (EIP-55). - * Throws an error if the input file is invalid or decryption fails due to incorrect password. - * - * @param file - The path to the keystore file containing the encrypted private key. - * @param password - The password used for decryption of the keystore file (default: ''). - * @returns An EthAddress instance representing the address of the added account. - */ -public async addAccountFromKeystore(file: string, password = '') { + * Adds an account to the wallet provider by loading a keystore file and decrypting the private key using the provided password. + * The keystore file should follow the JSON format defined in Ethereum Improvement Proposal 55 (EIP-55). + * Throws an error if the input file is invalid or decryption fails due to incorrect password. + * + * @param file - The path to the keystore file containing the encrypted private key. + * @param password - The password used for decryption of the keystore file (default: ''). + * @returns An EthAddress instance representing the address of the added account. + */ + public async addAccountFromKeystore(file: string, password = '') { const json = JSON.parse(await readFile(file, { encoding: 'ascii' })); return this.wallet.add(await EthAccount.fromKeyStoreJson(json, password)).address; } /** - * Retrieve all available accounts in the wallet. - * This function returns an array of EthAddress instances corresponding to each account in the wallet. - * If no accounts have been added, it returns an empty array. - * - * @returns An array of EthAddress instances representing the accounts in the wallet. - */ -public getAccounts() { + * Retrieve all available accounts in the wallet. + * This function returns an array of EthAddress instances corresponding to each account in the wallet. + * If no accounts have been added, it returns an empty array. + * + * @returns An array of EthAddress instances representing the accounts in the wallet. + */ + public getAccounts() { return this.wallet.getAccountAddresses(); } /** - * Retrieve the EthAddress instance of an account at a specific index within the wallet. - * Returns `undefined` if the provided index is out of range or does not correspond to an existing account. - * - * @param account - The index (integer) of the account to be fetched from the wallet. - * @returns The EthAddress instance corresponding to the account, or `undefined` if not found. - */ -public getAccount(account: number) { + * Retrieve the EthAddress instance of an account at a specific index within the wallet. + * Returns `undefined` if the provided index is out of range or does not correspond to an existing account. + * + * @param account - The index (integer) of the account to be fetched from the wallet. + * @returns The EthAddress instance corresponding to the account, or `undefined` if not found. + */ + public getAccount(account: number) { return this.wallet.getAccount(account)?.address; } /** - * Retrieve the private key associated with the specified account index. - * Returns the private key as a Buffer if the account exists in the wallet, otherwise returns undefined. - * - * @param account - The index of the account whose private key is to be retrieved. - * @returns The private key as a Buffer, or undefined if the account does not exist. - */ -public getPrivateKey(account: number) { + * Retrieve the private key associated with the specified account index. + * Returns the private key as a Buffer if the account exists in the wallet, otherwise returns undefined. + * + * @param account - The index of the account whose private key is to be retrieved. + * @returns The private key as a Buffer, or undefined if the account does not exist. + */ + public getPrivateKey(account: number) { return this.wallet.getAccount(account)?.privateKey; } /** - * Retrieves the private key associated with the given Ethereum address. - * Returns the private key as a Buffer if found within the wallet, or undefined otherwise. - * - * @param account - The EthAddress instance representing the Ethereum address to lookup. - * @returns The private key as a Buffer or undefined if not found in the wallet. - */ -public getPrivateKeyForAddress(account: EthAddress) { + * Retrieves the private key associated with the given Ethereum address. + * Returns the private key as a Buffer if found within the wallet, or undefined otherwise. + * + * @param account - The EthAddress instance representing the Ethereum address to lookup. + * @returns The private key as a Buffer or undefined if not found in the wallet. + */ + public getPrivateKeyForAddress(account: EthAddress) { return this.wallet.getAccount(account)?.privateKey; } /** - * Handles the processing of various Ethereum JSON-RPC requests, delegating them to the appropriate internal methods. - * If a local account is available for signing transactions or messages, it will be used, otherwise the request - * is forwarded to the underlying provider for further processing. This allows adding and managing local accounts - * while still interacting with external providers such as remote nodes or browser-based wallets like MetaMask. - * - * @param args - The RequestArguments object containing the method to be called and any necessary parameters. - * @returns A Promise resolving to the result of the requested operation or an error if the operation fails. - */ -public async request(args: RequestArguments): Promise { + * Handles the processing of various Ethereum JSON-RPC requests, delegating them to the appropriate internal methods. + * If a local account is available for signing transactions or messages, it will be used, otherwise the request + * is forwarded to the underlying provider for further processing. This allows adding and managing local accounts + * while still interacting with external providers such as remote nodes or browser-based wallets like MetaMask. + * + * @param args - The RequestArguments object containing the method to be called and any necessary parameters. + * @returns A Promise resolving to the result of the requested operation or an error if the operation fails. + */ + public async request(args: RequestArguments): Promise { switch (args.method) { case 'eth_accounts': return this.wallet.length ? this.getAccounts().map(a => a.toString()) : await this.provider.request(args); @@ -191,15 +191,15 @@ public async request(args: RequestArguments): Promise { } /** - * Sign the provided typed data using an account's private key. - * This method is used for EIP-712 compliant signing of structured data. - * The signed digest can be used to verify the signer's identity and authenticity of the data. - * - * @param args - RequestArguments object containing the method name and input parameters. - * @returns A Promise that resolves to a string representing the signature of the typed data. - * @throws An error if the specified account is not found in the wallet or if the request to the provider fails. - */ -private async signTypedData(args: RequestArguments) { + * Sign the provided typed data using an account's private key. + * This method is used for EIP-712 compliant signing of structured data. + * The signed digest can be used to verify the signer's identity and authenticity of the data. + * + * @param args - RequestArguments object containing the method name and input parameters. + * @returns A Promise that resolves to a string representing the signature of the typed data. + * @throws An error if the specified account is not found in the wallet or if the request to the provider fails. + */ + private async signTypedData(args: RequestArguments) { const [from, data] = args.params!; const account = this.wallet.getAccount(EthAddress.fromString(from)); if (account) { @@ -232,14 +232,14 @@ private async signTypedData(args: RequestArguments) { } /** - * Sign a transaction using the local account associated with the 'from' address in the given transaction object. - * If the 'from' address is not managed by the WalletProvider, the transaction will be forwarded to the underlying provider. - * The input transaction should be in Ethereum JSON-RPC format. - * - * @param args - A RequestArguments object containing the transaction details. - * @returns A Promise that resolves to the signed transaction as a hex-encoded string. - */ -private async ethSignTransaction(args: RequestArguments) { + * Sign a transaction using the local account associated with the 'from' address in the given transaction object. + * If the 'from' address is not managed by the WalletProvider, the transaction will be forwarded to the underlying provider. + * The input transaction should be in Ethereum JSON-RPC format. + * + * @param args - A RequestArguments object containing the transaction details. + * @returns A Promise that resolves to the signed transaction as a hex-encoded string. + */ + private async ethSignTransaction(args: RequestArguments) { const tx = args.params![0]; const account = this.wallet.getAccount(EthAddress.fromString(tx.from)); if (account) { @@ -250,14 +250,14 @@ private async ethSignTransaction(args: RequestArguments) { } /** - * Process and send a given Ethereum transaction using the EthAccount instance associated with the 'from' address. - * If the account is found in the local wallet, it will sign the transaction locally and send the raw transaction - * to the Ethereum provider. If the account is not found in the local wallet, it will forward the request to the provider. - * - * @param args - The RequestArguments object containing the Ethereum transaction details. - * @returns A promise that resolves to the transaction hash of the submitted transaction. - */ -private async ethSendTransaction(args: RequestArguments) { + * Process and send a given Ethereum transaction using the EthAccount instance associated with the 'from' address. + * If the account is found in the local wallet, it will sign the transaction locally and send the raw transaction + * to the Ethereum provider. If the account is not found in the local wallet, it will forward the request to the provider. + * + * @param args - The RequestArguments object containing the Ethereum transaction details. + * @returns A promise that resolves to the transaction hash of the submitted transaction. + */ + private async ethSendTransaction(args: RequestArguments) { const tx = args.params![0]; const account = this.wallet.getAccount(EthAddress.fromString(tx.from)); if (account) { @@ -271,126 +271,126 @@ private async ethSendTransaction(args: RequestArguments) { } /** - * Attaches a callback function to the specified event type on the Ethereum provider. - * The listener will be invoked whenever the event occurs for the given notification. - * Common events include 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. - * - * @param notification - The event type to listen for. - * @param listener - The callback function to be invoked when the event occurs. - * @returns The WalletProvider instance, allowing for method chaining. - */ -on(notification: 'connect', listener: (connectInfo: ProviderConnectInfo) => void): this; + * Attaches a callback function to the specified event type on the Ethereum provider. + * The listener will be invoked whenever the event occurs for the given notification. + * Common events include 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. + * + * @param notification - The event type to listen for. + * @param listener - The callback function to be invoked when the event occurs. + * @returns The WalletProvider instance, allowing for method chaining. + */ + on(notification: 'connect', listener: (connectInfo: ProviderConnectInfo) => void): this; /** - * Registers an event listener for the specified notification type. - * The listener will be invoked with the relevant data when the provider emits that notification. - * - * @param notification - The notification type to subscribe to, such as 'connect', 'disconnect', 'chainChanged', 'accountsChanged', or 'message'. - * @param listener - The callback function to be invoked when the provider emits the specified notification. - * @returns This WalletProvider instance, allowing for chained method calls. - */ -on(notification: 'disconnect', listener: (error: ProviderRpcError) => void): this; + * Registers an event listener for the specified notification type. + * The listener will be invoked with the relevant data when the provider emits that notification. + * + * @param notification - The notification type to subscribe to, such as 'connect', 'disconnect', 'chainChanged', 'accountsChanged', or 'message'. + * @param listener - The callback function to be invoked when the provider emits the specified notification. + * @returns This WalletProvider instance, allowing for chained method calls. + */ + on(notification: 'disconnect', listener: (error: ProviderRpcError) => void): this; /** - * Registers an event listener for the specified notification type. - * The listener function will be invoked when the corresponding event is emitted by the provider. - * This allows for handling of various events such as connection changes, account changes, etc. - * - * @param notification - The type of event to listen for ('connect', 'disconnect', 'chainChanged', 'accountsChanged', or 'message'). - * @param listener - The callback function to be invoked when the specified event occurs. - * @returns The WalletProvider instance for chaining purposes. - */ -on(notification: 'chainChanged', listener: (chainId: string) => void): this; + * Registers an event listener for the specified notification type. + * The listener function will be invoked when the corresponding event is emitted by the provider. + * This allows for handling of various events such as connection changes, account changes, etc. + * + * @param notification - The type of event to listen for ('connect', 'disconnect', 'chainChanged', 'accountsChanged', or 'message'). + * @param listener - The callback function to be invoked when the specified event occurs. + * @returns The WalletProvider instance for chaining purposes. + */ + on(notification: 'chainChanged', listener: (chainId: string) => void): this; /** - * Add an event listener for the specified notification type. - * The listener function will be called whenever an event of the specified type is emitted from the provider. - * Supported notification types are: 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. - * - * @param notification - The type of event to listen for. - * @param listener - The function to be called when the event occurs. - * @returns The WalletProvider instance, allowing chained calls. - */ -on(notification: 'accountsChanged', listener: (accounts: string[]) => void): this; + * Add an event listener for the specified notification type. + * The listener function will be called whenever an event of the specified type is emitted from the provider. + * Supported notification types are: 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. + * + * @param notification - The type of event to listen for. + * @param listener - The function to be called when the event occurs. + * @returns The WalletProvider instance, allowing chained calls. + */ + on(notification: 'accountsChanged', listener: (accounts: string[]) => void): this; /** - * Add an event listener for the specified notification on this WalletProvider instance. - * The listener will be called with relevant information when the event occurs. - * Supported notifications include 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. - * - * @param notification - The type of event to listen for. - * @param listener - The function that will be called when the event occurs, with arguments based on the event type. - * @returns This WalletProvider instance, allowing for method chaining. - */ -on(notification: 'message', listener: (message: ProviderMessage) => void): this; + * Add an event listener for the specified notification on this WalletProvider instance. + * The listener will be called with relevant information when the event occurs. + * Supported notifications include 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. + * + * @param notification - The type of event to listen for. + * @param listener - The function that will be called when the event occurs, with arguments based on the event type. + * @returns This WalletProvider instance, allowing for method chaining. + */ + on(notification: 'message', listener: (message: ProviderMessage) => void): this; /** - * Registers a listener function to be called when the specified event occurs. - * The available events are 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. - * The listener function should take the appropriate argument based on the event type. - * - * @param notification - The event type to listen for. One of: 'connect', 'disconnect', 'chainChanged', 'accountsChanged', or 'message'. - * @param listener - The function to be called when the specified event occurs, taking the appropriate argument based on the event type. - * @returns The WalletProvider instance, allowing for method chaining. - */ -on(notification: any, listener: any) { + * Registers a listener function to be called when the specified event occurs. + * The available events are 'connect', 'disconnect', 'chainChanged', 'accountsChanged', and 'message'. + * The listener function should take the appropriate argument based on the event type. + * + * @param notification - The event type to listen for. One of: 'connect', 'disconnect', 'chainChanged', 'accountsChanged', or 'message'. + * @param listener - The function to be called when the specified event occurs, taking the appropriate argument based on the event type. + * @returns The WalletProvider instance, allowing for method chaining. + */ + on(notification: any, listener: any) { return this.provider.on(notification, listener); } /** - * Removes an event listener for the specified notification type. - * The listener should be a function previously added using the `on` method. - * If the listener is not found, this method does nothing. - * - * @param notification - The notification type to remove the listener from. - * @param listener - The event listener function to remove. - * @returns The WalletProvider instance. - */ -removeListener(notification: 'connect', listener: (connectInfo: ProviderConnectInfo) => void): this; + * Removes an event listener for the specified notification type. + * The listener should be a function previously added using the `on` method. + * If the listener is not found, this method does nothing. + * + * @param notification - The notification type to remove the listener from. + * @param listener - The event listener function to remove. + * @returns The WalletProvider instance. + */ + removeListener(notification: 'connect', listener: (connectInfo: ProviderConnectInfo) => void): this; /** - * Removes a specified listener function from the given event notification. - * The listener function will no longer be triggered when the specified event occurs. - * - * @param notification - The event notification type for which the listener needs to be removed. - * @param listener - The listener function that was previously added and needs to be removed. - * @returns The modified WalletProvider instance. - */ -removeListener(notification: 'disconnect', listener: (error: ProviderRpcError) => void): this; + * Removes a specified listener function from the given event notification. + * The listener function will no longer be triggered when the specified event occurs. + * + * @param notification - The event notification type for which the listener needs to be removed. + * @param listener - The listener function that was previously added and needs to be removed. + * @returns The modified WalletProvider instance. + */ + removeListener(notification: 'disconnect', listener: (error: ProviderRpcError) => void): this; /** - * Removes a previously added listener function for the specified event notification. - * The function will no longer be invoked when the specified event is emitted. - * - * @param notification - The event notification from which to remove the listener. - * @param listener - The listener function that was previously added and now needs to be removed. - * @returns The WalletProvider instance for chaining. - */ -removeListener(notification: 'chainChanged', listener: (chainId: string) => void): this; + * Removes a previously added listener function for the specified event notification. + * The function will no longer be invoked when the specified event is emitted. + * + * @param notification - The event notification from which to remove the listener. + * @param listener - The listener function that was previously added and now needs to be removed. + * @returns The WalletProvider instance for chaining. + */ + removeListener(notification: 'chainChanged', listener: (chainId: string) => void): this; /** - * Removes a previously added listener function for the specified notification event. - * The listener function will no longer be called when the corresponding event occurs. - * This helps to prevent unwanted side-effects, memory leaks and improve performance - * by unregistering listeners that are no longer needed. - * - * @param notification - The event name for which the listener should be removed. - * @param listener - The callback function that was previously added as a listener for the specified event. - * @returns The WalletProvider instance, allowing for method chaining. - */ -removeListener(notification: 'accountsChanged', listener: (accounts: string[]) => void): this; + * Removes a previously added listener function for the specified notification event. + * The listener function will no longer be called when the corresponding event occurs. + * This helps to prevent unwanted side-effects, memory leaks and improve performance + * by unregistering listeners that are no longer needed. + * + * @param notification - The event name for which the listener should be removed. + * @param listener - The callback function that was previously added as a listener for the specified event. + * @returns The WalletProvider instance, allowing for method chaining. + */ + removeListener(notification: 'accountsChanged', listener: (accounts: string[]) => void): this; /** - * Removes a previously added event listener for the specified notification type. - * The listener function should be the same as the one used when calling 'on' to add the listener. - * If the listener is not found, this method will have no effect. - * - * @param notification - The notification type for which to remove the listener. - * @param listener - The listener function that was previously added. - * @returns The WalletProvider instance with the listener removed. - */ -removeListener(notification: 'message', listener: (message: ProviderMessage) => void): this; + * Removes a previously added event listener for the specified notification type. + * The listener function should be the same as the one used when calling 'on' to add the listener. + * If the listener is not found, this method will have no effect. + * + * @param notification - The notification type for which to remove the listener. + * @param listener - The listener function that was previously added. + * @returns The WalletProvider instance with the listener removed. + */ + removeListener(notification: 'message', listener: (message: ProviderMessage) => void): this; /** - * Removes a specified listener function from the given event notification. - * Listeners are functions that have been previously added via the `on` method. - * If the listener is successfully removed, it will no longer be called when the corresponding event is triggered. - * - * @param notification - The event notification type from which the listener should be removed. - * @param listener - The listener function to be removed from the specified event notification. - * @returns The WalletProvider instance with the updated set of listeners. - */ -removeListener(notification: any, listener: any) { + * Removes a specified listener function from the given event notification. + * Listeners are functions that have been previously added via the `on` method. + * If the listener is successfully removed, it will no longer be called when the corresponding event is triggered. + * + * @param notification - The event notification type from which the listener should be removed. + * @param listener - The listener function to be removed from the specified event notification. + * @returns The WalletProvider instance with the updated set of listeners. + */ + removeListener(notification: any, listener: any) { return this.provider.removeListener(notification, listener); } } diff --git a/yarn-project/ethereum.js/src/provider/web3_adapter.ts b/yarn-project/ethereum.js/src/provider/web3_adapter.ts index 2e7757b4b96..76ef933ca01 100644 --- a/yarn-project/ethereum.js/src/provider/web3_adapter.ts +++ b/yarn-project/ethereum.js/src/provider/web3_adapter.ts @@ -10,15 +10,15 @@ export class Web3Adapter implements EthereumProvider { constructor(private provider: Web3Provider) {} /** - * Sends a JSON-RPC request to the legacy web3 provider and returns the result in a Promise. - * The function constructs a payload object using the method and params provided in the RequestArguments, - * and sends it to the provider for execution. It handles errors and responses accordingly, and - * resolves or rejects the Promise based on the response from the provider. - * - * @param args - A RequestArguments object containing the JSON-RPC method and parameters. - * @returns A Promise resolving with the result of the executed request or rejecting with an error. - */ -public request(args: RequestArguments): Promise { + * Sends a JSON-RPC request to the legacy web3 provider and returns the result in a Promise. + * The function constructs a payload object using the method and params provided in the RequestArguments, + * and sends it to the provider for execution. It handles errors and responses accordingly, and + * resolves or rejects the Promise based on the response from the provider. + * + * @param args - A RequestArguments object containing the JSON-RPC method and parameters. + * @returns A Promise resolving with the result of the executed request or rejecting with an error. + */ + public request(args: RequestArguments): Promise { return new Promise((resolve, reject) => { const payload = { jsonrpc: '2.0', @@ -40,24 +40,24 @@ public request(args: RequestArguments): Promise { } /** - * Adds an event listener for the specified event on the Web3Adapter instance. - * Please note that this method is not implemented and will throw an error when called, as events are not supported. - * - * @throws {Error} Will throw an error if the method is called, because events are not supported in this implementation. - * @returns {this} Returns the Web3Adapter instance for chaining purposes (if events were supported). - */ -on(): this { + * Adds an event listener for the specified event on the Web3Adapter instance. + * Please note that this method is not implemented and will throw an error when called, as events are not supported. + * + * @throws {Error} Will throw an error if the method is called, because events are not supported in this implementation. + * @returns {this} Returns the Web3Adapter instance for chaining purposes (if events were supported). + */ + on(): this { throw new Error('Events not supported.'); } /** - * Remove an event listener from the Ethereum provider. - * This method is not supported for the Web3Adapter class, and calling it will result in an error being thrown. - * - * @throws {Error} - An error indicating that event removal is not supported. - * @returns {this} - The current instance of the Web3Adapter class. - */ -removeListener(): this { + * Remove an event listener from the Ethereum provider. + * This method is not supported for the Web3Adapter class, and calling it will result in an error being thrown. + * + * @throws {Error} - An error indicating that event removal is not supported. + * @returns {this} - The current instance of the Web3Adapter class. + */ + removeListener(): this { throw new Error('Events not supported.'); } } diff --git a/yarn-project/ethereum.js/src/provider/web3_provider.ts b/yarn-project/ethereum.js/src/provider/web3_provider.ts index 4effef7da6f..9565cfab9fa 100644 --- a/yarn-project/ethereum.js/src/provider/web3_provider.ts +++ b/yarn-project/ethereum.js/src/provider/web3_provider.ts @@ -4,21 +4,21 @@ */ interface JsonRpcRequest { /** - * A JSON-RPC version identifier. - */ -jsonrpc: string; + * A JSON-RPC version identifier. + */ + jsonrpc: string; /** - * The name of the JSON-RPC method to call. - */ -method: string; + * The name of the JSON-RPC method to call. + */ + method: string; /** - * An array of method-specific parameters. - */ -params: any[]; + * An array of method-specific parameters. + */ + params: any[]; /** - * Unique identifier for the JSON-RPC request. - */ -id: number; + * Unique identifier for the JSON-RPC request. + */ + id: number; } /** @@ -28,33 +28,33 @@ id: number; */ interface JsonRpcResponse { /** - * JSON-RPC version used for communication. - */ -jsonrpc: string; + * JSON-RPC version used for communication. + */ + jsonrpc: string; /** - * A unique identifier for the JSON-RPC request. - */ -id: number; + * A unique identifier for the JSON-RPC request. + */ + id: number; /** - * The outcome of the invoked method. - */ -result?: any; + * The outcome of the invoked method. + */ + result?: any; /** - * Represents error details returned in JSON-RPC response. - */ -error?: { + * Represents error details returned in JSON-RPC response. + */ + error?: { /** - * The numerical error code representing the type of error occurred. - */ -code: number; + * The numerical error code representing the type of error occurred. + */ + code: number; /** - * The name of the method to be called on the remote server. - */ -message: string; + * The name of the method to be called on the remote server. + */ + message: string; /** - * Additional information related to the error. - */ -data?: any; + * Additional information related to the error. + */ + data?: any; }; } diff --git a/yarn-project/ethereum.js/src/retry/index.ts b/yarn-project/ethereum.js/src/retry/index.ts index c5d6e4cdf44..a293108ca6c 100644 --- a/yarn-project/ethereum.js/src/retry/index.ts +++ b/yarn-project/ethereum.js/src/retry/index.ts @@ -1,7 +1,6 @@ import { sleep } from '../sleep/index.js'; import { Timer } from '../timer/index.js'; - export function* backoffGenerator() { const v = [1, 1, 1, 2, 4, 8, 16, 32, 64]; let i = 0; @@ -10,7 +9,6 @@ export function* backoffGenerator() { } } - export async function retry(fn: () => Promise, name = 'Operation', backoff = backoffGenerator()) { while (true) { try { diff --git a/yarn-project/ethereum.js/src/serialize/deserializer.ts b/yarn-project/ethereum.js/src/serialize/deserializer.ts index 7f2901c0c7f..6c031b036aa 100644 --- a/yarn-project/ethereum.js/src/serialize/deserializer.ts +++ b/yarn-project/ethereum.js/src/serialize/deserializer.ts @@ -7,72 +7,62 @@ import { deserializeUInt32, } from './free_funcs.js'; - -export type DeserializeFn = (buf: Buffer, offset: number) => { - -elem: T; -adv: number }; - +export type DeserializeFn = ( + buf: Buffer, + offset: number, +) => { + elem: T; + adv: number; +}; export class Deserializer { constructor(private buf: Buffer, private offset = 0) {} - -public bool() { + public bool() { return this.exec(deserializeBool) ? true : false; } - -public uInt32() { + public uInt32() { return this.exec(deserializeUInt32); } - -public int32() { + public int32() { return this.exec(deserializeInt32); } - -public bigInt(width = 32) { + public bigInt(width = 32) { return this.exec((buf: Buffer, offset: number) => deserializeBigInt(buf, offset, width)); } - -public vector() { + public vector() { return this.exec(deserializeBufferFromVector); } - -public buffer(width: number) { + public buffer(width: number) { const buf = this.buf.slice(this.offset, this.offset + width); this.offset += width; return buf; } - -public string() { + public string() { return this.vector().toString(); } - -public date() { + public date() { return new Date(Number(this.bigInt(8))); } - -public deserializeArray(fn: DeserializeFn) { + public deserializeArray(fn: DeserializeFn) { return this.exec((buf: Buffer, offset: number) => deserializeArrayFromVector(fn, buf, offset)); } - -public exec(fn: DeserializeFn): T { + public exec(fn: DeserializeFn): T { const { elem, adv } = fn(this.buf, this.offset); this.offset += adv; return elem; } - -public getOffset() { + public getOffset() { return this.offset; } } diff --git a/yarn-project/ethereum.js/src/serialize/free_funcs.ts b/yarn-project/ethereum.js/src/serialize/free_funcs.ts index 40b9819c8fa..afda89748d5 100644 --- a/yarn-project/ethereum.js/src/serialize/free_funcs.ts +++ b/yarn-project/ethereum.js/src/serialize/free_funcs.ts @@ -173,13 +173,19 @@ export function serializeBufferArrayToVector(arr: Buffer[]) { * @returns An object containing the deserialized array of elements (elem) and the total bytes consumed in the process (adv). */ export function deserializeArrayFromVector( - deserialize: (buf: Buffer, offset: number) => { /** - * The deserialized element from the buffer. - */ -elem: T; /** - * The number of bytes advanced in the buffer during deserialization. - */ -adv: number }, + deserialize: ( + buf: Buffer, + offset: number, + ) => { + /** + * The deserialized element from the buffer. + */ + elem: T; + /** + * The number of bytes advanced in the buffer during deserialization. + */ + adv: number; + }, vector: Buffer, offset = 0, ) { diff --git a/yarn-project/ethereum.js/src/serialize/serializer.ts b/yarn-project/ethereum.js/src/serialize/serializer.ts index 16364868d8c..a1b947935b3 100644 --- a/yarn-project/ethereum.js/src/serialize/serializer.ts +++ b/yarn-project/ethereum.js/src/serialize/serializer.ts @@ -16,45 +16,45 @@ export class Serializer { constructor() {} /** - * Serializes a boolean value into a Buffer and appends it to the internal buffer array. - * The serialized byte can represent either true or false, using 1 for true and 0 for false. - * - * @param bool - The boolean value to be serialized. - */ -public bool(bool: boolean) { + * Serializes a boolean value into a Buffer and appends it to the internal buffer array. + * The serialized byte can represent either true or false, using 1 for true and 0 for false. + * + * @param bool - The boolean value to be serialized. + */ + public bool(bool: boolean) { this.buf.push(boolToByte(bool)); } /** - * Serialize an unsigned 32-bit integer into a big-endian byte Buffer and add it to the internal buffer list. - * The input 'num' should be within the range of 0 to 2^32-1, inclusive. - * Throws an error if the input value is out of range. - * - * @param num - The unsigned 32-bit integer to be serialized. - */ -public uInt32(num: number) { + * Serialize an unsigned 32-bit integer into a big-endian byte Buffer and add it to the internal buffer list. + * The input 'num' should be within the range of 0 to 2^32-1, inclusive. + * Throws an error if the input value is out of range. + * + * @param num - The unsigned 32-bit integer to be serialized. + */ + public uInt32(num: number) { this.buf.push(numToUInt32BE(num)); } /** - * Serializes the given signed 32-bit integer as a big-endian buffer and stores it in the internal buffer. - * The input 'num' should be within the range of [-2147483648, 2147483647], inclusive. - * Throws an error if the input value is out of range. - * - * @param num - The signed 32-bit integer to serialize. - */ -public int32(num: number) { + * Serializes the given signed 32-bit integer as a big-endian buffer and stores it in the internal buffer. + * The input 'num' should be within the range of [-2147483648, 2147483647], inclusive. + * Throws an error if the input value is out of range. + * + * @param num - The signed 32-bit integer to serialize. + */ + public int32(num: number) { this.buf.push(numToInt32BE(num)); } /** - * Serialize a bigint value into a Buffer and append it to the internal buffer array. - * The function takes care of handling large integer values that cannot be stored in - * standard JavaScript number type, allowing serialization of big integers without loss of precision. - * - * @param num - The bigint value to be serialized and added to the buffer. - */ -public bigInt(num: bigint) { + * Serialize a bigint value into a Buffer and append it to the internal buffer array. + * The function takes care of handling large integer values that cannot be stored in + * standard JavaScript number type, allowing serialization of big integers without loss of precision. + * + * @param num - The bigint value to be serialized and added to the buffer. + */ + public bigInt(num: bigint) { this.buf.push(serializeBigInt(num)); } @@ -76,46 +76,46 @@ public bigInt(num: bigint) { } /** - * Serialize a given string by first converting it to a Buffer and then appending its length as a prefix. - * The converted buffer is pushed into the internal buffer array for further serialization. - * This method ensures the corresponding deserialize function can correctly read variable length strings. - * - * @param str - The input string to be serialized. - */ -public string(str: string) { + * Serialize a given string by first converting it to a Buffer and then appending its length as a prefix. + * The converted buffer is pushed into the internal buffer array for further serialization. + * This method ensures the corresponding deserialize function can correctly read variable length strings. + * + * @param str - The input string to be serialized. + */ + public string(str: string) { this.vector(Buffer.from(str)); } /** - * Serializes a Date object and appends it to the buffer. - * The date is converted into a 64-bit integer representing the number of milliseconds since - * January 1, 1970, 00:00:00 UTC. This ensures accurate representation and reconstruction of dates - * during serialization and deserialization processes. - * - * @param date - The Date object to be serialized. - */ -public date(date: Date) { + * Serializes a Date object and appends it to the buffer. + * The date is converted into a 64-bit integer representing the number of milliseconds since + * January 1, 1970, 00:00:00 UTC. This ensures accurate representation and reconstruction of dates + * during serialization and deserialization processes. + * + * @param date - The Date object to be serialized. + */ + public date(date: Date) { this.buf.push(serializeDate(date)); } /** - * Returns the serialized buffer obtained by concatenating all the serialized elements added to the Serializer instance. - * The resulting buffer can be used for data transmission or storage, and can be deserialized later to retrieve the original elements. - * - * @returns A Buffer containing the serialized data from the Serializer instance. - */ -public getBuffer() { + * Returns the serialized buffer obtained by concatenating all the serialized elements added to the Serializer instance. + * The resulting buffer can be used for data transmission or storage, and can be deserialized later to retrieve the original elements. + * + * @returns A Buffer containing the serialized data from the Serializer instance. + */ + public getBuffer() { return Buffer.concat(this.buf); } /** - * Serializes an array of elements and appends it to the internal buffer as a vector. - * Each element in the array is assumed to have a 'toBuffer' method which returns its serialized representation as a Buffer. - * The serialized array is prefixed with its length, allowing for variable-length arrays to be deserialized correctly. - * - * @param arr - The array of elements to be serialized. - */ -public serializeArray(arr: T[]) { + * Serializes an array of elements and appends it to the internal buffer as a vector. + * Each element in the array is assumed to have a 'toBuffer' method which returns its serialized representation as a Buffer. + * The serialized array is prefixed with its length, allowing for variable-length arrays to be deserialized correctly. + * + * @param arr - The array of elements to be serialized. + */ + public serializeArray(arr: T[]) { this.buf.push(serializeBufferArrayToVector(arr.map((e: any) => e.toBuffer()))); } } diff --git a/yarn-project/ethereum.js/src/sleep/index.ts b/yarn-project/ethereum.js/src/sleep/index.ts index 70207608aa6..48a45a3a214 100644 --- a/yarn-project/ethereum.js/src/sleep/index.ts +++ b/yarn-project/ethereum.js/src/sleep/index.ts @@ -1,4 +1,3 @@ - export class InterruptError extends Error {} /** @@ -12,8 +11,7 @@ export class InterruptableSleep { private interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); private timeouts: NodeJS.Timeout[] = []; - -public async sleep(ms: number) { + public async sleep(ms: number) { let timeout!: NodeJS.Timeout; const promise = new Promise(resolve => (timeout = setTimeout(() => resolve(false), ms))); this.timeouts.push(timeout); @@ -25,14 +23,12 @@ public async sleep(ms: number) { } } - -public interrupt(sleepShouldThrow = false) { + public interrupt(sleepShouldThrow = false) { this.interruptResolve(sleepShouldThrow); this.interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); } } - export function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } diff --git a/yarn-project/ethereum.js/src/timer/index.ts b/yarn-project/ethereum.js/src/timer/index.ts index 6c4c17cf3d6..3e1aac7c0f6 100644 --- a/yarn-project/ethereum.js/src/timer/index.ts +++ b/yarn-project/ethereum.js/src/timer/index.ts @@ -1,4 +1,3 @@ - export class Timer { private start: number; @@ -6,13 +5,11 @@ export class Timer { this.start = new Date().getTime(); } - -public ms() { + public ms() { return new Date().getTime() - this.start; } - -public s() { + public s() { return (new Date().getTime() - this.start) / 1000; } } From 583f0f194f07893d2e36f9e4e380cd3a68f59582 Mon Sep 17 00:00:00 2001 From: Orloaft Date: Wed, 19 Apr 2023 19:17:30 -0400 Subject: [PATCH 5/5] fix jsdocs warnings --- .../ethereum.js/src/bigint_buffer/index.ts | 14 +- .../abi/abi-coder/ethers/abi-coder.ts | 33 +++-- .../contract/abi/abi-coder/ethers/errors.ts | 6 +- .../src/contract/abi/abi-coder/index.ts | 128 ++++++++---------- .../src/contract/abi/contract_entry.ts | 4 +- .../contract/abi/contract_function_entry.ts | 4 +- .../src/contract/constructor_interaction.ts | 3 + .../ethereum.js/src/contract/contract.ts | 15 +- .../ethereum.js/src/contract/decode_error.ts | 1 - .../src/contract/function_interaction.ts | 14 +- .../ethereum.js/src/contract/gen_def/index.ts | 8 +- .../gen_def/sources/source-etherscan.ts | 14 +- .../ethereum.js/src/crypto/scrypt/index.ts | 22 +-- .../src/eth_account/eth_account.ts | 4 +- .../ethereum.js/src/eth_rpc/ethereum_rpc.ts | 12 +- .../ethereum.js/src/eth_rpc/sent_tx.ts | 10 +- .../ethereum.js/src/eth_sign/hash_message.ts | 2 +- .../src/eth_transaction/sign_transaction.ts | 2 +- .../ethereum.js/src/eth_typed_data/eip-712.ts | 10 +- yarn-project/ethereum.js/src/log/console.ts | 4 + yarn-project/ethereum.js/src/log/debug.ts | 18 +++ .../src/provider/ethereum_provider.ts | 5 + .../src/provider/json_rpc_provider.ts | 16 +-- .../src/provider/wallet_provider.ts | 7 +- .../ethereum.js/src/provider/web3_adapter.ts | 8 +- yarn-project/ethereum.js/src/retry/index.ts | 9 ++ .../ethereum.js/src/serialize/deserializer.ts | 16 ++- .../ethereum.js/src/serialize/free_funcs.ts | 23 +++- .../ethereum.js/src/serialize/serializer.ts | 6 + yarn-project/ethereum.js/src/sleep/index.ts | 4 + yarn-project/ethereum.js/src/timer/index.ts | 3 + yarn-project/ethereum.js/src/units/units.ts | 12 +- 32 files changed, 270 insertions(+), 167 deletions(-) diff --git a/yarn-project/ethereum.js/src/bigint_buffer/index.ts b/yarn-project/ethereum.js/src/bigint_buffer/index.ts index b04faaaf864..a75777a4f63 100644 --- a/yarn-project/ethereum.js/src/bigint_buffer/index.ts +++ b/yarn-project/ethereum.js/src/bigint_buffer/index.ts @@ -1,6 +1,6 @@ /** * Convert a little-endian buffer into a BigInt. - * @param buf The little-endian buffer to convert + * @param buf - The little-endian buffer to convert. * @returns A BigInt with the little-endian representation of buf. */ export function toBigIntLE(buf: Buffer): bigint { @@ -14,8 +14,8 @@ export function toBigIntLE(buf: Buffer): bigint { } /** - * Convert a big-endian buffer into a BigInt - * @param buf The big-endian buffer to convert. + * Convert a big-endian buffer into a BigInt. + * @param buf - The big-endian buffer to convert. * @returns A BigInt with the big-endian representation of buf. */ export function toBigIntBE(buf: Buffer): bigint { @@ -28,8 +28,8 @@ export function toBigIntBE(buf: Buffer): bigint { /** * Convert a BigInt to a little-endian buffer. - * @param num The BigInt to convert. - * @param width The number of bytes that the resulting buffer should be. + * @param num - The BigInt to convert. + * @param width - The number of bytes that the resulting buffer should be. * @returns A little-endian buffer representation of num. */ export function toBufferLE(num: bigint, width: number): Buffer { @@ -41,8 +41,8 @@ export function toBufferLE(num: bigint, width: number): Buffer { /** * Convert a BigInt to a big-endian buffer. - * @param num The BigInt to convert. - * @param width The number of bytes that the resulting buffer should be. + * @param num - The BigInt to convert. + * @param width - The number of bytes that the resulting buffer should be. * @returns A big-endian buffer representation of num. */ export function toBufferBE(num: bigint, width: number): Buffer { diff --git a/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts b/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts index 04afebad9d4..eb44cfd98f1 100644 --- a/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts +++ b/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/abi-coder.ts @@ -63,6 +63,15 @@ const paramTypeArray = new RegExp(/^(.*)\[([0-9]*)\]$/); // const regexParen = new RegExp('^([^)(]*)\\((.*)\\)([^)(]*)$'); // const regexIdentifier = new RegExp('^[A-Za-z_][A-Za-z0-9_]*$'); +/** + * Verifies and transforms the given type string to its full description if necessary. + * This function handles cases where the input type is a shorthand for specific types + * like 'uint' or 'int', converting them into their complete representations, such as 'uint256' or 'int256'. + * In all other cases, the input type is returned as-is. + * + * @param type - The data type string to be verified and transformed if necessary. + * @returns A string representing the full description of the input type. + */ function verifyType(type: string): string { // These need to be transformed to their full description if (type.match(/^uint($|[^1-9])/)) { @@ -149,7 +158,7 @@ function parseParam(param: string, allowIndexed?: boolean): ParamType { * @param reason - The main reason for the error being thrown. * @param code - The error code associated with the particular type of error. * @param params - An optional object containing any additional information related to the error. - * @throws {Error} A custom error with the provided details. + * @throws Error - A custom error with the provided details. */ function throwError(i: number) { throw new Error('unexpected character "' + param[i] + '" at position ' + i + ' in "' + param + '"'); @@ -453,18 +462,15 @@ function parseParam(param: string, allowIndexed?: boolean): ParamType { /////////////////////////////////// // Coders - +/** + * Represents the result of a decoding operation, containing both the decoded value and the number of bytes consumed during the process. + * This type is used to return information from functions that decode binary data according to specific data types or encoding schemes. + */ type DecodedResult = { - /** - * The number of bytes consumed during decoding. - */ /** * The number of bytes consumed during decoding. */ consumed: number; - /** - * The actual data value for the corresponding coder type. - */ /** * The actual data value for the corresponding coder type. */ @@ -511,7 +517,9 @@ abstract class Coder { abstract decode(data: Buffer, offset: number): DecodedResult; } -// Clones the functionality of an existing Coder, but without a localName +/** + * Clones the functionality of an existing Coder, but without a localName. + */ class CoderAnonymous extends Coder { constructor(private coder: Coder) { super(coder.name, coder.type, undefined, coder.dynamic); @@ -1244,9 +1252,9 @@ class CoderArray extends Coder { * The function takes an array of type descriptors and a buffer containing the ABI encoded data, * and returns an object with decoded values. * - * @param {Array} types - An array of type descriptors, either as strings or ParamType objects. - * @param {Buffer} data - A Buffer containing the ABI encoded data to be decoded. - * @returns {any} An object with the decoded values based on the provided types. + * @param types - An array of type descriptors, either as strings or ParamType objects. + * @param data - A Buffer containing the ABI encoded data to be decoded. + * @returns - An object with the decoded values based on the provided types. */ decode(data: Buffer, offset: number) { // @TODO: @@ -1520,7 +1528,6 @@ export class AbiCoder { * @param data - A Buffer containing the ABI-encoded data to be decoded. * @returns An array or an object containing the decoded values, with optional keys if names are provided in the types. */ - decode(types: Array, data: Buffer): any { const coders = types.map(type => { if (typeof type === 'string') { diff --git a/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/errors.ts b/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/errors.ts index d96f1fb55d3..5e284c83b2a 100644 --- a/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/errors.ts +++ b/yarn-project/ethereum.js/src/contract/abi/abi-coder/ethers/errors.ts @@ -25,8 +25,8 @@ const _censorErrors = false; * * @param message - The custom error message to display. * @param code - The specific error code for this error (default is UNKNOWN_ERROR). - * @param params - An object containing additional information related to the error (e.g. argument name, value, etc.). - * @returns never - This function always throws an error and does not return any value. + * @param params - An object containing additional information related to the error. + * @returns - This function always throws an error and does not return any value. */ export function throwError(message: string, code: string = UNKNOWN_ERROR, params: any = {}): never { if (_censorErrors) { @@ -68,7 +68,7 @@ export function throwError(message: string, code: string = UNKNOWN_ERROR, params * @param count - The actual number of arguments received by the function. * @param expectedCount - The expected number of arguments for the function. * @param suffix - Optional string to be appended to the error message when thrown. - * @throws {Error} If either too few or too many arguments are provided. + * @throws If either too few or too many arguments are provided. */ export function checkArgumentCount(count: number, expectedCount: number, suffix?: string): void { if (!suffix) { diff --git a/yarn-project/ethereum.js/src/contract/abi/abi-coder/index.ts b/yarn-project/ethereum.js/src/contract/abi/abi-coder/index.ts index 515a81f8fd4..1c55bbaa3f1 100644 --- a/yarn-project/ethereum.js/src/contract/abi/abi-coder/index.ts +++ b/yarn-project/ethereum.js/src/contract/abi/abi-coder/index.ts @@ -4,7 +4,7 @@ import { AbiInput } from '../contract_abi_definition.js'; import { hexToBuffer } from '../../../hex_string/index.js'; /** - * ABICoder prototype should be used to encode/decode solidity params of any type + * ABICoder prototype should be used to encode/decode solidity params of any type. */ export class ABICoder { private ethersAbiCoder: EthersAbi; @@ -14,11 +14,10 @@ export class ABICoder { } /** + * EncodeFunctionSignature. * Encodes the function name to its ABI representation, which are the first 4 bytes of the sha3 of the function name including types. - * - * @method encodeFunctionSignature - * @param {String|Object} functionName - * @return {String} encoded function name + * @param functionName - Name of the function. + * @returns Encoded function name. */ public encodeFunctionSignature(functionName) { if (typeof functionName === 'object') { @@ -30,10 +29,9 @@ export class ABICoder { /** * Encodes the function name to its ABI representation, which are the first 4 bytes of the sha3 of the function name including types. - * - * @method encodeEventSignature - * @param {String|Object} functionName - * @return {String} encoded function name + *EncodeEventSignature. + * @param functionName - Name of the function. + * @returns Encoded function name. */ public encodeEventSignature(functionName) { if (typeof functionName === 'object') { @@ -44,24 +42,22 @@ export class ABICoder { } /** - * Should be used to encode plain param - * - * @method encodeParameter - * @param {String} type - * @param {Object} param - * @return {String} encoded plain param + * Should be used to encode plain param. + * EncodeParameter. + * @param type - Type of the param. + * @param param - Param to be encoded. + * @returns Encoded plain param. */ public encodeParameter(type, param) { return this.encodeParameters([type], [param]); } /** - * Should be used to encode list of params - * - * @method encodeParameters - * @param {Array} types - * @param {Array} params - * @return {String} encoded list of params + * Should be used to encode list of params. + * EncodeParameters. + * @param types - Array of types. + * @param params - Params to be encoded. + * @returns Encoded list of params. */ public encodeParameters(types, params) { return hexToBuffer(this.ethersAbiCoder.encode(this.mapTypes(types), params)); @@ -69,11 +65,10 @@ export class ABICoder { /** * Encodes a function call from its json interface and parameters. - * - * @method encodeFunctionCall - * @param {Array} jsonInterface - * @param {Array} params - * @return {String} The encoded ABI for this function call + * EncodeFunctionCall. + * @param jsonInterface - Interface of the function call represented in JSON. + * @param params - Parameters of the function call. + * @returns The encoded ABI for this function call. */ public encodeFunctionCall(jsonInterface, params) { return ( @@ -82,19 +77,19 @@ export class ABICoder { } /** - * Should be used to decode bytes to plain param - * - * @method decodeParameter - * @param {String} type - * @param {String} bytes - * @return {Object} plain param + * Should be used to decode bytes to plain param. + * DecodeParameter. + * @param type - Of param. + * @param bytes - To be decoded. + * @returns Plain param. */ public decodeParameter(type, bytes: Buffer | string) { return this.decodeParameters([type], bytes)[0]; } /** - * Should be used to decode list of params + * Should be used to decode list of params. + * @returns Decoded list of params. */ public decodeParameters(outputs, bytes: Buffer | string): { [k: string | number]: any } { const returnValue: { [k: string | number]: any } = { __length__: 0 }; @@ -130,12 +125,11 @@ export class ABICoder { /** * Decodes events non- and indexed parameters. - * - * @method decodeLog - * @param {Object} inputs - * @param {String} data - * @param {Array} topics - * @return {Array} array of plain params + * DecodeLog. + * @param inputs - Abi inputs. + * @param data - Event data. + * @param topics - Event topics. + * @returns Array of plain params. */ public decodeLog(inputs: AbiInput[], data, topics) { topics = Array.isArray(topics) ? topics : [topics]; @@ -187,11 +181,10 @@ export class ABICoder { } /** - * Map types if simplified format is used - * - * @method mapTypes - * @param {Array} types - * @return {Array} + * Map types if simplified format is used. + * MapTypes. + * @param types - Types to be mapped. + * @returns Array. */ private mapTypes(types) { const mappedTypes: any[] = []; @@ -214,22 +207,20 @@ export class ABICoder { } /** - * Check if type is simplified struct format - * - * @method isSimplifiedStructFormat - * @param {string | Object} type - * @returns {boolean} + * Check if type is simplified struct format. + * IsSimplifiedStructFormat. + * @param type - The type. + * @returns A boolean. */ private isSimplifiedStructFormat(type) { return typeof type === 'object' && typeof type.components === 'undefined' && typeof type.name === 'undefined'; } /** - * Maps the correct tuple type and name when the simplified format in encode/decodeParameter is used - * - * @method mapStructNameAndType - * @param {string} structName - * @return {{type: string, name: *}} + * Maps the correct tuple type and name when the simplified format in encode/decodeParameter is used. + * MapStructNameAndType. + * @param structName - Name. + * @returns \{type: string, name: *\}. */ private mapStructNameAndType(structName) { let type = 'tuple'; @@ -243,11 +234,10 @@ export class ABICoder { } /** - * Maps the simplified format in to the expected format of the ABICoder - * - * @method mapStructToCoderFormat - * @param {Object} struct - * @return {Array} + * Maps the simplified format in to the expected format of the ABICoder. + * MapStructToCoderFormat. + * @param struct - Simplified format. + * @returns Array. */ private mapStructToCoderFormat(struct) { const components: any[] = []; @@ -272,11 +262,10 @@ export class ABICoder { } /** - * Should be used to create full function/event name from json abi - * - * @method jsonInterfaceMethodToString - * @param {Object} json - * @return {String} full function/event name + * Should be used to create full function/event name from json abi. + * JsonInterfaceMethodToString. + * @param json - JSON abi. + * @returns Full function/event name. */ public abiMethodToString(json) { if (typeof json === 'object' && json.name && json.name.indexOf('(') !== -1) { @@ -288,12 +277,11 @@ export class ABICoder { } /** - * Should be used to flatten json abi inputs/outputs into an array of type-representing-strings - * - * @method flattenTypes - * @param {bool} includeTuple - * @param {Object} puts - * @return {Array} parameters as strings + * Should be used to flatten json abi inputs/outputs into an array of type-representing-strings. + * FlattenTypes. + * @param includeTuple - Bool. + * @param puts - Inputs/outputs. + * @returns Array of Parameters as strings. */ function flattenTypes(includeTuple: boolean, puts: any[]) { // console.log("entered _flattenTypes. inputs/outputs: " + puts) diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts b/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts index 78ca1b417da..0c91ea18a2f 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_entry.ts @@ -9,11 +9,11 @@ import { ContractEntryDefinition } from './contract_abi_definition.js'; */ export class ContractEntry { constructor(protected entry: ContractEntryDefinition) {} - + // eslint-disable-next-line jsdoc/require-jsdoc public get name() { return this.entry.name; } - + // eslint-disable-next-line jsdoc/require-jsdoc public get anonymous() { return this.entry.anonymous || false; } diff --git a/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts b/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts index a82ec6d96e9..ae1ef5e20bd 100644 --- a/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts +++ b/yarn-project/ethereum.js/src/contract/abi/contract_function_entry.ts @@ -22,11 +22,11 @@ export class ContractFunctionEntry extends ContractEntry { ? 'constructor' : abiCoder.encodeFunctionSignature(abiCoder.abiMethodToString(entry)); } - + // eslint-disable-next-line jsdoc/require-jsdoc public get constant() { return this.entry.stateMutability === 'view' || this.entry.stateMutability === 'pure' || this.entry.constant; } - + // eslint-disable-next-line jsdoc/require-jsdoc public get payable() { return this.entry.stateMutability === 'payable' || this.entry.payable; } diff --git a/yarn-project/ethereum.js/src/contract/constructor_interaction.ts b/yarn-project/ethereum.js/src/contract/constructor_interaction.ts index e6fe13698ac..f277cd5fd6c 100644 --- a/yarn-project/ethereum.js/src/contract/constructor_interaction.ts +++ b/yarn-project/ethereum.js/src/contract/constructor_interaction.ts @@ -34,6 +34,9 @@ export class ConstructorInteraction extends FunctionInteraction { } /** + * Encodes the ABI (Application Binary Interface) for the function interaction with the provided arguments. + * The encoded ABI is a serialized representation of the function's signature and its arguments, which can be used by the Ethereum client to process the method call or transaction. + * This is useful for encoding contract function calls when interacting with the Ethereum blockchain. * @returns The contract bytecode concatenated with the abi encoded constructor arguments. */ public encodeABI() { diff --git a/yarn-project/ethereum.js/src/contract/contract.ts b/yarn-project/ethereum.js/src/contract/contract.ts index 224bae07cab..50266fdb3db 100644 --- a/yarn-project/ethereum.js/src/contract/contract.ts +++ b/yarn-project/ethereum.js/src/contract/contract.ts @@ -126,10 +126,10 @@ export class Contract { } /** - * - * @param data Contract bytecode as a hex string. - * @param args Constructor arguments. - * @returns + * DeployBytecode. + * @param data - Contract bytecode as a hex string. + * @param args - Constructor arguments. + * @returns ConstructorInteraction. */ public deployBytecode(data: string, ...args: any[]) { const linkedData = Object.entries(this.linkTable).reduce( @@ -218,8 +218,11 @@ export class Contract { return this.executorFactory([new ContractFunctionEntry(abiEntry)]); } - // PRIVATE METHODS + /** + * PRIVATE METHODS. + */ + // eslint-disable-next-line jsdoc/require-jsdoc private executorFactory(functions: ContractFunctionEntry[]): TxFactory { return (...args: any[]): FunctionInteraction => { if (this.address.equals(EthAddress.ZERO)) { @@ -248,7 +251,7 @@ export class Contract { * It groups and assigns contract functions to their respective method names. * In case of function overloads, it will create an executor factory for all matching functions. * - * @private + * * @returns An object containing the generated methods mapped to their respective names. */ private buildMethods() { diff --git a/yarn-project/ethereum.js/src/contract/decode_error.ts b/yarn-project/ethereum.js/src/contract/decode_error.ts index 58afd99ae44..09e99c72cdd 100644 --- a/yarn-project/ethereum.js/src/contract/decode_error.ts +++ b/yarn-project/ethereum.js/src/contract/decode_error.ts @@ -16,7 +16,6 @@ export interface DecodedError { /** * An array of decoded error parameters. */ - params?: any[]; /** * A human-readable description of the error. diff --git a/yarn-project/ethereum.js/src/contract/function_interaction.ts b/yarn-project/ethereum.js/src/contract/function_interaction.ts index 1b95081c597..ae8561a0725 100644 --- a/yarn-project/ethereum.js/src/contract/function_interaction.ts +++ b/yarn-project/ethereum.js/src/contract/function_interaction.ts @@ -78,12 +78,12 @@ export interface TxSend { } /** - * This is the class that is returned when calling e.g. `contract.methods.myMethod(arg1, arg2)` - * It represents an interaction that can occur with that method and arguments. Interactions are: - * - `estimateGas` - * - `call` - * - `send` - * - `encodeAbi` + * This is the class that is returned when calling e.g. `contract.methods.myMethod(arg1, arg2)`. + * It represents an interaction that can occur with that method and arguments. Interactions are:. + * - `estimateGas`. + * - `call`. + * - `send`. + * - `encodeAbi`. */ export class FunctionInteraction implements TxCall, TxSend { constructor( @@ -210,7 +210,7 @@ export class FunctionInteraction implements TxCall, TxSend { * Otherwise, throws the original error with its message. * * @param err - The error object caught during the contract function call execution. - * @throws {Error} An error with either the decoded error message or the original error message. + * @throws An error with either the decoded error message or the original error message. */ private handleError(err: any): never { if (err.data && err.data.length > 2) { diff --git a/yarn-project/ethereum.js/src/contract/gen_def/index.ts b/yarn-project/ethereum.js/src/contract/gen_def/index.ts index af3751aa681..f4c7c208454 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/index.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/index.ts @@ -619,7 +619,7 @@ function makeDefinitionInterface(name: string) { /** * Generate a TypeScript export statement for the given ABI name. - * The exported variable is named '${name}Abi' and its value is the 'abi' identifier. + * The exported variable is named '$(name)Abi' and its value is the 'abi' identifier. * * @param name - The name of the contract ABI to be exported. * @returns A TypeScript export statement node. @@ -639,7 +639,7 @@ function makeAbiExport(name: string) { * @param name - The name of the Contract. * @param abi - The Contract ABI Definition. * @param initData - The initialization data (bytecode) of the Contract. - * @param importPath - Path to '@aztec/ethereum.js' package used for generating import statements. + * @param importPath - Path to '\@aztec/ethereum.js' package used for generating import statements. * @returns An array of TypeScript Nodes representing the generated source code. */ function makeFile(name: string, abi: ContractAbiDefinition, initData: string | undefined, importPath: string) { @@ -672,7 +672,7 @@ function makeFile(name: string, abi: ContractAbiDefinition, initData: string | u /** * Generate the ABI (Application Binary Interface) for a contract and write it to a file. - * The output file will be named as '{name}Abi.ts' in the specified 'outputPath'. + * The output file will be named as '(name)Abi.ts' in the specified 'outputPath'. * The generated file contains an exported default instance of ContractAbi class created * with the provided ABI definition. The import path for the required modules is also generated. * @@ -698,7 +698,7 @@ function makeAndWriteAbi(outputPath: string, name: string, abi: ContractAbiDefin * @param outputPath - The path where the output files will be created. * @param name - The name of the contract used as a prefix for the generated files. * @param buildData - An object containing the ABI and initData of the contract. - * @param importPath - The import path for the '@aztec/ethereum.js' module. + * @param importPath - The import path for the '\@aztec/ethereum.js' module. * @returns A Promise that resolves when all files have been written. */ export async function makeAndWriteFiles( diff --git a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-etherscan.ts b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-etherscan.ts index 1fb88dc7b45..017a2d0e557 100644 --- a/yarn-project/ethereum.js/src/contract/gen_def/sources/source-etherscan.ts +++ b/yarn-project/ethereum.js/src/contract/gen_def/sources/source-etherscan.ts @@ -74,7 +74,19 @@ async function getAbi(net: string, address: string, apiKey: string): Promise boolean) { return new Promise((resolve, reject) => { N = ensureInteger(N, 'N'); diff --git a/yarn-project/ethereum.js/src/eth_account/eth_account.ts b/yarn-project/ethereum.js/src/eth_account/eth_account.ts index 49805e7a120..7c0c448c07c 100644 --- a/yarn-project/ethereum.js/src/eth_account/eth_account.ts +++ b/yarn-project/ethereum.js/src/eth_account/eth_account.ts @@ -130,7 +130,8 @@ export class EthAccount { } /** - * Prefixes the arbitrary length message with the '\x19Ethereum Signed Message:\n' preamble, and signs the message. + * Prefixes the arbitrary length message with the 'x19Ethereum Signed Message:n' preamble, and signs the message. + * @returns An EthSignature instance with the signature components (r, s, v). */ public signMessage(message: Buffer) { return signMessage(hashMessage(message), this.privateKey); @@ -138,6 +139,7 @@ export class EthAccount { /** * Signs a 32 byte digest. + * @returns An EthSignature instance with the signature components (r, s, v). */ public signDigest(digest: Buffer) { if (digest.length !== 32) { diff --git a/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts b/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts index 9f84e1871be..c25a2d70c2e 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/ethereum_rpc.ts @@ -23,14 +23,14 @@ import { LogRequest, toRawLogRequest } from './types/log_request.js'; /** * Provides a direct 1 to 1 mapping with the ethereum JSON-RPC specification. - * https://ethereum.org/en/developers/docs/apis/json-rpc + * Link - https://ethereum.org/en/developers/docs/apis/json-rpc. * * Types are marshalled to/from sensible types. - * Number - * BigInt - * Buffer - * TxHash - * EthAddress + * Number. + * BigInt. + * Buffer. + * TxHash. + * EthAddress. */ export class EthereumRpc { constructor(private provider: EthereumProvider) {} diff --git a/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts b/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts index cc70f990c25..3eb162fca97 100644 --- a/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts +++ b/yarn-project/ethereum.js/src/eth_rpc/sent_tx.ts @@ -45,11 +45,11 @@ export class SentTransaction implements SentTx { * returning the receipt. If 'throwOnError' is set to true, it will throw an error if the receipt * indicates that the transaction failed. Allows setting a 'timeout' and custom polling 'interval'. * - * @param {boolean} throwOnError - Whether to throw an error if the receipt status indicates failure. - * @param {number} numConfirmations - The minimum number of confirmations required before returning the receipt. - * @param {number} timeout - The maximum time in seconds to wait for the receipt before giving up. A value of 0 disables the timeout. - * @param {number} interval - The time in seconds between polling attempts to fetch the receipt. - * @returns {Promise} A promise that resolves to the fetched transaction receipt. + * @param throwOnError - Whether to throw an error if the receipt status indicates failure. + * @param numConfirmations - The minimum number of confirmations required before returning the receipt. + * @param timeout - The maximum time in seconds to wait for the receipt before giving up. A value of 0 disables the timeout. + * @param interval - The time in seconds between polling attempts to fetch the receipt. + * @returns A promise that resolves to the fetched transaction receipt. */ public async getReceipt( throwOnError = true, diff --git a/yarn-project/ethereum.js/src/eth_sign/hash_message.ts b/yarn-project/ethereum.js/src/eth_sign/hash_message.ts index 1ec74fb0cd7..96316c5ea97 100644 --- a/yarn-project/ethereum.js/src/eth_sign/hash_message.ts +++ b/yarn-project/ethereum.js/src/eth_sign/hash_message.ts @@ -5,7 +5,7 @@ import { keccak256 } from '../crypto/index.js'; * The function adds the Ethereum Signed Message preamble and message length before hashing the data. * This helps ensure that the data being signed cannot be misinterpreted as a transaction or other data. * - * @param data - a Buffer containing the data to be hashed. + * @param data - A Buffer containing the data to be hashed. * @returns A Buffer containing the keccak256 hashed Ethereum message. */ export function hashMessage(data: Buffer) { diff --git a/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts b/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts index c6fc41e0bfa..5c6674e4937 100644 --- a/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts +++ b/yarn-project/ethereum.js/src/eth_transaction/sign_transaction.ts @@ -48,7 +48,7 @@ export function recoverTransaction(rawTx: Buffer) { } /** - * Transaction type 2 (EIP1559 as per https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) + * Transaction type 2 (EIP1559 as per https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md). */ export function signTransaction(tx: EthTransaction, privateKey: Buffer): SignedEthTransaction { const { nonce, gas, maxFeePerGas, maxPriorityFeePerGas, chainId } = tx; diff --git a/yarn-project/ethereum.js/src/eth_typed_data/eip-712.ts b/yarn-project/ethereum.js/src/eth_typed_data/eip-712.ts index 63f8ef1cc9d..421af8a841c 100644 --- a/yarn-project/ethereum.js/src/eth_typed_data/eip-712.ts +++ b/yarn-project/ethereum.js/src/eth_typed_data/eip-712.ts @@ -35,10 +35,8 @@ export const getDependencies = (typedData: TypedData, type: string, dependencies /** * Encode a type to a string. All dependant types are alphabetically sorted. * - * @param {TypedData} typedData - * @param {string} type - * @param {Options} [options] - * @return {string} + * @param typedData -. + * @param type -. */ export const encodeType = (typedData: TypedData, type: string): string => { const [primary, ...dependencies] = getDependencies(typedData, type); @@ -102,7 +100,7 @@ const encodeValue = (typedData: TypedData, type: string, data: unknown): [string }; /** - * Encode the data to an ABI encoded Buffer. The data should be a key -> value object with all the required values. All + * Encode the data to an ABI encoded Buffer. The data should be a key -\> value object with all the required values. All * dependant types are automatically encoded. */ export const encodeData = (typedData: TypedData, type: string, data: Record): Buffer => { @@ -127,7 +125,7 @@ export const encodeData = (typedData: TypedData, type: string, data: Record value object with all the required values. All dependant + * Get encoded data as a hash. The data should be a key -\> value object with all the required values. All dependant * types are automatically encoded. */ export const getStructHash = (typedData: TypedData, type: string, data: Record) => { diff --git a/yarn-project/ethereum.js/src/log/console.ts b/yarn-project/ethereum.js/src/log/console.ts index 6315a10e0e7..07854d8cf01 100644 --- a/yarn-project/ethereum.js/src/log/console.ts +++ b/yarn-project/ethereum.js/src/log/console.ts @@ -1,13 +1,17 @@ +// eslint-disable-next-line jsdoc/require-jsdoc export type Logger = (...args: any[]) => void; +// eslint-disable-next-line jsdoc/require-jsdoc class ConsoleLogger { constructor(private prefix: string, private logger: (...args: any[]) => void = console.log) {} + // eslint-disable-next-line jsdoc/require-jsdoc public log(...args: any[]) { this.logger(`${this.prefix}:`, ...args); } } +// eslint-disable-next-line jsdoc/require-jsdoc export function createLogger(prefix: string): Logger { if (prefix) { const logger = new ConsoleLogger(prefix, console.log); diff --git a/yarn-project/ethereum.js/src/log/debug.ts b/yarn-project/ethereum.js/src/log/debug.ts index 812554cb762..8623ac61bee 100644 --- a/yarn-project/ethereum.js/src/log/debug.ts +++ b/yarn-project/ethereum.js/src/log/debug.ts @@ -3,6 +3,9 @@ import debug from 'debug'; let preLogHook: ((...args: any[]) => void) | undefined; let postLogHook: ((...args: any[]) => void) | undefined; +/** + * + */ function theFunctionThroughWhichAllLogsPass(logger: any, ...args: any[]) { if (!debug.enabled(logger.namespace)) { return; @@ -16,23 +19,38 @@ function theFunctionThroughWhichAllLogsPass(logger: any, ...args: any[]) { } } +/** + * + */ export function createDebugLogger(name: string): any { const logger = debug(name); return (...args: any[]) => theFunctionThroughWhichAllLogsPass(logger, ...args); } +/** + * + */ export function setPreDebugLogHook(fn: (...args: any[]) => void) { preLogHook = fn; } +/** + * + */ export function setPostDebugLogHook(fn: (...args: any[]) => void) { postLogHook = fn; } +/** + * + */ export function enableLogs(str: string) { debug.enable(str); } +/** + * + */ export function isLogEnabled(str: string) { return debug.enabled(str); } diff --git a/yarn-project/ethereum.js/src/provider/ethereum_provider.ts b/yarn-project/ethereum.js/src/provider/ethereum_provider.ts index b49a2cb081a..8249d72b259 100644 --- a/yarn-project/ethereum.js/src/provider/ethereum_provider.ts +++ b/yarn-project/ethereum.js/src/provider/ethereum_provider.ts @@ -1,3 +1,8 @@ +/** + * ProviderError is an enumeration representing specific error codes related to Ethereum provider communication. + * These error codes can be used by applications to handle various provider-related events or issues, such as user rejection, unauthorized access, unsupported functionality, and connection problems. + * By standardizing these error codes, it allows for more consistent and robust error handling across different Ethereum providers and applications. + */ export enum ProviderError { USER_REJECTED = 4001, UNAUTHORIZED = 4100, diff --git a/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts b/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts index 261e878e5c7..5badc4faf5b 100644 --- a/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts +++ b/yarn-project/ethereum.js/src/provider/json_rpc_provider.ts @@ -20,10 +20,10 @@ export class JsonRpcProvider implements EthereumProvider { * The 'method' should be a valid Ethereum JSON-RPC method, and 'params' should be an array of inputs required for that method. * Returns a promise which resolves to the result of the request, or rejects with an error if the request fails. * - * @param {RequestArguments} requestArguments - An object containing 'method' and 'params' properties. - * @param {string} requestArguments.method - The Ethereum JSON-RPC method to call. - * @param {Array} requestArguments.params - The parameters required for the called method. - * @returns {Promise} A promise resolving to the result of the request, or rejecting with an error if the request fails. + * @param requestArguments - An object containing 'method' and 'params' properties. + * @param method - The Ethereum JSON-RPC method to call. + * @param params - The parameters required for the called method. + * @returns A promise resolving to the result of the request, or rejecting with an error if the request fails. */ public async request({ method, params }: RequestArguments): Promise { const body = { @@ -45,8 +45,8 @@ export class JsonRpcProvider implements EthereumProvider { * Registers an event listener for the specified event on the JsonRpcProvider instance. * This method is not supported in the current implementation and will throw an error when called. * - * @throws {Error} An error indicating that events are not supported by the JsonRpcProvider. - * @returns {this} The current JsonRpcProvider instance. + * @throws An error indicating that events are not supported by the JsonRpcProvider. + * @returns The current JsonRpcProvider instance. */ on(): this { throw new Error('Events not supported.'); @@ -56,8 +56,8 @@ export class JsonRpcProvider implements EthereumProvider { * Remove an event listener from the Ethereum provider. This method is not supported by JsonRpcProvider * and will throw an error when called. To use event handling, consider using a different provider implementation. * - * @throws {Error} Throws an error indicating that events are not supported by this provider. - * @returns {this} Returns the current instance of the class for chaining purposes. + * @throws Throws an error indicating that events are not supported by this provider. + * @returns Returns the current instance of the class for chaining purposes. */ removeListener(): this { throw new Error('Events not supported.'); diff --git a/yarn-project/ethereum.js/src/provider/wallet_provider.ts b/yarn-project/ethereum.js/src/provider/wallet_provider.ts index 430e643df29..6142c82ce75 100644 --- a/yarn-project/ethereum.js/src/provider/wallet_provider.ts +++ b/yarn-project/ethereum.js/src/provider/wallet_provider.ts @@ -165,6 +165,7 @@ export class WalletProvider implements EthereumProvider { /** * The message will be prefixed and hashed, and the hash is signed. + * @returns Promise. */ private async ethSign(args: RequestArguments) { const [from, message] = args.params!; @@ -177,8 +178,9 @@ export class WalletProvider implements EthereumProvider { } /** - * personal_sign is the same as eth_sign but with args reversed. - * This is favoured as it has better client support r.e. displaying the message to the user before signing. + * Personal_sign is the same as eth_sign but with args reversed. + * This is favoured as it has better client support r.e. Displaying the message to the user before signing. + * @returns Promise | string. */ private async personalSign(args: RequestArguments) { const [message, from] = args.params!; @@ -211,6 +213,7 @@ export class WalletProvider implements EthereumProvider { /** * Given a tx in Eth Json Rpc format, create an EthTransaction, populate any missing fields, and sign. + * @returns Buffer. */ private async signTxLocally(tx: any, account: EthAccount) { const { chainId, to, gas, maxFeePerGas, maxPriorityFeePerGas, value, data, nonce } = tx; diff --git a/yarn-project/ethereum.js/src/provider/web3_adapter.ts b/yarn-project/ethereum.js/src/provider/web3_adapter.ts index 76ef933ca01..e84fb29d411 100644 --- a/yarn-project/ethereum.js/src/provider/web3_adapter.ts +++ b/yarn-project/ethereum.js/src/provider/web3_adapter.ts @@ -43,8 +43,8 @@ export class Web3Adapter implements EthereumProvider { * Adds an event listener for the specified event on the Web3Adapter instance. * Please note that this method is not implemented and will throw an error when called, as events are not supported. * - * @throws {Error} Will throw an error if the method is called, because events are not supported in this implementation. - * @returns {this} Returns the Web3Adapter instance for chaining purposes (if events were supported). + * @throws Will throw an error if the method is called, because events are not supported in this implementation. + * @returns Returns the Web3Adapter instance for chaining purposes (if events were supported). */ on(): this { throw new Error('Events not supported.'); @@ -54,8 +54,8 @@ export class Web3Adapter implements EthereumProvider { * Remove an event listener from the Ethereum provider. * This method is not supported for the Web3Adapter class, and calling it will result in an error being thrown. * - * @throws {Error} - An error indicating that event removal is not supported. - * @returns {this} - The current instance of the Web3Adapter class. + * @throws - An error indicating that event removal is not supported. + * @returns - The current instance of the Web3Adapter class. */ removeListener(): this { throw new Error('Events not supported.'); diff --git a/yarn-project/ethereum.js/src/retry/index.ts b/yarn-project/ethereum.js/src/retry/index.ts index a293108ca6c..df7ef669571 100644 --- a/yarn-project/ethereum.js/src/retry/index.ts +++ b/yarn-project/ethereum.js/src/retry/index.ts @@ -1,6 +1,9 @@ import { sleep } from '../sleep/index.js'; import { Timer } from '../timer/index.js'; +/** + * + */ export function* backoffGenerator() { const v = [1, 1, 1, 2, 4, 8, 16, 32, 64]; let i = 0; @@ -9,6 +12,9 @@ export function* backoffGenerator() { } } +/** + * + */ export async function retry(fn: () => Promise, name = 'Operation', backoff = backoffGenerator()) { while (true) { try { @@ -29,6 +35,9 @@ export async function retry(fn: () => Promise, name = 'Operation // Call `fn` repeatedly until it returns true or timeout. // Both `interval` and `timeout` are seconds. // Will never timeout if the value is 0. +/** + * + */ export async function retryUntil(fn: () => Promise, name = '', timeout = 0, interval = 1) { const timer = new Timer(); while (true) { diff --git a/yarn-project/ethereum.js/src/serialize/deserializer.ts b/yarn-project/ethereum.js/src/serialize/deserializer.ts index 6c031b036aa..42479a6cad0 100644 --- a/yarn-project/ethereum.js/src/serialize/deserializer.ts +++ b/yarn-project/ethereum.js/src/serialize/deserializer.ts @@ -7,61 +7,75 @@ import { deserializeUInt32, } from './free_funcs.js'; +// eslint-disable-next-line jsdoc/require-jsdoc export type DeserializeFn = ( buf: Buffer, offset: number, ) => { + // eslint-disable-next-line jsdoc/require-jsdoc elem: T; + // eslint-disable-next-line jsdoc/require-jsdoc adv: number; }; +// eslint-disable-next-line jsdoc/require-jsdoc export class Deserializer { constructor(private buf: Buffer, private offset = 0) {} + // eslint-disable-next-line jsdoc/require-jsdoc public bool() { return this.exec(deserializeBool) ? true : false; } + // eslint-disable-next-line jsdoc/require-jsdoc public uInt32() { return this.exec(deserializeUInt32); } + // eslint-disable-next-line jsdoc/require-jsdoc public int32() { return this.exec(deserializeInt32); } + // eslint-disable-next-line jsdoc/require-jsdoc public bigInt(width = 32) { return this.exec((buf: Buffer, offset: number) => deserializeBigInt(buf, offset, width)); } + // eslint-disable-next-line jsdoc/require-jsdoc public vector() { return this.exec(deserializeBufferFromVector); } + // eslint-disable-next-line jsdoc/require-jsdoc public buffer(width: number) { const buf = this.buf.slice(this.offset, this.offset + width); this.offset += width; return buf; } + // eslint-disable-next-line jsdoc/require-jsdoc public string() { return this.vector().toString(); } + // eslint-disable-next-line jsdoc/require-jsdoc public date() { return new Date(Number(this.bigInt(8))); } - + // eslint-disable-next-line jsdoc/require-jsdoc public deserializeArray(fn: DeserializeFn) { return this.exec((buf: Buffer, offset: number) => deserializeArrayFromVector(fn, buf, offset)); } + // eslint-disable-next-line jsdoc/require-jsdoc public exec(fn: DeserializeFn): T { const { elem, adv } = fn(this.buf, this.offset); this.offset += adv; return elem; } + // eslint-disable-next-line jsdoc/require-jsdoc public getOffset() { return this.offset; } diff --git a/yarn-project/ethereum.js/src/serialize/free_funcs.ts b/yarn-project/ethereum.js/src/serialize/free_funcs.ts index afda89748d5..eb3ce9b0a3a 100644 --- a/yarn-project/ethereum.js/src/serialize/free_funcs.ts +++ b/yarn-project/ethereum.js/src/serialize/free_funcs.ts @@ -1,6 +1,9 @@ import { toBigIntBE, toBufferBE } from '../bigint_buffer/index.js'; // For serializing bool. +/** + * + */ export function boolToByte(b: boolean) { const buf = Buffer.alloc(1); buf.writeUInt8(b ? 1 : 0); @@ -8,6 +11,9 @@ export function boolToByte(b: boolean) { } // For serializing numbers to 32 bit little-endian form. +/** + * + */ export function numToUInt32LE(n: number, bufferSize = 4) { const buf = Buffer.alloc(bufferSize); buf.writeUInt32LE(n, bufferSize - 4); @@ -15,6 +21,9 @@ export function numToUInt32LE(n: number, bufferSize = 4) { } // For serializing numbers to 32 bit big-endian form. +/** + * + */ export function numToUInt32BE(n: number, bufferSize = 4) { const buf = Buffer.alloc(bufferSize); buf.writeUInt32BE(n, bufferSize - 4); @@ -22,6 +31,9 @@ export function numToUInt32BE(n: number, bufferSize = 4) { } // For serializing signed numbers to 32 bit big-endian form. +/** + * + */ export function numToInt32BE(n: number, bufferSize = 4) { const buf = Buffer.alloc(bufferSize); buf.writeInt32BE(n, bufferSize - 4); @@ -29,6 +41,9 @@ export function numToInt32BE(n: number, bufferSize = 4) { } // For serializing numbers to 32 bit big-endian form. +/** + * + */ export function numToUInt8(n: number) { const bufferSize = 1; const buf = Buffer.alloc(bufferSize); @@ -37,6 +52,9 @@ export function numToUInt8(n: number) { } // For serializing a buffer as a vector. +/** + * + */ export function serializeBufferToVector(buf: Buffer) { const lengthBuf = Buffer.alloc(4); lengthBuf.writeUInt32BE(buf.length, 0); @@ -154,6 +172,9 @@ export function deserializeField(buf: Buffer, offset = 0) { } // For serializing an array of fixed length elements. +/** + * + */ export function serializeBufferArrayToVector(arr: Buffer[]) { const lengthBuf = Buffer.alloc(4); lengthBuf.writeUInt32BE(arr.length, 0); @@ -166,7 +187,7 @@ export function serializeBufferArrayToVector(arr: Buffer[]) { * elements and applies the provided deserialization function on each element. Returns an array * of the deserialized elements and the total bytes consumed in the process. * - * @typeparam - The type of the deserialized elements. + * @typeparam T - The type of the deserialized elements. * @param deserialize - The deserialization function to be applied on each element of the array. * @param vector - The source buffer containing the serialized data. * @param offset - The starting position in the buffer to begin deserialization (optional, default is 0). diff --git a/yarn-project/ethereum.js/src/serialize/serializer.ts b/yarn-project/ethereum.js/src/serialize/serializer.ts index a1b947935b3..4ed704f46d7 100644 --- a/yarn-project/ethereum.js/src/serialize/serializer.ts +++ b/yarn-project/ethereum.js/src/serialize/serializer.ts @@ -10,6 +10,12 @@ import { // export type DeserializeFn = (buf: Buffer, offset: number) => { elem: T; adv: number }; +/** + * The Serializer class is a utility for converting various data types into binary format (Buffer) suitable for transmission or storage. + * It offers several methods to serialize different data types, such as bool, int32, uInt32, bigInt, vector, buffer, string, and date. + * Additionally, it allows serializing arrays of elements with custom 'toBuffer' methods. Serialized data can be retrieved as a single + * Buffer using the getBuffer method. The class ensures proper serialization of variable-length data by prefixing them with their corresponding length. + */ export class Serializer { private buf: Buffer[] = []; diff --git a/yarn-project/ethereum.js/src/sleep/index.ts b/yarn-project/ethereum.js/src/sleep/index.ts index 48a45a3a214..5300376c78f 100644 --- a/yarn-project/ethereum.js/src/sleep/index.ts +++ b/yarn-project/ethereum.js/src/sleep/index.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line jsdoc/require-jsdoc export class InterruptError extends Error {} /** @@ -11,6 +12,7 @@ export class InterruptableSleep { private interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); private timeouts: NodeJS.Timeout[] = []; + // eslint-disable-next-line jsdoc/require-jsdoc public async sleep(ms: number) { let timeout!: NodeJS.Timeout; const promise = new Promise(resolve => (timeout = setTimeout(() => resolve(false), ms))); @@ -23,12 +25,14 @@ export class InterruptableSleep { } } + // eslint-disable-next-line jsdoc/require-jsdoc public interrupt(sleepShouldThrow = false) { this.interruptResolve(sleepShouldThrow); this.interruptPromise = new Promise(resolve => (this.interruptResolve = resolve)); } } +// eslint-disable-next-line jsdoc/require-jsdoc export function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } diff --git a/yarn-project/ethereum.js/src/timer/index.ts b/yarn-project/ethereum.js/src/timer/index.ts index 3e1aac7c0f6..d267285d11d 100644 --- a/yarn-project/ethereum.js/src/timer/index.ts +++ b/yarn-project/ethereum.js/src/timer/index.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line jsdoc/require-jsdoc export class Timer { private start: number; @@ -5,10 +6,12 @@ export class Timer { this.start = new Date().getTime(); } + // eslint-disable-next-line jsdoc/require-jsdoc public ms() { return new Date().getTime() - this.start; } + // eslint-disable-next-line jsdoc/require-jsdoc public s() { return (new Date().getTime() - this.start) / 1000; } diff --git a/yarn-project/ethereum.js/src/units/units.ts b/yarn-project/ethereum.js/src/units/units.ts index 82e56013a30..274414c5bde 100644 --- a/yarn-project/ethereum.js/src/units/units.ts +++ b/yarn-project/ethereum.js/src/units/units.ts @@ -1,11 +1,11 @@ /** * Converts the value to a decimal string representation with the given precision. - * The digits outside the precision are simply discarded (i.e. the result is floored). + * The digits outside the precision are simply discarded (i,e, the result is floored). * This ensures we never report more funds than actually exists. * Trailing 0's are also removed. - * @param value to convert to string - * @param decimals the number of least significant digits of value that represent the decimal - * @param precision the number of decimal places to return + * @param value - To convert to string. + * @param decimals - The number of least significant digits of value that represent the decimal. + * @param precision - The number of decimal places to return. */ export function fromBaseUnits(value: bigint, decimals: number, precision: number = decimals) { const neg = value < BigInt(0); @@ -23,8 +23,8 @@ export function fromBaseUnits(value: bigint, decimals: number, precision: number /** * Converts the value from a decimal string to bigint value. - * @param valueString to convert to bigint - * @param decimals the number of least significant digits of value that represent the decimal + * @param valueString - To convert to bigint. + * @param decimals - The number of least significant digits of value that represent the decimal. */ export function toBaseUnits(valueString: string, decimals: number) { const [integer, decimal] = valueString.split('.');