From e58e6366e65f5e52b00efbd679d93b7f3d1aad5d Mon Sep 17 00:00:00 2001 From: Luis Mastrangelo Date: Tue, 20 May 2025 17:50:41 +0200 Subject: [PATCH 01/16] Add validator refactor PoC draft Signed-off-by: Luis Mastrangelo --- packages/relay/src/lib/debug.ts | 13 +- packages/relay/src/lib/decorators/index.ts | 1 - .../rpcParamValidationRules.decorator.ts | 34 ---- .../src/lib/dispatcher/rpcMethodDispatcher.ts | 5 +- packages/relay/src/lib/eth.ts | 73 +++---- .../rpcMethodRegistryService.ts | 3 +- packages/relay/src/lib/types/index.ts | 1 - packages/relay/src/lib/types/validation.ts | 114 ----------- .../relay/src/lib/validators/constants.ts | 3 - packages/relay/src/lib/validators/index.ts | 93 ++++++++- .../relay/src/lib/validators/objectTypes.ts | 181 ++++-------------- packages/relay/src/lib/validators/types.ts | 45 +++-- packages/relay/src/lib/validators/utils.ts | 59 +----- packages/relay/src/lib/web3.ts | 6 +- packages/relay/src/utils.ts | 1 + packages/ws-server/src/utils/validators.ts | 17 +- 16 files changed, 212 insertions(+), 437 deletions(-) delete mode 100644 packages/relay/src/lib/decorators/rpcParamValidationRules.decorator.ts delete mode 100644 packages/relay/src/lib/types/validation.ts diff --git a/packages/relay/src/lib/debug.ts b/packages/relay/src/lib/debug.ts index e41b71406d..1c98079ff7 100644 --- a/packages/relay/src/lib/debug.ts +++ b/packages/relay/src/lib/debug.ts @@ -9,7 +9,7 @@ import { MirrorNodeClient } from './clients'; import { IOpcode } from './clients/models/IOpcode'; import { IOpcodesResponse } from './clients/models/IOpcodesResponse'; import constants, { CallType, TracerType } from './constants'; -import { cache, RPC_LAYOUT, rpcMethod, rpcParamLayoutConfig, rpcParamValidationRules } from './decorators'; +import { cache, RPC_LAYOUT, rpcMethod, rpcParamLayoutConfig } from './decorators'; import { predefined } from './errors/JsonRpcError'; import { CommonService } from './services'; import { CACHE_LEVEL, CacheService } from './services/cacheService/cacheService'; @@ -20,11 +20,11 @@ import { ICallTracerConfig, IOpcodeLoggerConfig, MirrorNodeContractResult, - ParamType, RequestDetails, TraceBlockByNumberTxResult, TransactionTracerConfig, } from './types'; +import { rpcParamValidationRules } from './validators'; /** * Represents a DebugService for tracing and debugging transactions. @@ -105,8 +105,9 @@ export class DebugImpl implements Debug { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.TRANSACTION_HASH_OR_ID, required: true }, - 1: { type: ParamType.TRACER_CONFIG_WRAPPER, required: false }, + 0: { type: ['transactionHash'], required: true }, + 1: { type: ['tracerType', 'tracerConfig', 'tracerConfigWrapper'], required: false }, + 2: { type: 'tracerConfig', required: false }, }) @rpcParamLayoutConfig(RPC_LAYOUT.custom((params) => [params[0], params[1]])) @cache(CacheService.getInstance(CACHE_LEVEL.L1)) @@ -161,8 +162,8 @@ export class DebugImpl implements Debug { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.BLOCK_NUMBER, required: true }, - 1: { type: ParamType.TRACER_CONFIG_WRAPPER, required: false }, + 0: { type: 'blockNumber', required: true }, + 1: { type: 'tracerConfigWrapper', required: false }, }) @rpcParamLayoutConfig(RPC_LAYOUT.custom((params) => [params[0], params[1]])) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { diff --git a/packages/relay/src/lib/decorators/index.ts b/packages/relay/src/lib/decorators/index.ts index adca248c35..02130dd4e6 100644 --- a/packages/relay/src/lib/decorators/index.ts +++ b/packages/relay/src/lib/decorators/index.ts @@ -1,6 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 export * from './rpcMethod.decorator'; -export * from './rpcParamValidationRules.decorator'; export * from './rpcParamLayoutConfig.decorator'; export * from './cache.decorator'; diff --git a/packages/relay/src/lib/decorators/rpcParamValidationRules.decorator.ts b/packages/relay/src/lib/decorators/rpcParamValidationRules.decorator.ts deleted file mode 100644 index aa866295fa..0000000000 --- a/packages/relay/src/lib/decorators/rpcParamValidationRules.decorator.ts +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -import { IParamValidation } from '../types'; - -/** - * This key is attached to method functions to store their validation rules. - */ -export const RPC_PARAM_VALIDATION_RULES_KEY = 'hedera-rpc-param-validation-rules'; - -/** - * Decorator that defines a schema for validating RPC method parameters - * - * @example - * ```typescript - * @rpcMethod - * @rpcParamValidationRules({ - * 0: { type: 'address', required: true }, - * 1: { type: 'blockNumber', required: true } - * }) - * getBalance(address: string, blockNumber: string, requestDetails: RequestDetails): Promise { - * // Implementation - * } - * ``` - * - * @param validationRules - Validation rules for method parameters - * @returns Method decorator function - */ -export function rpcParamValidationRules(validationRules: Record) { - return function (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) { - // Store validation rules directly on the function as a property - descriptor.value[RPC_PARAM_VALIDATION_RULES_KEY] = validationRules; - return descriptor; - }; -} diff --git a/packages/relay/src/lib/dispatcher/rpcMethodDispatcher.ts b/packages/relay/src/lib/dispatcher/rpcMethodDispatcher.ts index 36e0ae1a12..44d301c2a3 100644 --- a/packages/relay/src/lib/dispatcher/rpcMethodDispatcher.ts +++ b/packages/relay/src/lib/dispatcher/rpcMethodDispatcher.ts @@ -3,13 +3,12 @@ import { Logger } from 'pino'; import { Utils } from '../../utils'; -import { RPC_PARAM_VALIDATION_RULES_KEY } from '../decorators'; import { JsonRpcError } from '../errors/JsonRpcError'; import { predefined } from '../errors/JsonRpcError'; import { MirrorNodeClientError } from '../errors/MirrorNodeClientError'; import { SDKClientError } from '../errors/SDKClientError'; import { OperationHandler, RequestDetails, RpcMethodRegistry } from '../types'; -import { Validator } from '../validators'; +import { RPC_PARAM_VALIDATION_RULES_KEY, validateParams } from '../validators'; /** * Dispatches JSON-RPC method calls to their appropriate handlers @@ -105,7 +104,7 @@ export class RpcMethodDispatcher { } Validating method parameters for ${rpcMethodName}, params: ${JSON.stringify(rpcMethodParams)}`, ); } - Validator.validateParams(rpcMethodParams, methodParamSchemas); + validateParams(rpcMethodParams, methodParamSchemas); } return operationHandler; diff --git a/packages/relay/src/lib/eth.ts b/packages/relay/src/lib/eth.ts index 7a3b690503..eda880a11d 100644 --- a/packages/relay/src/lib/eth.ts +++ b/packages/relay/src/lib/eth.ts @@ -6,7 +6,7 @@ import { Logger } from 'pino'; import { Eth } from '../index'; import { MirrorNodeClient } from './clients'; import constants from './constants'; -import { cache, RPC_LAYOUT, rpcMethod, rpcParamLayoutConfig, rpcParamValidationRules } from './decorators'; +import { cache, RPC_LAYOUT, rpcMethod, rpcParamLayoutConfig } from './decorators'; import { JsonRpcError, predefined } from './errors/JsonRpcError'; import { Block, Log, Receipt, Transaction } from './model'; import { @@ -35,6 +35,7 @@ import { RequestDetails, } from './types'; import { ParamType } from './types/validation'; +import { rpcParamValidationRules } from './validators'; /** * Implementation of the "eth_" methods from the Ethereum JSON-RPC API. @@ -175,9 +176,9 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.HEX, required: true }, - 1: { type: ParamType.BLOCK_NUMBER, required: true }, - 2: { type: ParamType.ARRAY, required: false }, + 0: { type: 'hex', required: true }, + 1: { type: 'blockNumber', required: true }, + 2: { type: 'array', required: false }, }) @rpcParamLayoutConfig(RPC_LAYOUT.custom((params) => [Number(params[0]), params[1], params[2]])) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { @@ -248,8 +249,8 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.TRANSACTION, required: true }, - 1: { type: ParamType.BLOCK_NUMBER, required: false }, + 0: { type: 'transaction', required: true }, + 1: { type: 'blockNumber', required: false }, }) @rpcParamLayoutConfig(RPC_LAYOUT.custom((params) => [params[0], params[1]])) async estimateGas( @@ -322,7 +323,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.FILTER, required: true }, + 0: { type: 'filter', required: true }, }) async newFilter(params: INewFilterParams, requestDetails: RequestDetails): Promise { const requestIdPrefix = requestDetails.formattedRequestId; @@ -344,7 +345,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.HEX, required: true }, + 0: { type: 'hex', required: true }, }) async getFilterLogs(filterId: string, requestDetails: RequestDetails): Promise { if (this.logger.isLevelEnabled('trace')) { @@ -365,7 +366,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.HEX, required: true }, + 0: { type: 'hex', required: true }, }) async getFilterChanges(filterId: string, requestDetails: RequestDetails): Promise { if (this.logger.isLevelEnabled('trace')) { @@ -404,7 +405,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.HEX, required: true }, + 0: { type: 'hex', required: true }, }) async uninstallFilter(filterId: string, requestDetails: RequestDetails): Promise { if (this.logger.isLevelEnabled('trace')) { @@ -677,9 +678,9 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.ADDRESS, required: true }, - 1: { type: ParamType.HEX64, required: true }, - 2: { type: ParamType.BLOCK_NUMBER_OR_HASH, required: true }, + 0: { type: 'address', required: true }, + 1: { type: 'hex64', required: true }, + 2: { type: ['blockNumber', 'blockHash'], required: false }, }) @rpcParamLayoutConfig(RPC_LAYOUT.custom((params) => [params[0], params[1], params[2]])) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { @@ -708,8 +709,8 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.ADDRESS, required: true }, - 1: { type: ParamType.BLOCK_NUMBER_OR_HASH, required: true }, + 0: { type: 'address', required: true }, + 1: { type: ['blockNumber', 'blockHash'], required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { skipParams: [{ index: '1', value: constants.NON_CACHABLE_BLOCK_PARAMS }], @@ -736,8 +737,8 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.ADDRESS, required: true }, - 1: { type: ParamType.BLOCK_NUMBER_OR_HASH, required: true }, + 0: { type: 'address', required: true }, + 1: { type: ['blockNumber', 'blockHash'], required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { skipParams: [{ index: '1', value: constants.NON_CACHABLE_BLOCK_PARAMS }], @@ -763,8 +764,8 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.BLOCK_HASH, required: true }, - 1: { type: ParamType.BOOLEAN, required: true }, + 0: { type: 'blockHash', required: true }, + 1: { type: 'boolean', required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1)) async getBlockByHash(hash: string, showDetails: boolean, requestDetails: RequestDetails): Promise { @@ -783,7 +784,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.BLOCK_HASH, required: true }, + 0: { type: 'blockHash', required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1)) async getBlockTransactionCountByHash(hash: string, requestDetails: RequestDetails): Promise { @@ -802,7 +803,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.BLOCK_NUMBER, required: true }, + 0: { type: 'blockNumber', required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { skipParams: [{ index: '0', value: constants.NON_CACHABLE_BLOCK_PARAMS }], @@ -827,8 +828,8 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.BLOCK_HASH, required: true }, - 1: { type: ParamType.HEX, required: true }, + 0: { type: 'blockHash', required: true }, + 1: { type: 'hex', required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1)) async getTransactionByBlockHashAndIndex( @@ -852,8 +853,8 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.BLOCK_NUMBER, required: true }, - 1: { type: ParamType.HEX, required: true }, + 0: { type: 'blockNumber', required: true }, + 1: { type: 'hex', required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { skipParams: [{ index: '0', value: constants.NON_CACHABLE_BLOCK_PARAMS }], @@ -883,8 +884,8 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.BLOCK_NUMBER, required: true }, - 1: { type: ParamType.BOOLEAN, required: true }, + 0: { type: 'blockNumber', required: true }, + 1: { type: 'boolean', required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { skipParams: [{ index: '0', value: constants.NON_CACHABLE_BLOCK_PARAMS }], @@ -913,8 +914,8 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.ADDRESS, required: true }, - 1: { type: ParamType.BLOCK_NUMBER_OR_HASH, required: true }, + 0: { type: 'address', required: true }, + 1: { type: ['blockNumber', 'blockHash'], required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { skipParams: [{ index: '1', value: constants.NON_CACHABLE_BLOCK_PARAMS }], @@ -939,7 +940,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.HEX, required: true }, + 0: { type: 'hex', required: true }, }) async sendRawTransaction(transaction: string, requestDetails: RequestDetails): Promise { return await this.transactionService.sendRawTransaction(transaction, requestDetails); @@ -958,8 +959,8 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.TRANSACTION, required: true }, - 1: { type: ParamType.BLOCK_PARAMS, required: true }, + 0: { type: 'transaction', required: true }, + 1: { type: 'blockParams', required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { skipParams: [{ index: '1', value: constants.NON_CACHABLE_BLOCK_PARAMS }], @@ -1001,7 +1002,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.TRANSACTION_HASH, required: true }, + 0: { type: 'transactionHash', required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1)) async getTransactionByHash(hash: string, requestDetails: RequestDetails): Promise { @@ -1019,7 +1020,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.TRANSACTION_HASH, required: true }, + 0: { type: 'transactionHash', required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1)) async getTransactionReceipt(hash: string, requestDetails: RequestDetails): Promise { @@ -1058,7 +1059,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.FILTER, required: true }, + 0: { type: 'filter', required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { skipNamedParams: [ @@ -1106,7 +1107,7 @@ export class EthImpl implements Eth { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.BLOCK_NUMBER_OR_HASH, required: true }, + 0: { type: ['blockNumber', 'blockHash'], required: true }, }) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { skipParams: [{ index: '0', value: constants.NON_CACHABLE_BLOCK_PARAMS }], diff --git a/packages/relay/src/lib/services/registryService/rpcMethodRegistryService.ts b/packages/relay/src/lib/services/registryService/rpcMethodRegistryService.ts index eed5d027b3..5cd6d98121 100644 --- a/packages/relay/src/lib/services/registryService/rpcMethodRegistryService.ts +++ b/packages/relay/src/lib/services/registryService/rpcMethodRegistryService.ts @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 -import { RPC_METHOD_KEY, RPC_PARAM_LAYOUT_KEY, RPC_PARAM_VALIDATION_RULES_KEY } from '../../decorators'; +import { RPC_METHOD_KEY, RPC_PARAM_LAYOUT_KEY } from '../../decorators'; import { RpcMethodRegistry, RpcNamespaceRegistry } from '../../types'; +import { RPC_PARAM_VALIDATION_RULES_KEY } from '../../validators'; /** * Registers RPC methods from the provided service implementations. diff --git a/packages/relay/src/lib/types/index.ts b/packages/relay/src/lib/types/index.ts index 19cd1d8f9f..5a0609f1fa 100644 --- a/packages/relay/src/lib/types/index.ts +++ b/packages/relay/src/lib/types/index.ts @@ -11,6 +11,5 @@ export * from './RequestDetails'; export * from './requestParams'; export * from './spendingPlanConfig'; export * from './registry'; -export * from './validation'; export * from './debug'; export * from './rateLimiter'; diff --git a/packages/relay/src/lib/types/validation.ts b/packages/relay/src/lib/types/validation.ts deleted file mode 100644 index 86e7a80c38..0000000000 --- a/packages/relay/src/lib/types/validation.ts +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/** - * Represents a validation rule for a parameter - */ -export interface IParamValidation { - /** - * The type of parameter to validate against - * Can be a ParamType enum value or a compound type string with pipe symbol (e.g., 'blockNumber|blockHash') - */ - type: ParamType | string; - - /** - * Whether the parameter is required - */ - required: boolean; - - /** - * Optional custom error message - */ - errorMessage?: string; -} - -/** - * Standard parameter types supported by the validator - * These are the basic types used in parameter validation schemas - */ -export enum ParamType { - // Basic types - ADDRESS = 'address', - BLOCK_NUMBER = 'blockNumber', - BLOCK_HASH = 'blockHash', - TRANSACTION_HASH = 'transactionHash', - TRANSACTION_ID = 'transactionId', - BLOCK_NUMBER_OR_HASH = 'blockNumber|blockHash', - TRANSACTION_HASH_OR_ID = 'transactionHash|transactionId', - - // Hex types - HEX = 'hex', - HEX64 = 'hex64', - - // Complex objects - TRANSACTION = 'transaction', - BLOCK_PARAMS = 'blockParams', - FILTER = 'filter', - - // Debug tracer types - TRACER_TYPE = 'tracerType', - TRACER_CONFIG = 'tracerConfig', - TRACER_CONFIG_WRAPPER = 'tracerConfigWrapper', - COMBINED_TRACER_TYPE = 'tracerType|tracerConfig|tracerConfigWrapper', - - // Basic JavaScript types - BOOLEAN = 'boolean', - ARRAY = 'array', -} - -/** - * Validation rule for a parameter type - */ -export interface ITypeValidator { - /** - * Validates the parameter value against this type - */ - validate: (value: any) => boolean; - - /** - * Error message when validation fails - */ - errorMessage: string; -} - -/** - * Registry of validation schemas for RPC methods - */ -export type ValidationSchemaRegistry = Map>; - -export type IMethodValidation = { - [index: number]: IMethodParamSchema; -}; - -export type IMethodParamSchema = { - type: string; - required?: boolean; -}; - -export type IObjectSchema = { - name: string; - properties: { - [key: string]: IObjectParamSchema; - }; - failOnEmpty?: boolean; - failOnUnexpectedParams?: boolean; - deleteUnknownProperties?: boolean; -}; - -export type IObjectParamSchema = { - type: string; - nullable: boolean; - required?: boolean; -}; - -export interface IObjectValidation { - get object(): T; - validate(): boolean; - name(): string; - checkForUnexpectedParams(): void; - deleteUnknownProperties(): void; -} - -export type ITypeValidation = { - test: (param: any) => boolean; - error: string; -}; diff --git a/packages/relay/src/lib/validators/constants.ts b/packages/relay/src/lib/validators/constants.ts index 61f9bd2f12..7036542080 100644 --- a/packages/relay/src/lib/validators/constants.ts +++ b/packages/relay/src/lib/validators/constants.ts @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 export const BASE_HEX_REGEX = '^0[xX][a-fA-F0-9]'; -export const ERROR_CODE = -32602; export const DEFAULT_HEX_ERROR = 'Expected 0x prefixed hexadecimal value'; export const EVEN_HEX_ERROR = `${DEFAULT_HEX_ERROR} with even length`; export const HASH_ERROR = 'Expected 0x prefixed string representing the hash (32 bytes)'; @@ -11,8 +10,6 @@ export const BLOCK_NUMBER_ERROR = export const BLOCK_PARAMS_ERROR = `Expected ${HASH_ERROR} in object, 0x prefixed hexadecimal block number, or the string "latest", "earliest" or "pending"`; export const BLOCK_HASH_ERROR = `Expected ${HASH_ERROR} of a block`; export const TRANSACTION_HASH_ERROR = `Expected ${HASH_ERROR} of a transaction`; -export const TRANSACTION_ID_ERROR = `Expected a transaction ID string in the format "shard.realm.num-sss-nnn" where sss are seconds and nnn are nanoseconds`; -export const TRANSACTION_ID_REGEX = /^(\d)\.(\d)\.(\d{1,10})-(\d{1,19})-(\d{1,9})$/; export const TOPIC_HASH_ERROR = `Expected ${HASH_ERROR} of a topic`; export const INVALID_BLOCK_HASH_TAG_NUMBER = 'The value passed is not a valid blockHash/blockNumber/blockTag value:'; export enum TracerType { diff --git a/packages/relay/src/lib/validators/index.ts b/packages/relay/src/lib/validators/index.ts index b9a1b44ea5..381dec5ddc 100644 --- a/packages/relay/src/lib/validators/index.ts +++ b/packages/relay/src/lib/validators/index.ts @@ -1,10 +1,57 @@ // SPDX-License-Identifier: Apache-2.0 import { predefined } from '../errors/JsonRpcError'; -import { IMethodValidation } from '../types/validation'; -import { validateParam } from './utils'; +import { TYPES } from './types'; +import { requiredIsMissing } from './utils'; -export function validateParams(params: any[], indexes: IMethodValidation) { +/** + * Represents a validation rule for a parameter + */ +export interface IParamValidation { + /** + * The type of parameter to validate against + * Can be a ParamType enum value or a compound type string with pipe symbol (e.g., 'blockNumber|blockHash') + */ + type: keyof typeof TYPES | (keyof typeof TYPES)[]; + + /** + * Whether the parameter is required + */ + required: boolean; +} + +/** + * This key is attached to method functions to store their validation rules. + */ +export const RPC_PARAM_VALIDATION_RULES_KEY = 'hedera-rpc-param-validation-rules'; + +/** + * Decorator that defines a schema for validating RPC method parameters + * + * @example + * ```typescript + * @rpcMethod + * @rpcParamValidationRules({ + * 0: { type: 'address', required: true }, + * 1: { type: 'blockNumber', required: true } + * }) + * getBalance(address: string, blockNumber: string, requestDetails: RequestDetails): Promise { + * // Implementation + * } + * ``` + * + * @param validationRules - Validation rules for method parameters + * @returns Method decorator function + */ +export function rpcParamValidationRules(validationRules: Record) { + return function (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) { + // Store validation rules directly on the function as a property + descriptor.value[RPC_PARAM_VALIDATION_RULES_KEY] = validationRules; + return descriptor; + }; +} + +export function validateParams(params: any[], indexes: { [index: number]: IParamValidation }) { if (params.length > Object.keys(indexes).length) { throw predefined.INVALID_PARAMETERS; } @@ -17,8 +64,38 @@ export function validateParams(params: any[], indexes: IMethodValidation) { } } -export * from './constants'; -export * from './types'; -export * from './objectTypes'; -export * from './utils'; -export * as Validator from '.'; +function validateParam(index: number | string, param: any, validation: IParamValidation): void { + const paramType = Array.isArray(validation.type) + ? validation.type.map((type) => TYPES[type]) + : TYPES[validation.type]; + + if (paramType === undefined) { + throw predefined.INTERNAL_ERROR(`Missing or unsupported param type '${validation.type}'`); + } + + if (requiredIsMissing(param, validation.required)) { + throw predefined.MISSING_REQUIRED_PARAMETER(index); + } else if (!validation.required && param === undefined) { + //if parameter is undefined and not required, no need to validate + //e.g estimateGas method, blockNumber is not required + return; + } + + if (param === null) { + throw predefined.INVALID_PARAMETER(index, `The value passed is not valid: ${param}.`); + } + + if (Array.isArray(paramType)) { + const results = paramType.map((validator) => validator.test(param)); + if (!results.includes(true)) { + const errorMessages = paramType.map((validator) => validator.error).join(' OR '); + throw predefined.INVALID_PARAMETER(index, `The value passed is not valid: ${param}. ${errorMessages}`); + } + } else if (!paramType.test(param)) { + const paramString = typeof param === 'object' ? JSON.stringify(param) : param; + throw predefined.INVALID_PARAMETER(index, `${paramType.error}, value: ${paramString}`); + } +} + +export { TYPES } from './types'; +export { validateEthSubscribeLogsParamObject } from './objectTypes'; diff --git a/packages/relay/src/lib/validators/objectTypes.ts b/packages/relay/src/lib/validators/objectTypes.ts index c585b10179..d3de922f58 100644 --- a/packages/relay/src/lib/validators/objectTypes.ts +++ b/packages/relay/src/lib/validators/objectTypes.ts @@ -1,15 +1,23 @@ // SPDX-License-Identifier: Apache-2.0 -import { TracerType } from '../constants'; import { predefined } from '../errors/JsonRpcError'; -import { - ICallTracerConfig, - IObjectSchema, - IObjectValidation, - IOpcodeLoggerConfig, - ITracerConfigWrapper, -} from '../types'; -import { Validator } from '.'; +import { validateObject } from './utils'; + +export type IObjectSchema = { + name: string; + properties: { + [prop: string]: IObjectParamSchema; + }; + failOnEmpty?: boolean; + failOnUnexpectedParams?: boolean; + deleteUnknownProperties?: boolean; +}; + +type IObjectParamSchema = { + type: string; + nullable: boolean; + required?: boolean; +}; export const OBJECTS_VALIDATIONS: { [key: string]: IObjectSchema } = { blockHashObject: { @@ -192,153 +200,34 @@ export const OBJECTS_VALIDATIONS: { [key: string]: IObjectSchema } = { }, }; -export class DefaultValidation implements IObjectValidation { - private readonly _object: T; - protected readonly schema: IObjectSchema; - - constructor(schema: IObjectSchema, object: T) { - this.schema = schema; - this._object = object; - } - - get object(): T { - return this._object; - } - - validate() { - if (this.schema.failOnUnexpectedParams) { - this.checkForUnexpectedParams(); - } - if (this.schema.deleteUnknownProperties) { - this.deleteUnknownProperties(); - } - return Validator.validateObject(this.object, this.schema); - } - - name() { - return this.schema.name; - } - - checkForUnexpectedParams() { - const expectedParams = Object.keys(this.schema.properties); - const actualParams = Object.keys(this.object); +export function validateSchema(schema: IObjectSchema, object: any) { + if (schema.failOnUnexpectedParams) { + const expectedParams = Object.keys(schema.properties); + const actualParams = Object.keys(object); const unknownParam = actualParams.find((param) => !expectedParams.includes(param)); if (unknownParam) { - throw predefined.INVALID_PARAMETER(`'${unknownParam}' for ${this.schema.name}`, `Unknown parameter`); + throw predefined.INVALID_PARAMETER(`'${unknownParam}' for ${schema.name}`, `Unknown parameter`); } } - - deleteUnknownProperties() { - const expectedParams = Object.keys(this.schema.properties); - const actualParams = Object.keys(this.object); + if (schema.deleteUnknownProperties) { + const expectedParams = Object.keys(schema.properties); + const actualParams = Object.keys(object); const unknownParams = actualParams.filter((param) => !expectedParams.includes(param)); for (const param of unknownParams) { - delete this.object[param]; + delete object[param]; } } + return validateObject(object, schema); } -export class TransactionObject extends DefaultValidation { - constructor(transaction: any) { - super(OBJECTS_VALIDATIONS.transaction, transaction); - } -} - -export class FilterObject extends DefaultValidation { - constructor(filter: any) { - super(OBJECTS_VALIDATIONS.filter, filter); +export function validateEthSubscribeLogsParamObject(param: any): asserts param is { address: string } { + const schema = OBJECTS_VALIDATIONS.ethSubscribeLogsParams; + const valid = validateSchema(schema, param); + // Check if the address is an array and has a length of 0 + // address and is not an empty array + if (valid && Array.isArray(param.address) && param.address.length === 0 && schema.properties.address.required) { + throw predefined.MISSING_REQUIRED_PARAMETER(`'address' for ${schema.name}`); } - validate() { - if (this.object.blockHash && (this.object.toBlock || this.object.fromBlock)) { - throw predefined.INVALID_PARAMETER(0, "Can't use both blockHash and toBlock/fromBlock"); - } - return super.validate(); - } -} - -export class BlockHashObject extends DefaultValidation { - constructor(param: any) { - super(OBJECTS_VALIDATIONS.blockHashObject, param); - } -} - -export class BlockNumberObject extends DefaultValidation { - constructor(param: any) { - super(OBJECTS_VALIDATIONS.blockNumberObject, param); - } -} - -export class EthSubscribeLogsParamsObject extends DefaultValidation { - constructor(param: any) { - super(OBJECTS_VALIDATIONS.ethSubscribeLogsParams, param); - } - - validate() { - const valid = super.validate(); - // address and is not an empty array - if ( - valid && - Array.isArray(this.object.address) && - this.object.address.length === 0 && - OBJECTS_VALIDATIONS.ethSubscribeLogsParams.properties.address.required - ) { - throw predefined.MISSING_REQUIRED_PARAMETER(`'address' for ${this.schema.name}`); - } - - return valid; - } -} - -export class CallTracerConfig extends DefaultValidation { - constructor(config: any) { - super(OBJECTS_VALIDATIONS.callTracerConfig, config); - } -} - -export class OpcodeLoggerConfig extends DefaultValidation { - constructor(config: any) { - super(OBJECTS_VALIDATIONS.opcodeLoggerConfig, config); - } -} - -export class TracerConfigWrapper extends DefaultValidation { - constructor(config: any) { - super(OBJECTS_VALIDATIONS.tracerConfigWrapper, config); - } - - validate() { - const valid = super.validate(); - - const { tracer, tracerConfig } = this.object; - - if (!tracerConfig) { - return valid; - } - - const callTracerKeys = Object.keys(OBJECTS_VALIDATIONS.callTracerConfig.properties); - const opcodeLoggerKeys = Object.keys(OBJECTS_VALIDATIONS.opcodeLoggerConfig.properties); - - const configKeys = Object.keys(tracerConfig); - const hasCallTracerKeys = configKeys.some((k) => callTracerKeys.includes(k)); - const hasOpcodeLoggerKeys = configKeys.some((k) => opcodeLoggerKeys.includes(k)); - - // we want to accept ICallTracerConfig only if the tracer is callTracer - // this config is not valid for opcodeLogger and vice versa - // accept only IOpcodeLoggerConfig with opcodeLogger tracer - if (hasCallTracerKeys && tracer === TracerType.OpcodeLogger) { - throw predefined.INVALID_PARAMETER( - 1, - `callTracer 'tracerConfig' for ${this.name()} is only valid when tracer=${TracerType.CallTracer}`, - ); - } - - if (hasOpcodeLoggerKeys && tracer !== TracerType.OpcodeLogger) { - throw predefined.INVALID_PARAMETER( - 1, - `opcodeLogger 'tracerConfig' for ${this.name()} is only valid when tracer=${TracerType.OpcodeLogger}`, - ); - } - return valid; - } + // return valid; } diff --git a/packages/relay/src/lib/validators/types.ts b/packages/relay/src/lib/validators/types.ts index 97950c93c3..3e4fe6eb43 100644 --- a/packages/relay/src/lib/validators/types.ts +++ b/packages/relay/src/lib/validators/types.ts @@ -1,25 +1,27 @@ // SPDX-License-Identifier: Apache-2.0 +import { predefined } from '../errors/JsonRpcError'; +import { ICallTracerConfig, IOpcodeLoggerConfig, ITracerConfig, ITracerConfigWrapper } from '../types'; import * as Constants from './constants'; -import { CallTracerConfig, OpcodeLoggerConfig, TracerConfigWrapper, Validator } from '.'; -import { ICallTracerConfig, IOpcodeLoggerConfig, ITracerConfig, ITracerConfigWrapper, ITypeValidation } from '../types'; +import { OBJECTS_VALIDATIONS, validateSchema } from './objectTypes'; +import { validateArray } from './utils'; -export const TYPES: { [key: string]: ITypeValidation } = { +export const TYPES = { address: { - test: (param: string) => new RegExp(Constants.BASE_HEX_REGEX + '{40}$').test(param), + test: (param) => new RegExp(Constants.BASE_HEX_REGEX + '{40}$').test(param), error: Constants.ADDRESS_ERROR, }, addressFilter: { test: (param: string | string[]) => { return Array.isArray(param) - ? Validator.validateArray(param.flat(), 'address') + ? validateArray(param.flat(), 'address') : new RegExp(Constants.BASE_HEX_REGEX + '{40}$').test(param); }, error: `${Constants.ADDRESS_ERROR} or an array of addresses`, }, array: { test: (param: any, innerType?: any) => { - return Array.isArray(param) ? Validator.validateArray(param, innerType) : false; + return Array.isArray(param) ? validateArray(param, innerType) : false; }, error: 'Expected Array', }, @@ -40,10 +42,11 @@ export const TYPES: { [key: string]: ITypeValidation } = { blockParams: { test: (param: any) => { if (Object.prototype.toString.call(param) === '[object Object]') { - if (param.hasOwnProperty('blockHash')) { - return new Validator.BlockHashObject(param).validate(); + if (Object.prototype.hasOwnProperty.call(param, 'blockHash')) { + // if (param.hasOwnProperty('blockHash')) { + return validateSchema(OBJECTS_VALIDATIONS.blockHashObject, param); } - return new Validator.BlockNumberObject(param).validate(); + return validateSchema(OBJECTS_VALIDATIONS.blockNumberObject, param); } return ( (/^0[xX]([1-9A-Fa-f]+[0-9A-Fa-f]{0,13}|0)$/.test(param) && Number.MAX_SAFE_INTEGER >= Number(param)) || @@ -55,7 +58,10 @@ export const TYPES: { [key: string]: ITypeValidation } = { filter: { test: (param: any) => { if (Object.prototype.toString.call(param) === '[object Object]') { - return new Validator.FilterObject(param).validate(); + if (param.blockHash && (param.toBlock || param.fromBlock)) { + throw predefined.INVALID_PARAMETER(0, "Can't use both blockHash and toBlock/fromBlock"); + } + return validateSchema(OBJECTS_VALIDATIONS.filter, param); } return false; @@ -80,14 +86,14 @@ export const TYPES: { [key: string]: ITypeValidation } = { }, topics: { test: (param: string[] | string[][]) => { - return Array.isArray(param) ? Validator.validateArray(param.flat(), 'topicHash') : false; + return Array.isArray(param) ? validateArray(param.flat(), 'topicHash') : false; }, error: `Expected an array or array of arrays containing ${Constants.HASH_ERROR} of a topic`, }, transaction: { test: (param: any) => { if (Object.prototype.toString.call(param) === '[object Object]') { - return new Validator.TransactionObject(param).validate(); + return validateSchema(OBJECTS_VALIDATIONS.transaction, param); } return false; @@ -98,10 +104,6 @@ export const TYPES: { [key: string]: ITypeValidation } = { test: (param: string) => new RegExp(Constants.BASE_HEX_REGEX + '{64}$').test(param), error: Constants.TRANSACTION_HASH_ERROR, }, - transactionId: { - test: (param: string) => new RegExp(Constants.TRANSACTION_ID_REGEX).test(param), - error: Constants.TRANSACTION_ID_ERROR, - }, tracerType: { test: (param: any): param is Constants.TracerType => typeof param === 'string' && @@ -113,7 +115,7 @@ export const TYPES: { [key: string]: ITypeValidation } = { callTracerConfig: { test: (param: any): param is ICallTracerConfig => { if (param && typeof param === 'object') { - return new CallTracerConfig(param).validate(); + return validateSchema(OBJECTS_VALIDATIONS.callTracerConfig, param); } return false; }, @@ -122,7 +124,7 @@ export const TYPES: { [key: string]: ITypeValidation } = { opcodeLoggerConfig: { test: (param: any): param is IOpcodeLoggerConfig => { if (param && typeof param === 'object') { - return new OpcodeLoggerConfig(param).validate(); + return validateSchema(OBJECTS_VALIDATIONS.opcodeLoggerConfig, param); } return false; }, @@ -143,10 +145,15 @@ export const TYPES: { [key: string]: ITypeValidation } = { tracerConfigWrapper: { test: (param: any): param is ITracerConfigWrapper => { if (param && typeof param === 'object') { - return new TracerConfigWrapper(param).validate(); + return validateSchema(OBJECTS_VALIDATIONS.tracerConfigWrapper, param); } return false; }, error: 'Expected TracerConfigWrapper which contains a valid TracerType and/or TracerConfig', }, +} satisfies { + [paramTypeName: string]: { + test: (param: any) => boolean; + error: string; + }; }; diff --git a/packages/relay/src/lib/validators/utils.ts b/packages/relay/src/lib/validators/utils.ts index 94adb29132..11f2e9733f 100644 --- a/packages/relay/src/lib/validators/utils.ts +++ b/packages/relay/src/lib/validators/utils.ts @@ -1,55 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 -import { Validator } from '.'; -import { IMethodParamSchema, IObjectSchema, ITypeValidation } from '../types'; import { JsonRpcError, predefined } from '../errors/JsonRpcError'; - -export function validateParam(index: number | string, param: any, validation: IMethodParamSchema): void { - const paramType = getParamType(validation.type); - - if (paramType === undefined) { - throw predefined.INTERNAL_ERROR(`Missing or unsupported param type '${validation.type}'`); - } - - if (requiredIsMissing(param, validation.required)) { - throw predefined.MISSING_REQUIRED_PARAMETER(index); - } else if (!validation.required && param === undefined) { - //if parameter is undefined and not required, no need to validate - //e.g estimateGas method, blockNumber is not required - return; - } - - if (param === null) { - throw predefined.INVALID_PARAMETER(index, `The value passed is not valid: ${param}.`); - } - - if (Array.isArray(paramType)) { - const results: any[] = []; - for (const validator of paramType) { - const result = validator.test(param); - results.push(result); - } - if (!results.some((item) => item === true)) { - const errorMessages = paramType.map((validator) => validator.error).join(' OR '); - throw predefined.INVALID_PARAMETER(index, `The value passed is not valid: ${param}. ${errorMessages}`); - } - } - - if (!Array.isArray(paramType)) { - if (!paramType.test(param)) { - const paramString = typeof param === 'object' ? JSON.stringify(param) : param; - throw predefined.INVALID_PARAMETER(index, `${paramType.error}, value: ${paramString}`); - } - } -} - -function getParamType(validationType: string): ITypeValidation | ITypeValidation[] { - if (validationType?.includes('|')) { - return validationType.split('|').map((type) => Validator.TYPES[type]); - } else { - return Validator.TYPES[validationType]; - } -} +import { IObjectSchema } from './objectTypes'; +import { TYPES } from './types'; export function validateObject(object: T, filters: IObjectSchema) { for (const property of Object.keys(filters.properties)) { @@ -62,13 +15,13 @@ export function validateObject(object: T, filters: IObje if (isValidAndNonNullableParam(param, validation.nullable)) { try { - const result = Validator.TYPES[validation.type].test(param); + const result = TYPES[validation.type].test(param); if (!result) { const paramString = typeof param === 'object' ? JSON.stringify(param) : param; throw predefined.INVALID_PARAMETER( `'${property}' for ${filters.name}`, - `${Validator.TYPES[validation.type].error}, value: ${paramString}`, + `${TYPES[validation.type].error}, value: ${paramString}`, ); } } catch (error: any) { @@ -76,7 +29,7 @@ export function validateObject(object: T, filters: IObje const paramString = typeof param === 'object' ? JSON.stringify(param) : param; throw predefined.INVALID_PARAMETER( `'${property}' for ${filters.name}`, - `${Validator.TYPES[validation.type].error}, value: ${paramString}`, + `${TYPES[validation.type].error}, value: ${paramString}`, ); } @@ -92,7 +45,7 @@ export function validateObject(object: T, filters: IObje export function validateArray(array: any[], innerType?: string): boolean { if (!innerType) return true; - const isInnerType = (element: any) => Validator.TYPES[innerType].test(element); + const isInnerType = (element: any) => TYPES[innerType].test(element); return array.every(isInnerType); } diff --git a/packages/relay/src/lib/web3.ts b/packages/relay/src/lib/web3.ts index 8688673e57..1f1a5530f5 100644 --- a/packages/relay/src/lib/web3.ts +++ b/packages/relay/src/lib/web3.ts @@ -4,8 +4,8 @@ import { keccak256 } from '@ethersproject/keccak256'; import { ConfigService } from '@hashgraph/json-rpc-config-service/dist/services'; import { Web3 } from '../index'; -import { rpcMethod, rpcParamValidationRules } from './decorators'; -import { ParamType } from './types'; +import { rpcMethod } from './decorators'; +import { rpcParamValidationRules } from './validators'; export class Web3Impl implements Web3 { constructor() {} @@ -33,7 +33,7 @@ export class Web3Impl implements Web3 { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ParamType.HEX, required: true }, + 0: { type: 'hex', required: true }, }) sha3(input: string): string { return keccak256(input); diff --git a/packages/relay/src/utils.ts b/packages/relay/src/utils.ts index ba091526e2..0fc5bea97e 100644 --- a/packages/relay/src/utils.ts +++ b/packages/relay/src/utils.ts @@ -162,6 +162,7 @@ export class Utils { return 'local'; } } + /** * Arranges parameters for an RPC method based on its layout configuration * diff --git a/packages/ws-server/src/utils/validators.ts b/packages/ws-server/src/utils/validators.ts index 73f7e4558c..b113460601 100644 --- a/packages/ws-server/src/utils/validators.ts +++ b/packages/ws-server/src/utils/validators.ts @@ -1,10 +1,10 @@ // SPDX-License-Identifier: Apache-2.0 -import constants from '@hashgraph/json-rpc-relay/dist/lib/constants'; import { JsonRpcError, predefined } from '@hashgraph/json-rpc-relay/dist'; import { MirrorNodeClient } from '@hashgraph/json-rpc-relay/dist/lib/clients'; -import { EthSubscribeLogsParamsObject } from '@hashgraph/json-rpc-relay/dist/lib/validators'; +import constants from '@hashgraph/json-rpc-relay/dist/lib/constants'; import { RequestDetails } from '@hashgraph/json-rpc-relay/dist/lib/types'; +import { validateEthSubscribeLogsParamObject } from '@hashgraph/json-rpc-relay/dist/lib/validators'; /** * Validates whether the provided address corresponds to a contract or token type. @@ -43,24 +43,23 @@ const validateIsContractOrTokenAddress = async ( * @param {RequestDetails} requestDetails - The request details for logging and tracking. */ export const validateSubscribeEthLogsParams = async ( - filters: any, + filters: unknown, mirrorNodeClient: MirrorNodeClient, requestDetails: RequestDetails, ) => { // validate address exists and is correct length and type // validate topics if exists and is array and each one is correct length and type // @todo: move EthSubscribeLogsParamsObject to ws-server package - const ethSubscribeLogsParams = new EthSubscribeLogsParamsObject(filters); - ethSubscribeLogsParams.validate(); + validateEthSubscribeLogsParamObject(filters); // validate address or addresses are an existing smart contract - if (ethSubscribeLogsParams.object.address) { - if (Array.isArray(ethSubscribeLogsParams.object.address)) { - for (const address of ethSubscribeLogsParams.object.address) { + if (filters.address) { + if (Array.isArray(filters.address)) { + for (const address of filters.address) { await validateIsContractOrTokenAddress(address, mirrorNodeClient, requestDetails); } } else { - await validateIsContractOrTokenAddress(ethSubscribeLogsParams.object.address, mirrorNodeClient, requestDetails); + await validateIsContractOrTokenAddress(filters.address, mirrorNodeClient, requestDetails); } } }; From f0247e98555bc415758655b142496023320c92e1 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Wed, 2 Jul 2025 18:18:13 +0300 Subject: [PATCH 02/16] refactors validator service Signed-off-by: Konstantina Blazhukova --- packages/relay/src/lib/debug.ts | 5 +-- packages/relay/src/lib/eth.ts | 1 - .../relay/src/lib/validators/objectTypes.ts | 40 ++++++++++++++++++- packages/ws-server/src/utils/validators.ts | 7 +++- 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/packages/relay/src/lib/debug.ts b/packages/relay/src/lib/debug.ts index 1c98079ff7..34066f58e0 100644 --- a/packages/relay/src/lib/debug.ts +++ b/packages/relay/src/lib/debug.ts @@ -105,9 +105,8 @@ export class DebugImpl implements Debug { */ @rpcMethod @rpcParamValidationRules({ - 0: { type: ['transactionHash'], required: true }, - 1: { type: ['tracerType', 'tracerConfig', 'tracerConfigWrapper'], required: false }, - 2: { type: 'tracerConfig', required: false }, + 0: { type: 'transactionHash', required: true }, + 1: { type: 'tracerConfigWrapper', required: true }, }) @rpcParamLayoutConfig(RPC_LAYOUT.custom((params) => [params[0], params[1]])) @cache(CacheService.getInstance(CACHE_LEVEL.L1)) diff --git a/packages/relay/src/lib/eth.ts b/packages/relay/src/lib/eth.ts index eda880a11d..370018a9b7 100644 --- a/packages/relay/src/lib/eth.ts +++ b/packages/relay/src/lib/eth.ts @@ -34,7 +34,6 @@ import { ITransactionReceipt, RequestDetails, } from './types'; -import { ParamType } from './types/validation'; import { rpcParamValidationRules } from './validators'; /** diff --git a/packages/relay/src/lib/validators/objectTypes.ts b/packages/relay/src/lib/validators/objectTypes.ts index d3de922f58..7d6cbc37df 100644 --- a/packages/relay/src/lib/validators/objectTypes.ts +++ b/packages/relay/src/lib/validators/objectTypes.ts @@ -1,5 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 +import { TracerType } from '../constants'; import { predefined } from '../errors/JsonRpcError'; import { validateObject } from './utils'; @@ -220,7 +221,7 @@ export function validateSchema(schema: IObjectSchema, object: any) { return validateObject(object, schema); } -export function validateEthSubscribeLogsParamObject(param: any): asserts param is { address: string } { +export function validateEthSubscribeLogsParamObject(param: any): boolean { const schema = OBJECTS_VALIDATIONS.ethSubscribeLogsParams; const valid = validateSchema(schema, param); // Check if the address is an array and has a length of 0 @@ -229,5 +230,40 @@ export function validateEthSubscribeLogsParamObject(param: any): asserts param i throw predefined.MISSING_REQUIRED_PARAMETER(`'address' for ${schema.name}`); } - // return valid; + return valid; +} + +export function validateTracerConfigWrapper(param: any): boolean { + const schema = OBJECTS_VALIDATIONS.tracerConfigWrapper; + const valid = validateSchema(schema, param); + const { tracer, tracerConfig } = param; + + if (!tracerConfig) { + return valid; + } + + const callTracerKeys = Object.keys(OBJECTS_VALIDATIONS.callTracerConfig.properties); + const opcodeLoggerKeys = Object.keys(OBJECTS_VALIDATIONS.opcodeLoggerConfig.properties); + + const configKeys = Object.keys(tracerConfig); + const hasCallTracerKeys = configKeys.some((k) => callTracerKeys.includes(k)); + const hasOpcodeLoggerKeys = configKeys.some((k) => opcodeLoggerKeys.includes(k)); + + // we want to accept ICallTracerConfig only if the tracer is callTracer + // this config is not valid for opcodeLogger and vice versa + // accept only IOpcodeLoggerConfig with opcodeLogger tracer + if (hasCallTracerKeys && tracer === TracerType.OpcodeLogger) { + throw predefined.INVALID_PARAMETER( + 1, + `callTracer 'tracerConfig' for ${schema.name} is only valid when tracer=${TracerType.CallTracer}`, + ); + } + + if (hasOpcodeLoggerKeys && tracer !== TracerType.OpcodeLogger) { + throw predefined.INVALID_PARAMETER( + 1, + `opcodeLogger 'tracerConfig' for ${schema.name} is only valid when tracer=${TracerType.OpcodeLogger}`, + ); + } + return valid; } diff --git a/packages/ws-server/src/utils/validators.ts b/packages/ws-server/src/utils/validators.ts index b113460601..0253773bbc 100644 --- a/packages/ws-server/src/utils/validators.ts +++ b/packages/ws-server/src/utils/validators.ts @@ -6,6 +6,11 @@ import constants from '@hashgraph/json-rpc-relay/dist/lib/constants'; import { RequestDetails } from '@hashgraph/json-rpc-relay/dist/lib/types'; import { validateEthSubscribeLogsParamObject } from '@hashgraph/json-rpc-relay/dist/lib/validators'; +interface EthSubscribeLogsParams { + address?: string | string[]; + topics?: any[]; +} + /** * Validates whether the provided address corresponds to a contract or token type. * Throws an error if the address is not a valid contract or token type or does not exist. @@ -43,7 +48,7 @@ const validateIsContractOrTokenAddress = async ( * @param {RequestDetails} requestDetails - The request details for logging and tracking. */ export const validateSubscribeEthLogsParams = async ( - filters: unknown, + filters: EthSubscribeLogsParams, mirrorNodeClient: MirrorNodeClient, requestDetails: RequestDetails, ) => { From 2063c7ab4c351e3393363fcc18d137a5266e51d9 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Thu, 3 Jul 2025 16:40:53 +0300 Subject: [PATCH 03/16] fixes tests Signed-off-by: Konstantina Blazhukova --- packages/relay/src/lib/eth.ts | 2 +- .../relay/src/lib/validators/constants.ts | 3 + packages/relay/src/lib/validators/index.ts | 9 +- .../lib/decorators/rpcParamSchema.spec.ts | 45 +- .../tests/lib/validators/validators.spec.ts | 719 +++++++++--------- .../server/tests/integration/server.spec.ts | 312 ++++---- 6 files changed, 530 insertions(+), 560 deletions(-) diff --git a/packages/relay/src/lib/eth.ts b/packages/relay/src/lib/eth.ts index 370018a9b7..7df8402fba 100644 --- a/packages/relay/src/lib/eth.ts +++ b/packages/relay/src/lib/eth.ts @@ -679,7 +679,7 @@ export class EthImpl implements Eth { @rpcParamValidationRules({ 0: { type: 'address', required: true }, 1: { type: 'hex64', required: true }, - 2: { type: ['blockNumber', 'blockHash'], required: false }, + 2: { type: ['blockNumber', 'blockHash'], required: true }, }) @rpcParamLayoutConfig(RPC_LAYOUT.custom((params) => [params[0], params[1], params[2]])) @cache(CacheService.getInstance(CACHE_LEVEL.L1), { diff --git a/packages/relay/src/lib/validators/constants.ts b/packages/relay/src/lib/validators/constants.ts index 7036542080..01c880f50a 100644 --- a/packages/relay/src/lib/validators/constants.ts +++ b/packages/relay/src/lib/validators/constants.ts @@ -2,6 +2,7 @@ export const BASE_HEX_REGEX = '^0[xX][a-fA-F0-9]'; export const DEFAULT_HEX_ERROR = 'Expected 0x prefixed hexadecimal value'; +export const ERROR_CODE = -32602; export const EVEN_HEX_ERROR = `${DEFAULT_HEX_ERROR} with even length`; export const HASH_ERROR = 'Expected 0x prefixed string representing the hash (32 bytes)'; export const ADDRESS_ERROR = 'Expected 0x prefixed string representing the address (20 bytes)'; @@ -11,6 +12,8 @@ export const BLOCK_PARAMS_ERROR = `Expected ${HASH_ERROR} in object, 0x prefixed export const BLOCK_HASH_ERROR = `Expected ${HASH_ERROR} of a block`; export const TRANSACTION_HASH_ERROR = `Expected ${HASH_ERROR} of a transaction`; export const TOPIC_HASH_ERROR = `Expected ${HASH_ERROR} of a topic`; +export const TRANSACTION_ID_ERROR = `Expected a transaction ID string in the format "shard.realm.num-sss-nnn" where sss are seconds and nnn are nanoseconds`; +export const TRANSACTION_ID_REGEX = /^(\d)\.(\d)\.(\d{1,10})-(\d{1,19})-(\d{1,9})$/; export const INVALID_BLOCK_HASH_TAG_NUMBER = 'The value passed is not a valid blockHash/blockNumber/blockTag value:'; export enum TracerType { CallTracer = 'callTracer', diff --git a/packages/relay/src/lib/validators/index.ts b/packages/relay/src/lib/validators/index.ts index 381dec5ddc..75ce037361 100644 --- a/packages/relay/src/lib/validators/index.ts +++ b/packages/relay/src/lib/validators/index.ts @@ -18,6 +18,11 @@ export interface IParamValidation { * Whether the parameter is required */ required: boolean; + + /** + * The error message to return if the parameter is invalid + */ + errorMessage?: string; } /** @@ -64,7 +69,7 @@ export function validateParams(params: any[], indexes: { [index: number]: IParam } } -function validateParam(index: number | string, param: any, validation: IParamValidation): void { +export function validateParam(index: number | string, param: any, validation: IParamValidation): void { const paramType = Array.isArray(validation.type) ? validation.type.map((type) => TYPES[type]) : TYPES[validation.type]; @@ -98,4 +103,6 @@ function validateParam(index: number | string, param: any, validation: IParamVal } export { TYPES } from './types'; +export { OBJECTS_VALIDATIONS } from './objectTypes'; export { validateEthSubscribeLogsParamObject } from './objectTypes'; +export * as Constants from './constants'; diff --git a/packages/relay/tests/lib/decorators/rpcParamSchema.spec.ts b/packages/relay/tests/lib/decorators/rpcParamSchema.spec.ts index 61d8e64724..fc09a9fbbe 100644 --- a/packages/relay/tests/lib/decorators/rpcParamSchema.spec.ts +++ b/packages/relay/tests/lib/decorators/rpcParamSchema.spec.ts @@ -5,11 +5,12 @@ import { describe, it } from 'mocha'; import sinon from 'sinon'; import { + IParamValidation, RPC_PARAM_VALIDATION_RULES_KEY, rpcParamValidationRules, -} from '../../../src/lib/decorators/rpcParamValidationRules.decorator'; -import { IParamValidation, ParamType } from '../../../src/lib/types'; -import * as validatorUtils from '../../../src/lib/validators/utils'; + validateParam, +} from '../../../src/lib/validators'; +import * as validator from '../../../src/lib/validators'; describe('rpcParamValidationRules decorator', () => { // Reset sinon after each test @@ -21,8 +22,8 @@ describe('rpcParamValidationRules decorator', () => { class TestClass { // @ts-ignore @rpcParamValidationRules({ - 0: { type: ParamType.ADDRESS, required: true }, - 1: { type: ParamType.BLOCK_NUMBER, required: false }, + 0: { type: 'address', required: true }, + 1: { type: 'blockNumber', required: false }, }) addressAndBlockMethod(address: string, blockNumber?: string) { return `${address}-${blockNumber || 'latest'}`; @@ -30,8 +31,8 @@ describe('rpcParamValidationRules decorator', () => { // @ts-ignore @rpcParamValidationRules({ - 0: { type: ParamType.TRANSACTION_HASH, required: true }, - 1: { type: ParamType.BOOLEAN, required: false, errorMessage: 'Custom error message' }, + 0: { type: 'transactionHash', required: true }, + 1: { type: 'boolean', required: false, errorMessage: 'Custom error message' }, }) customErrorMethod(txHash: string, fullTx: boolean = false) { return `${txHash}-${fullTx}`; @@ -51,14 +52,14 @@ describe('rpcParamValidationRules decorator', () => { it('should add RPC_PARAM_VALIDATION_RULES_KEY to decorated methods', () => { const addressSchema = testInstance.addressAndBlockMethod[RPC_PARAM_VALIDATION_RULES_KEY]; expect(addressSchema).to.be.an('object'); - expect(addressSchema[0].type).to.equal(ParamType.ADDRESS); + expect(addressSchema[0].type).to.equal('address'); expect(addressSchema[0].required).to.be.true; - expect(addressSchema[1].type).to.equal(ParamType.BLOCK_NUMBER); + expect(addressSchema[1].type).to.equal('blockNumber'); expect(addressSchema[1].required).to.be.false; const customSchema = testInstance.customErrorMethod[RPC_PARAM_VALIDATION_RULES_KEY]; expect(customSchema).to.be.an('object'); - expect(customSchema[0].type).to.equal(ParamType.TRANSACTION_HASH); + expect(customSchema[0].type).to.equal('transactionHash'); expect(customSchema[1].errorMessage).to.equal('Custom error message'); expect(testInstance.regularMethod[RPC_PARAM_VALIDATION_RULES_KEY]).to.be.undefined; @@ -78,15 +79,15 @@ describe('rpcParamValidationRules decorator', () => { beforeEach(() => { // Create a stub for the validateParam function from validators/utils - validateParamStub = sinon.stub(validatorUtils, 'validateParam'); + validateParamStub = sinon.stub(validator, 'validateParam'); }); it('should allow schema retrieval for validation', () => { class TestValidationClass { // @ts-ignore @rpcParamValidationRules({ - 0: { type: ParamType.ADDRESS, required: true }, - 1: { type: ParamType.BLOCK_NUMBER, required: false }, + 0: { type: 'address', required: true }, + 1: { type: 'blockNumber', required: false }, }) testMethod(address: string, blockNumber?: string) { return `${address}-${blockNumber || 'latest'}`; @@ -106,7 +107,7 @@ describe('rpcParamValidationRules decorator', () => { // Simulate validation with the schema for (const [index, param] of params.entries()) { if (schema[index]) { - validatorUtils.validateParam(index, param, schema[index]); + validateParam(index, param, schema[index]); } } @@ -119,9 +120,9 @@ describe('rpcParamValidationRules decorator', () => { describe('Schema structure', () => { it('should support various parameter types', () => { const schema: Record = { - 0: { type: ParamType.ADDRESS, required: true }, - 1: { type: ParamType.BLOCK_NUMBER_OR_HASH, required: false }, - 2: { type: ParamType.HEX, required: true, errorMessage: 'Must be hex' }, + 0: { type: 'address', required: true }, + 1: { type: ['blockNumber', 'blockHash'], required: false }, + 2: { type: 'hex', required: true, errorMessage: 'Must be hex' }, }; class TestTypeClass { @@ -136,14 +137,14 @@ describe('rpcParamValidationRules decorator', () => { const appliedSchema = instance.testMethod[RPC_PARAM_VALIDATION_RULES_KEY]; // Verify all schema properties were correctly applied - expect(appliedSchema[0].type).to.equal(ParamType.ADDRESS); - expect(appliedSchema[1].type).to.equal(ParamType.BLOCK_NUMBER_OR_HASH); - expect(appliedSchema[2].type).to.equal(ParamType.HEX); + expect(appliedSchema[0].type).to.equal('address'); + expect(appliedSchema[1].type).to.deep.equal(['blockNumber', 'blockHash']); + expect(appliedSchema[2].type).to.equal('hex'); expect(appliedSchema[2].errorMessage).to.equal('Must be hex'); }); it('should support custom type strings', () => { - const customType = 'custom|type|string'; + const customType = ['custom', 'type', 'string']; class TestCustomTypeClass { // @ts-ignore @@ -174,7 +175,7 @@ describe('rpcParamValidationRules decorator', () => { @mockDecorator // @ts-ignore @rpcParamValidationRules({ - 0: { type: ParamType.ADDRESS, required: true }, + 0: { type: 'address', required: true }, }) testMethod(address: string) { return address; diff --git a/packages/relay/tests/lib/validators/validators.spec.ts b/packages/relay/tests/lib/validators/validators.spec.ts index 258dbb39e2..8151808757 100644 --- a/packages/relay/tests/lib/validators/validators.spec.ts +++ b/packages/relay/tests/lib/validators/validators.spec.ts @@ -1,8 +1,10 @@ // SPDX-License-Identifier: Apache-2.0 import { expect } from 'chai'; -import { OBJECTS_VALIDATIONS, TracerType, TransactionObject, Validator } from '../../../src/lib/validators'; +import { OBJECTS_VALIDATIONS, TYPES, validateParams } from '../../../src/lib/validators'; import * as Constants from '../../../src/lib/validators/constants'; +import { validateSchema } from '../../../src/lib/validators/objectTypes'; +import { isValidAndNonNullableParam, validateObject } from '../../../src/lib/validators/utils'; describe('Validator', async () => { function expectInvalidParam(index: number | string, message: string, paramValue?: string) { @@ -21,46 +23,40 @@ describe('Validator', async () => { const validation = { 0: { type: 'address' } }; it('throws an error if address hash is smaller than 20bytes', async () => { - expect(() => Validator.validateParams(['0x4422E9088662'], validation)).to.throw( - expectInvalidParam(0, Validator.ADDRESS_ERROR, '0x4422E9088662'), + expect(() => validateParams(['0x4422E9088662'], validation)).to.throw( + expectInvalidParam(0, Constants.ADDRESS_ERROR, '0x4422E9088662'), ); }); it('throws an error if address is larger than 20bytes', async () => { - expect(() => Validator.validateParams(['0x4422E9088662c44604189B2aA3ae8eE282fceBB7b7b7'], validation)).to.throw( - expectInvalidParam(0, Validator.ADDRESS_ERROR, '0x4422E9088662c44604189B2aA3ae8eE282fceBB7b7b7'), + expect(() => validateParams(['0x4422E9088662c44604189B2aA3ae8eE282fceBB7b7b7'], validation)).to.throw( + expectInvalidParam(0, Constants.ADDRESS_ERROR, '0x4422E9088662c44604189B2aA3ae8eE282fceBB7b7b7'), ); }); it('throws an error if address is NOT 0x prefixed', async () => { - expect(() => Validator.validateParams(['4422E9088662c44604189B2aA3ae8eE282fceBB7'], validation)).to.throw( - expectInvalidParam(0, Validator.ADDRESS_ERROR, '4422E9088662c44604189B2aA3ae8eE282fceBB7'), + expect(() => validateParams(['4422E9088662c44604189B2aA3ae8eE282fceBB7'], validation)).to.throw( + expectInvalidParam(0, Constants.ADDRESS_ERROR, '4422E9088662c44604189B2aA3ae8eE282fceBB7'), ); }); it('throws an error if address is other type', async () => { - expect(() => Validator.validateParams(['random string'], validation)).to.throw( - expectInvalidParam(0, Validator.ADDRESS_ERROR, 'random string'), - ); - expect(() => Validator.validateParams(['123'], validation)).to.throw( - expectInvalidParam(0, Validator.ADDRESS_ERROR, '123'), - ); - expect(() => Validator.validateParams([[]], validation)).to.throw( - expectInvalidParam(0, Validator.ADDRESS_ERROR, ''), - ); - expect(() => Validator.validateParams([{}], validation)).to.throw( - expectInvalidParam(0, Validator.ADDRESS_ERROR, '{}'), + expect(() => validateParams(['random string'], validation)).to.throw( + expectInvalidParam(0, Constants.ADDRESS_ERROR, 'random string'), ); + expect(() => validateParams(['123'], validation)).to.throw(expectInvalidParam(0, Constants.ADDRESS_ERROR, '123')); + expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, Constants.ADDRESS_ERROR, '')); + expect(() => validateParams([{}], validation)).to.throw(expectInvalidParam(0, Constants.ADDRESS_ERROR, '{}')); }); it('does not throw an error if address is valid', async () => { - const result = Validator.validateParams(['0x4422E9088662c44604189B2aA3ae8eE282fceBB7'], validation); + const result = validateParams(['0x4422E9088662c44604189B2aA3ae8eE282fceBB7'], validation); expect(result).to.eq(undefined); }); it('does not throw an error if address is long-zero address', async () => { - const result = Validator.validateParams(['0x0000000000000000000000000000000000000408'], validation); + const result = validateParams(['0x0000000000000000000000000000000000000408'], validation); expect(result).to.eq(undefined); }); @@ -68,19 +64,19 @@ describe('Validator', async () => { describe('validates Array type correctly', async () => { const validation = { 0: { type: 'array' } }; - const error = Validator.TYPES['array'].error; + const error = TYPES['array'].error; it('throws an error if the param is not an array', async () => { - expect(() => Validator.validateParams(['random string'], validation)).to.throw( + expect(() => validateParams(['random string'], validation)).to.throw( expectInvalidParam(0, error, 'random string'), ); - expect(() => Validator.validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); - expect(() => Validator.validateParams([true], validation)).to.throw(expectInvalidParam(0, error, 'true')); - expect(() => Validator.validateParams([{}], validation)).to.throw(expectInvalidParam(0, error, '{}')); + expect(() => validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); + expect(() => validateParams([true], validation)).to.throw(expectInvalidParam(0, error, 'true')); + expect(() => validateParams([{}], validation)).to.throw(expectInvalidParam(0, error, '{}')); }); it('does not throw an error if param is array', async () => { - expect(Validator.validateParams([['0x1']], validation)).to.eq(undefined); + expect(validateParams([['0x1']], validation)).to.eq(undefined); }); }); @@ -88,21 +84,18 @@ describe('Validator', async () => { const validation = { 0: { type: 'blockHash' } }; it('throws an error if block hash is smaller than 32bytes', async () => { - expect(() => Validator.validateParams(['0xdec54931fcfe'], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_HASH_ERROR, '0xdec54931fcfe'), + expect(() => validateParams(['0xdec54931fcfe'], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_HASH_ERROR, '0xdec54931fcfe'), ); }); it('throws an error if block hash is larger than 32bytes', async () => { expect(() => - Validator.validateParams( - ['0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8a8a8'], - validation, - ), + validateParams(['0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8a8a8'], validation), ).to.throw( expectInvalidParam( 0, - Validator.BLOCK_HASH_ERROR, + Constants.BLOCK_HASH_ERROR, '0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8a8a8', ), ); @@ -110,36 +103,29 @@ describe('Validator', async () => { it('throws an error if block hash is NOT 0x prefixed', async () => { expect(() => - Validator.validateParams(['dec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8a8a8'], validation), + validateParams(['dec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8a8a8'], validation), ).to.throw( expectInvalidParam( 0, - Validator.BLOCK_HASH_ERROR, + Constants.BLOCK_HASH_ERROR, 'dec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8a8a8', ), ); }); it('throws an error if block hash is other type', async () => { - expect(() => Validator.validateParams(['string'], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_HASH_ERROR, 'string'), + expect(() => validateParams(['string'], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_HASH_ERROR, 'string'), ); - expect(() => Validator.validateParams([123], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_HASH_ERROR, '123'), - ); - expect(() => Validator.validateParams([[]], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_HASH_ERROR, ''), - ); - expect(() => Validator.validateParams([{}], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_HASH_ERROR, '{}'), + expect(() => validateParams([123], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_HASH_ERROR, '123'), ); + expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, Constants.BLOCK_HASH_ERROR, '')); + expect(() => validateParams([{}], validation)).to.throw(expectInvalidParam(0, Constants.BLOCK_HASH_ERROR, '{}')); }); it('does not throw an error if block hash is valid', async () => { - const result = Validator.validateParams( - ['0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8'], - validation, - ); + const result = validateParams(['0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8'], validation); expect(result).to.eq(undefined); }); @@ -149,55 +135,53 @@ describe('Validator', async () => { const validation = { 0: { type: 'blockNumber' } }; it('throws error if block number is decimal', async () => { - expect(() => Validator.validateParams([123], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_NUMBER_ERROR, '123'), + expect(() => validateParams([123], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_NUMBER_ERROR, '123'), ); }); it('throws error if block number is NOT 0x prefixed hex', async () => { - expect(() => Validator.validateParams(['000f'], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_NUMBER_ERROR, '000f'), + expect(() => validateParams(['000f'], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_NUMBER_ERROR, '000f'), ); }); it('throws error if block number is hex with leading zeros digits', async () => { - expect(() => Validator.validateParams(['0x00000000000000a'], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_NUMBER_ERROR, '0x00000000000000a'), + expect(() => validateParams(['0x00000000000000a'], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_NUMBER_ERROR, '0x00000000000000a'), ); }); it('throws error if block number is greater than (2^53 – 1)', async () => { - expect(() => Validator.validateParams(['0x20000000000007'], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_NUMBER_ERROR, '0x20000000000007'), + expect(() => validateParams(['0x20000000000007'], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_NUMBER_ERROR, '0x20000000000007'), ); }); it('throws error if block number contains invalid hex characters', async () => { - expect(() => Validator.validateParams(['0xg'], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_NUMBER_ERROR, '0xg'), + expect(() => validateParams(['0xg'], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_NUMBER_ERROR, '0xg'), ); }); it('throws error if block number is not correct tag', async () => { - expect(() => Validator.validateParams(['newest'], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_NUMBER_ERROR, 'newest'), + expect(() => validateParams(['newest'], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_NUMBER_ERROR, 'newest'), ); }); it('throws error if block number is random type', async () => { - expect(() => Validator.validateParams(['string'], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_NUMBER_ERROR, 'string'), + expect(() => validateParams(['string'], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_NUMBER_ERROR, 'string'), ); - expect(() => Validator.validateParams([[]], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_NUMBER_ERROR, ''), - ); - expect(() => Validator.validateParams([{}], validation)).to.throw( - expectInvalidParam(0, Validator.BLOCK_NUMBER_ERROR, '{}'), + expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, Constants.BLOCK_NUMBER_ERROR, '')); + expect(() => validateParams([{}], validation)).to.throw( + expectInvalidParam(0, Constants.BLOCK_NUMBER_ERROR, '{}'), ); }); it('does not throw error when block number is valid hex', async () => { - const result = Validator.validateParams(['0xf'], validation); + const result = validateParams(['0xf'], validation); expect(result).to.eq(undefined); }); @@ -205,126 +189,126 @@ describe('Validator', async () => { it('does not throw error when block number is valid tag', async () => { const validation = { 0: { type: 'blockNumber' } }; - expect(Validator.validateParams(['earliest'], validation)).to.eq(undefined); - expect(Validator.validateParams(['pending'], validation)).to.eq(undefined); - expect(Validator.validateParams(['latest'], validation)).to.eq(undefined); + expect(validateParams(['earliest'], validation)).to.eq(undefined); + expect(validateParams(['pending'], validation)).to.eq(undefined); + expect(validateParams(['latest'], validation)).to.eq(undefined); }); }); describe('validates boolean type correctly', async () => { const validation = { 0: { type: 'boolean', required: true } }; - const error = Validator.TYPES['boolean'].error; + const error = TYPES['boolean'].error; it('throws an error if param is string', async () => { - expect(() => Validator.validateParams(['true'], validation)).to.throw(expectInvalidParam(0, error, 'true')); - expect(() => Validator.validateParams(['false'], validation)).to.throw(expectInvalidParam(0, error, 'false')); + expect(() => validateParams(['true'], validation)).to.throw(expectInvalidParam(0, error, 'true')); + expect(() => validateParams(['false'], validation)).to.throw(expectInvalidParam(0, error, 'false')); }); it('throws an error if param is other type of truthy or falsy value', async () => { - expect(() => Validator.validateParams([1], validation)).to.throw(expectInvalidParam(0, error, '1')); - expect(() => Validator.validateParams([2], validation)).to.throw(expectInvalidParam(0, error, '2')); + expect(() => validateParams([1], validation)).to.throw(expectInvalidParam(0, error, '1')); + expect(() => validateParams([2], validation)).to.throw(expectInvalidParam(0, error, '2')); }); it('throws an error if param is another type', async () => { - expect(() => Validator.validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); - expect(() => Validator.validateParams(['0x1'], validation)).to.throw(expectInvalidParam(0, error, '0x1')); - expect(() => Validator.validateParams([[]], validation)).to.throw(expectInvalidParam(0, error, '')); - expect(() => Validator.validateParams([{}], validation)).to.throw(expectInvalidParam(0, error, '{}')); + expect(() => validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); + expect(() => validateParams(['0x1'], validation)).to.throw(expectInvalidParam(0, error, '0x1')); + expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, error, '')); + expect(() => validateParams([{}], validation)).to.throw(expectInvalidParam(0, error, '{}')); }); }); - describe('validates Filter Object type correctly', async () => { - const validation = { 0: { type: 'filter', required: true } }; - const error = Validator.TYPES['filter'].error; - const object = Validator.FilterObject.name; - - it('throws an error if the param is not an Object', async () => { - expect(() => Validator.validateParams(['0x1'], validation)).to.throw(expectInvalidParam(0, error, '0x1')); - expect(() => Validator.validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); - expect(() => Validator.validateParams([[]], validation)).to.throw(expectInvalidParam(0, error, '')); - expect(() => Validator.validateParams([true], validation)).to.throw(expectInvalidParam(0, error, 'true')); - }); - - it('throws an error if both blockHash and fromBlock/toBlock are used', async () => { - expect(() => - Validator.validateParams( - [{ blockHash: '0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8', fromBlock: 'latest' }], - validation, - ), - ).to.throw(expectInvalidParam(0, "Can't use both blockHash and toBlock/fromBlock")); - }); - - it('throws an error if the Filter Object properties are the wrong type', async () => { - expect(() => Validator.validateParams([{ blockHash: 123 }], validation)).to.throw( - expectInvalidObject('blockHash', Validator.BLOCK_HASH_ERROR, object, '123'), - ); - expect(() => Validator.validateParams([{ toBlock: 123 }], validation)).to.throw( - expectInvalidObject('toBlock', Validator.BLOCK_NUMBER_ERROR, object, '123'), - ); - expect(() => Validator.validateParams([{ fromBlock: 123 }], validation)).to.throw( - expectInvalidObject('fromBlock', Validator.BLOCK_NUMBER_ERROR, object, '123'), - ); - expect(() => Validator.validateParams([{ address: '0x1' }], validation)).to.throw( - expectInvalidObject('address', Validator.TYPES.addressFilter.error, object, '0x1'), - ); - expect(() => Validator.validateParams([{ topics: {} }], validation)).to.throw( - expectInvalidObject('topics', Validator.TYPES.topics.error, object, '{}'), - ); - expect(() => Validator.validateParams([{ topics: [123] }], validation)).to.throw( - expectInvalidObject('topics', Validator.TYPES.topics.error, object, '[123]'), - ); - }); - - it('does not throw an error for correct values', async () => { - expect( - Validator.validateParams( - [{ blockHash: '0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8' }], - validation, - ), - ).to.eq(undefined); - expect(Validator.validateParams([{ toBlock: '0x2' }], validation)).to.eq(undefined); - expect(Validator.validateParams([{ toBlock: 'latest' }], validation)).to.eq(undefined); - expect(Validator.validateParams([{ fromBlock: '0x1' }], validation)).to.eq(undefined); - expect(Validator.validateParams([{ fromBlock: 'earliest' }], validation)).to.eq(undefined); - expect(Validator.validateParams([{ address: '0x4422E9088662c44604189B2aA3ae8eE282fceBB7' }], validation)).to.eq( - undefined, - ); - expect( - Validator.validateParams( - [{ address: ['0x4422E9088662c44604189B2aA3ae8eE282fceBB7', '0x4422E9088662c44604189B2aA3ae8eE282fceBB8'] }], - validation, - ), - ).to.eq(undefined); - expect( - Validator.validateParams( - [{ topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'] }], - validation, - ), - ).to.eq(undefined); - expect( - Validator.validateParams( - [ - { - topics: [ - [ - '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', - '0xea443924a9fba8d643a00daf0a7956ebc37fa4e9da82f07f80c34f0f5217edf9', - ], - ], - }, - ], - validation, - ), - ).to.eq(undefined); - }); - }); + // describe('validates Filter Object type correctly', async () => { + // const validation = { 0: { type: 'filter', required: true } }; + // const error = TYPES['filter'].error; + // const object = OBJECTS_VALIDATIONS.FilterObject.name; + + // it('throws an error if the param is not an Object', async () => { + // expect(() => validateParams(['0x1'], validation)).to.throw(expectInvalidParam(0, error, '0x1')); + // expect(() => validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); + // expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, error, '')); + // expect(() => validateParams([true], validation)).to.throw(expectInvalidParam(0, error, 'true')); + // }); + + // it('throws an error if both blockHash and fromBlock/toBlock are used', async () => { + // expect(() => + // validateParams( + // [{ blockHash: '0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8', fromBlock: 'latest' }], + // validation, + // ), + // ).to.throw(expectInvalidParam(0, "Can't use both blockHash and toBlock/fromBlock")); + // }); + + // it('throws an error if the Filter Object properties are the wrong type', async () => { + // expect(() => validateParams([{ blockHash: 123 }], validation)).to.throw( + // expectInvalidObject('blockHash', Constants.BLOCK_HASH_ERROR, object, '123'), + // ); + // expect(() => validateParams([{ toBlock: 123 }], validation)).to.throw( + // expectInvalidObject('toBlock', Constants.BLOCK_NUMBER_ERROR, object, '123'), + // ); + // expect(() => validateParams([{ fromBlock: 123 }], validation)).to.throw( + // expectInvalidObject('fromBlock', Constants.BLOCK_NUMBER_ERROR, object, '123'), + // ); + // expect(() => validateParams([{ address: '0x1' }], validation)).to.throw( + // expectInvalidObject('address', TYPES.addressFilter.error, object, '0x1'), + // ); + // expect(() => validateParams([{ topics: {} }], validation)).to.throw( + // expectInvalidObject('topics', TYPES.topics.error, object, '{}'), + // ); + // expect(() => validateParams([{ topics: [123] }], validation)).to.throw( + // expectInvalidObject('topics', TYPES.topics.error, object, '[123]'), + // ); + // }); + + // it('does not throw an error for correct values', async () => { + // expect( + // validateParams( + // [{ blockHash: '0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8' }], + // validation, + // ), + // ).to.eq(undefined); + // expect(validateParams([{ toBlock: '0x2' }], validation)).to.eq(undefined); + // expect(validateParams([{ toBlock: 'latest' }], validation)).to.eq(undefined); + // expect(validateParams([{ fromBlock: '0x1' }], validation)).to.eq(undefined); + // expect(validateParams([{ fromBlock: 'earliest' }], validation)).to.eq(undefined); + // expect(validateParams([{ address: '0x4422E9088662c44604189B2aA3ae8eE282fceBB7' }], validation)).to.eq( + // undefined, + // ); + // expect( + // validateParams( + // [{ address: ['0x4422E9088662c44604189B2aA3ae8eE282fceBB7', '0x4422E9088662c44604189B2aA3ae8eE282fceBB8'] }], + // validation, + // ), + // ).to.eq(undefined); + // expect( + // validateParams( + // [{ topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'] }], + // validation, + // ), + // ).to.eq(undefined); + // expect( + // validateParams( + // [ + // { + // topics: [ + // [ + // '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', + // '0xea443924a9fba8d643a00daf0a7956ebc37fa4e9da82f07f80c34f0f5217edf9', + // ], + // ], + // }, + // ], + // validation, + // ), + // ).to.eq(undefined); + // }); + // }); describe('validates topics type correctly', async () => { const validation = { 0: { type: 'topics' } }; - const topicsError = Validator.TYPES['topics'].error; + const topicsError = TYPES['topics'].error; it('throws an error if topics contains hash smaller than 32bytes', async () => { expect(() => - Validator.validateParams( + validateParams( [['0xddf252ad1be2c89', '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef']], validation, ), @@ -339,7 +323,7 @@ describe('Validator', async () => { it('throws an error if topics contains hash larger than 32bytes', async () => { expect(() => - Validator.validateParams( + validateParams( [ [ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', @@ -359,7 +343,7 @@ describe('Validator', async () => { it('throws an error if topics contains hashes NOT 0x prefixed', async () => { expect(() => - Validator.validateParams( + validateParams( [ [ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', @@ -378,13 +362,13 @@ describe('Validator', async () => { }); it('throws an error if topics is not array', async () => { - expect(() => Validator.validateParams([123], validation)).to.throw(expectInvalidParam(0, topicsError, '123')); - expect(() => Validator.validateParams(['0x1'], validation)).to.throw(expectInvalidParam(0, topicsError, '0x1')); - expect(() => Validator.validateParams([{}], validation)).to.throw(expectInvalidParam(0, topicsError, '{}')); + expect(() => validateParams([123], validation)).to.throw(expectInvalidParam(0, topicsError, '123')); + expect(() => validateParams(['0x1'], validation)).to.throw(expectInvalidParam(0, topicsError, '0x1')); + expect(() => validateParams([{}], validation)).to.throw(expectInvalidParam(0, topicsError, '{}')); }); it('does not throw an error if topics param is valid', async () => { - const result = Validator.validateParams( + const result = validateParams( [['0x790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb55']], validation, ); @@ -393,7 +377,7 @@ describe('Validator', async () => { }); it('does not throw an error if topics param is null', async () => { - const result = Validator.validateParams( + const result = validateParams( [[null, '0x790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb55']], validation, ); @@ -402,7 +386,7 @@ describe('Validator', async () => { }); it('should handle nested topic arrays', async () => { - const result = Validator.validateParams( + const result = validateParams( [ [ ['0x790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb55'], @@ -416,7 +400,7 @@ describe('Validator', async () => { }); it('should allow topic to be null in nested topic arrays', async () => { - const result = Validator.validateParams( + const result = validateParams( [ [ [null, '0x790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb55'], @@ -431,7 +415,7 @@ describe('Validator', async () => { it('should correctly validate nested topic arrays', async () => { expect(() => - Validator.validateParams( + validateParams( [ [ ['0x790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb55'], @@ -454,21 +438,18 @@ describe('Validator', async () => { const validation = { 0: { type: 'topicHash' } }; it('throws an error if topic hash is smaller than 32bytes', async () => { - expect(() => Validator.validateParams(['0xddf252ad1be2c89'], validation)).to.throw( - expectInvalidParam(0, Validator.TOPIC_HASH_ERROR, '0xddf252ad1be2c89'), + expect(() => validateParams(['0xddf252ad1be2c89'], validation)).to.throw( + expectInvalidParam(0, Constants.TOPIC_HASH_ERROR, '0xddf252ad1be2c89'), ); }); it('throws an error if topic hash is larger than 32bytes', async () => { expect(() => - Validator.validateParams( - ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3effffff'], - validation, - ), + validateParams(['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3effffff'], validation), ).to.throw( expectInvalidParam( 0, - Validator.TOPIC_HASH_ERROR, + Constants.TOPIC_HASH_ERROR, '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3effffff', ), ); @@ -476,103 +457,93 @@ describe('Validator', async () => { it('throws an error if topic hash is NOT 0x prefixed', async () => { expect(() => - Validator.validateParams(['ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'], validation), + validateParams(['ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'], validation), ).to.throw( expectInvalidParam( 0, - Validator.TOPIC_HASH_ERROR, + Constants.TOPIC_HASH_ERROR, 'ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', ), ); }); it('throws an error if topic hash is other type', async () => { - expect(() => Validator.validateParams(['string'], validation)).to.throw( - expectInvalidParam(0, Validator.TOPIC_HASH_ERROR, 'string'), - ); - expect(() => Validator.validateParams([123], validation)).to.throw( - expectInvalidParam(0, Validator.TOPIC_HASH_ERROR, '123'), + expect(() => validateParams(['string'], validation)).to.throw( + expectInvalidParam(0, Constants.TOPIC_HASH_ERROR, 'string'), ); - expect(() => Validator.validateParams([[]], validation)).to.throw( - expectInvalidParam(0, Validator.TOPIC_HASH_ERROR, ''), - ); - expect(() => Validator.validateParams([{}], validation)).to.throw( - expectInvalidParam(0, Validator.TOPIC_HASH_ERROR, '{}'), + expect(() => validateParams([123], validation)).to.throw( + expectInvalidParam(0, Constants.TOPIC_HASH_ERROR, '123'), ); + expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, Constants.TOPIC_HASH_ERROR, '')); + expect(() => validateParams([{}], validation)).to.throw(expectInvalidParam(0, Constants.TOPIC_HASH_ERROR, '{}')); }); it('does not throw an error if topic hash is valid', async () => { - const result = Validator.validateParams( - ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'], - validation, - ); + const result = validateParams(['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'], validation); expect(result).to.eq(undefined); }); }); - describe('validates Transaction Object type correctly', async () => { - const validation = { 0: { type: 'transaction', required: true } }; - const error = Validator.TYPES['transaction'].error; - const object = Validator.TransactionObject.name; - - it('throws an error if the param is not an Object', async () => { - expect(() => Validator.validateParams(['string'], validation)).to.throw(expectInvalidParam(0, error, 'string')); - expect(() => Validator.validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); - expect(() => Validator.validateParams([[]], validation)).to.throw(expectInvalidParam(0, error, '')); - expect(() => Validator.validateParams([true], validation)).to.throw(expectInvalidParam(0, error, 'true')); - }); - - it('throws an error if the Transaction Object properties are the wrong type', async () => { - expect(() => Validator.validateParams([{ from: '0x1234' }], validation)).to.throw( - expectInvalidObject('from', Validator.ADDRESS_ERROR, object, '0x1234'), - ); - expect(() => Validator.validateParams([{ to: '0x1234' }], validation)).to.throw( - expectInvalidObject('to', Validator.ADDRESS_ERROR, object, '0x1234'), - ); - expect(() => Validator.validateParams([{ gas: 123 }], validation)).to.throw( - expectInvalidObject('gas', Validator.DEFAULT_HEX_ERROR, object, '123'), - ); - expect(() => Validator.validateParams([{ gasPrice: 123 }], validation)).to.throw( - expectInvalidObject('gasPrice', Validator.DEFAULT_HEX_ERROR, object, '123'), - ); - expect(() => Validator.validateParams([{ maxPriorityFeePerGas: 123 }], validation)).to.throw( - expectInvalidObject('maxPriorityFeePerGas', Validator.DEFAULT_HEX_ERROR, object, '123'), - ); - expect(() => Validator.validateParams([{ maxFeePerGas: 123 }], validation)).to.throw( - expectInvalidObject('maxFeePerGas', Validator.DEFAULT_HEX_ERROR, object, '123'), - ); - expect(() => Validator.validateParams([{ value: '123456' }], validation)).to.throw( - expectInvalidObject('value', Validator.DEFAULT_HEX_ERROR, object, '123456'), - ); - expect(() => Validator.validateParams([{ data: '123456' }], validation)).to.throw( - expectInvalidObject('data', Validator.EVEN_HEX_ERROR, object, '123456'), - ); - expect(() => Validator.validateParams([{ data: '0x1234567' }], validation)).to.throw( - expectInvalidObject('data', Validator.EVEN_HEX_ERROR, object, '0x1234567'), - ); - }); - }); + // describe('validates Transaction Object type correctly', async () => { + // const validation = { 0: { type: 'transaction', required: true } }; + // const error = TYPES['transaction'].error; + // const object = OBJECTS_VALIDATIONS.transactionObject.name; + + // it('throws an error if the param is not an Object', async () => { + // expect(() => validateParams(['string'], validation)).to.throw(expectInvalidParam(0, error, 'string')); + // expect(() => validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); + // expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, error, '')); + // expect(() => validateParams([true], validation)).to.throw(expectInvalidParam(0, error, 'true')); + // }); + + // it('throws an error if the Transaction Object properties are the wrong type', async () => { + // expect(() => validateParams([{ from: '0x1234' }], validation)).to.throw( + // expectInvalidObject('from', Constants.ADDRESS_ERROR, object, '0x1234'), + // ); + // expect(() => validateParams([{ to: '0x1234' }], validation)).to.throw( + // expectInvalidObject('to', Constants.ADDRESS_ERROR, object, '0x1234'), + // ); + // expect(() => validateParams([{ gas: 123 }], validation)).to.throw( + // expectInvalidObject('gas', Constants.DEFAULT_HEX_ERROR, object, '123'), + // ); + // expect(() => validateParams([{ gasPrice: 123 }], validation)).to.throw( + // expectInvalidObject('gasPrice', Constants.DEFAULT_HEX_ERROR, object, '123'), + // ); + // expect(() => validateParams([{ maxPriorityFeePerGas: 123 }], validation)).to.throw( + // expectInvalidObject('maxPriorityFeePerGas', Constants.DEFAULT_HEX_ERROR, object, '123'), + // ); + // expect(() => validateParams([{ maxFeePerGas: 123 }], validation)).to.throw( + // expectInvalidObject('maxFeePerGas', Constants.DEFAULT_HEX_ERROR, object, '123'), + // ); + // expect(() => validateParams([{ value: '123456' }], validation)).to.throw( + // expectInvalidObject('value', Constants.DEFAULT_HEX_ERROR, object, '123456'), + // ); + // expect(() => validateParams([{ data: '123456' }], validation)).to.throw( + // expectInvalidObject('data', Constants.EVEN_HEX_ERROR, object, '123456'), + // ); + // expect(() => validateParams([{ data: '0x1234567' }], validation)).to.throw( + // expectInvalidObject('data', Constants.EVEN_HEX_ERROR, object, '0x1234567'), + // ); + // }); + // }); describe('validates transactionHash type correctly', async () => { const validation = { 0: { type: 'transactionHash' } }; it('throws an error if transactionHash is smaller than 32bytes', async () => { - expect(() => Validator.validateParams(['0xdec54931fcfe'], validation)).to.throw( - expectInvalidParam(0, Validator.TRANSACTION_HASH_ERROR, '0xdec54931fcfe'), + expect(() => validateParams(['0xdec54931fcfe'], validation)).to.throw( + expectInvalidParam(0, Constants.TRANSACTION_HASH_ERROR, '0xdec54931fcfe'), ); }); it('throws an error if transactionHash is larger than 32bytes', async () => { expect(() => - Validator.validateParams( - ['0x790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb555555'], - validation, - ), + validateParams(['0x790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb555555'], validation), ).to.throw( expectInvalidParam( 0, - Validator.TRANSACTION_HASH_ERROR, + Constants.TRANSACTION_HASH_ERROR, '0x790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb555555', ), ); @@ -580,43 +551,40 @@ describe('Validator', async () => { it('throws an error if transactionHash is NOT 0x prefixed', async () => { expect(() => - Validator.validateParams(['790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb55'], validation), + validateParams(['790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb55'], validation), ).to.throw( expectInvalidParam( 0, - Validator.TRANSACTION_HASH_ERROR, + Constants.TRANSACTION_HASH_ERROR, '790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb55', ), ); }); it('throws an error if transactionHash is other type', async () => { - expect(() => Validator.validateParams(['string'], validation)).to.throw( - expectInvalidParam(0, Validator.TRANSACTION_HASH_ERROR, 'string'), + expect(() => validateParams(['string'], validation)).to.throw( + expectInvalidParam(0, Constants.TRANSACTION_HASH_ERROR, 'string'), ); - expect(() => Validator.validateParams([123], validation)).to.throw( - expectInvalidParam(0, Validator.TRANSACTION_HASH_ERROR, '123'), + expect(() => validateParams([123], validation)).to.throw( + expectInvalidParam(0, Constants.TRANSACTION_HASH_ERROR, '123'), ); - expect(() => Validator.validateParams([[]], validation)).to.throw( - expectInvalidParam(0, Validator.TRANSACTION_HASH_ERROR, ''), + expect(() => validateParams([[]], validation)).to.throw( + expectInvalidParam(0, Constants.TRANSACTION_HASH_ERROR, ''), ); - expect(() => Validator.validateParams([{}], validation)).to.throw( - expectInvalidParam(0, Validator.TRANSACTION_HASH_ERROR, '{}'), + expect(() => validateParams([{}], validation)).to.throw( + expectInvalidParam(0, Constants.TRANSACTION_HASH_ERROR, '{}'), ); }); it('does not throw an error if transactionHash is valid', async () => { - const result = Validator.validateParams( - ['0x790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb55'], - validation, - ); + const result = validateParams(['0x790673a87ac19773537b2553e1dc7c451f659e0f75d1b69a706ad42d25cbdb55'], validation); expect(result).to.eq(undefined); }); }); describeTests('tracerType', { - validCases: [TracerType.CallTracer, TracerType.OpcodeLogger], + validCases: [Constants.TracerType.CallTracer, Constants.TracerType.OpcodeLogger], invalidCases: [ { input: undefined, @@ -624,7 +592,7 @@ describe('Validator', async () => { }, { input: 'invalidType', - error: expectInvalidParam(0, Validator.TYPES.tracerType.error, 'invalidType'), + error: expectInvalidParam(0, TYPES.tracerType.error, 'invalidType'), }, ], }); @@ -634,7 +602,7 @@ describe('Validator', async () => { invalidCases: [ { input: { onlyTopCall: 'invalid' }, - error: expectInvalidParam("'onlyTopCall' for CallTracerConfig", Validator.TYPES.boolean.error, 'invalid'), + error: expectInvalidParam("'onlyTopCall' for CallTracerConfig", TYPES.boolean.error, 'invalid'), }, ], }); @@ -651,15 +619,15 @@ describe('Validator', async () => { invalidCases: [ { input: { enableMemory: 'invalid' }, - error: expectInvalidParam("'enableMemory' for OpcodeLoggerConfig", Validator.TYPES.boolean.error, 'invalid'), + error: expectInvalidParam("'enableMemory' for OpcodeLoggerConfig", TYPES.boolean.error, 'invalid'), }, { input: { disableStack: 'invalid' }, - error: expectInvalidParam("'disableStack' for OpcodeLoggerConfig", Validator.TYPES.boolean.error, 'invalid'), + error: expectInvalidParam("'disableStack' for OpcodeLoggerConfig", TYPES.boolean.error, 'invalid'), }, { input: { disableStorage: 'invalid' }, - error: expectInvalidParam("'disableStorage' for OpcodeLoggerConfig", Validator.TYPES.boolean.error, 'invalid'), + error: expectInvalidParam("'disableStorage' for OpcodeLoggerConfig", TYPES.boolean.error, 'invalid'), }, ], }); @@ -681,19 +649,19 @@ describe('Validator', async () => { invalidCases: [ { input: { enableMemory: 'invalid' }, - error: expectInvalidParam("'enableMemory' for OpcodeLoggerConfig", Validator.TYPES.boolean.error, 'invalid'), + error: expectInvalidParam("'enableMemory' for OpcodeLoggerConfig", TYPES.boolean.error, 'invalid'), }, { input: { disableStack: 'invalid' }, - error: expectInvalidParam("'disableStack' for OpcodeLoggerConfig", Validator.TYPES.boolean.error, 'invalid'), + error: expectInvalidParam("'disableStack' for OpcodeLoggerConfig", TYPES.boolean.error, 'invalid'), }, { input: { disableStorage: 'invalid' }, - error: expectInvalidParam("'disableStorage' for OpcodeLoggerConfig", Validator.TYPES.boolean.error, 'invalid'), + error: expectInvalidParam("'disableStorage' for OpcodeLoggerConfig", TYPES.boolean.error, 'invalid'), }, { input: { onlyTopCall: 'invalid' }, - error: expectInvalidParam("'onlyTopCall' for CallTracerConfig", Validator.TYPES.boolean.error, 'invalid'), + error: expectInvalidParam("'onlyTopCall' for CallTracerConfig", TYPES.boolean.error, 'invalid'), }, ], }); @@ -701,25 +669,25 @@ describe('Validator', async () => { describeTests('tracerConfigWrapper', { validCases: [ // CallTracerConfig - { tracer: TracerType.CallTracer, tracerConfig: { onlyTopCall: true }, unknownParam: true }, - { tracer: TracerType.CallTracer, tracerConfig: { onlyTopCall: true } }, - { tracer: TracerType.CallTracer, tracerConfig: {} }, - { tracer: TracerType.CallTracer }, + { tracer: Constants.TracerType.CallTracer, tracerConfig: { onlyTopCall: true }, unknownParam: true }, + { tracer: Constants.TracerType.CallTracer, tracerConfig: { onlyTopCall: true } }, + { tracer: Constants.TracerType.CallTracer, tracerConfig: {} }, + { tracer: Constants.TracerType.CallTracer }, { tracerConfig: { onlyTopCall: true } }, // OpcodeLoggerConfig { - tracer: TracerType.OpcodeLogger, + tracer: Constants.TracerType.OpcodeLogger, tracerConfig: { enableMemory: true, disableStack: false, disableStorage: true, unknownParam: true }, }, { - tracer: TracerType.OpcodeLogger, + tracer: Constants.TracerType.OpcodeLogger, tracerConfig: { enableMemory: true, disableStack: false, disableStorage: true }, }, - { tracer: TracerType.OpcodeLogger, tracerConfig: { enableMemory: true } }, - { tracer: TracerType.OpcodeLogger, tracerConfig: { disableStack: false } }, - { tracer: TracerType.OpcodeLogger, tracerConfig: { disableStorage: true } }, - { tracer: TracerType.OpcodeLogger, tracerConfig: {} }, - { tracer: TracerType.OpcodeLogger }, + { tracer: Constants.TracerType.OpcodeLogger, tracerConfig: { enableMemory: true } }, + { tracer: Constants.TracerType.OpcodeLogger, tracerConfig: { disableStack: false } }, + { tracer: Constants.TracerType.OpcodeLogger, tracerConfig: { disableStorage: true } }, + { tracer: Constants.TracerType.OpcodeLogger, tracerConfig: {} }, + { tracer: Constants.TracerType.OpcodeLogger }, { tracerConfig: { enableMemory: true, disableStack: false, disableStorage: true } }, // Empty object {}, @@ -727,37 +695,37 @@ describe('Validator', async () => { invalidCases: [ { input: { tracer: 'invalid', tracerConfig: {} }, - error: expectInvalidParam("'tracer' for TracerConfigWrapper", Validator.TYPES.tracerType.error, 'invalid'), + error: expectInvalidParam("'tracer' for TracerConfigWrapper", TYPES.tracerType.error, 'invalid'), }, { - input: { tracer: TracerType.CallTracer, tracerConfig: { onlyTopCall: 'invalid' } }, + input: { tracer: Constants.TracerType.CallTracer, tracerConfig: { onlyTopCall: 'invalid' } }, error: expectInvalidParam( "'tracerConfig' for TracerConfigWrapper", - Validator.TYPES.tracerConfig.error, + TYPES.tracerConfig.error, JSON.stringify({ onlyTopCall: 'invalid' }), ), }, { - input: { tracer: TracerType.OpcodeLogger, tracerConfig: { enableMemory: 'invalid' } }, + input: { tracer: Constants.TracerType.OpcodeLogger, tracerConfig: { enableMemory: 'invalid' } }, error: expectInvalidParam( "'tracerConfig' for TracerConfigWrapper", - Validator.TYPES.tracerConfig.error, + TYPES.tracerConfig.error, JSON.stringify({ enableMemory: 'invalid' }), ), }, { - input: { tracer: TracerType.OpcodeLogger, tracerConfig: { disableStack: 'invalid' } }, + input: { tracer: Constants.TracerType.OpcodeLogger, tracerConfig: { disableStack: 'invalid' } }, error: expectInvalidParam( "'tracerConfig' for TracerConfigWrapper", - Validator.TYPES.tracerConfig.error, + TYPES.tracerConfig.error, JSON.stringify({ disableStack: 'invalid' }), ), }, { - input: { tracer: TracerType.OpcodeLogger, tracerConfig: { disableStorage: 'invalid' } }, + input: { tracer: Constants.TracerType.OpcodeLogger, tracerConfig: { disableStorage: 'invalid' } }, error: expectInvalidParam( "'tracerConfig' for TracerConfigWrapper", - Validator.TYPES.tracerConfig.error, + TYPES.tracerConfig.error, JSON.stringify({ disableStorage: 'invalid' }), ), }, @@ -768,7 +736,7 @@ describe('Validator', async () => { it('throws an error if validation type is wrong', async () => { const validation = { 0: { type: 'wrongType' } }; - expect(() => Validator.validateParams(['0x4422E9088662'], validation)).to.throw( + expect(() => validateParams(['0x4422E9088662'], validation)).to.throw( "Error invoking RPC: Missing or unsupported param type 'wrongType'", ); }); @@ -776,7 +744,7 @@ describe('Validator', async () => { it('throws an error if validation type is missing', async () => { const validation = { 0: { type: undefined as unknown as string } }; - expect(() => Validator.validateParams(['0x4422E9088662'], validation)).to.throw( + expect(() => validateParams(['0x4422E9088662'], validation)).to.throw( "Error invoking RPC: Missing or unsupported param type 'undefined'", ); }); @@ -784,13 +752,13 @@ describe('Validator', async () => { it('throws an error if passed params are more than defined validations', async () => { const validation = { 0: { type: 'boolean' } }; - expect(() => Validator.validateParams(['true', null], validation)).to.throw('Invalid params'); + expect(() => validateParams(['true', null], validation)).to.throw('Invalid params'); }); it('throws an error if validation type is unknown', async () => { const validation = { 0: { type: 'unknownType' } }; - expect(() => Validator.validateParams(['0x4422E9088662'], validation)).to.throw( + expect(() => validateParams(['0x4422E9088662'], validation)).to.throw( "Error invoking RPC: Missing or unsupported param type 'unknownType'", ); }); @@ -798,7 +766,7 @@ describe('Validator', async () => { it('throws an error if Filter Object param contains unexpected param', async () => { const validation = { 0: { type: 'filter' } }; - expect(() => Validator.validateParams([{ formBlock: '0x1' }], validation)).to.throw( + expect(() => validateParams([{ formBlock: '0x1' }], validation)).to.throw( expectUnknownParam('formBlock', 'FilterObject', 'Unknown parameter'), ); }); @@ -806,88 +774,87 @@ describe('Validator', async () => { it('does NOT throw an error if Transaction Object param contains unexpected param', async () => { const validation = { 0: { type: 'transaction' } }; - expect(() => Validator.validateParams([{ form: '0x1' }], validation)).to.not.throw; + expect(() => validateParams([{ form: '0x1' }], validation)).to.not.throw; }); it('deletes unknown properties of Transaction Object param', async () => { const transactionParam = { form: '0x1' }; const validation = { 0: { type: 'transaction' } }; - Validator.validateParams([transactionParam], validation); + validateParams([transactionParam], validation); expect(transactionParam).not.to.haveOwnProperty('form'); }); }); - describe('validates validateObject with transaction object', async () => { - const transactionFilterObject = new TransactionObject({ - from: '0xdd94180d1c8e069fc7e6760d5bf7dee477fe617b', - gasPrice: '0x0', - value: '0x0', - data: null, - }); - - it('returns true when transaction data is null and is nullable is true', async () => { - const result = Validator.validateObject(transactionFilterObject.object, { - ...OBJECTS_VALIDATIONS.transaction, - properties: { - ...OBJECTS_VALIDATIONS.transaction.properties, - data: { - type: 'hex', - nullable: true, - }, - }, - }); - - expect(result).to.be.true; - }); - - it('throws an error if Transaction Object data param is null and isNullable is false', async () => { - expect(() => - Validator.validateObject(transactionFilterObject.object, { - ...OBJECTS_VALIDATIONS.transaction, - properties: { - ...OBJECTS_VALIDATIONS.transaction.properties, - data: { - type: 'hex', - nullable: false, - }, - }, - }), - ).to.throw(expectInvalidObject('data', 'Expected 0x prefixed hexadecimal value', 'TransactionObject', 'null')); - }); - }); + // describe('validates validateObject with transaction object', async () => { + // const transactionFilterObject = new TransactionObject({ + // from: '0xdd94180d1c8e069fc7e6760d5bf7dee477fe617b', + // gasPrice: '0x0', + // value: '0x0', + // data: null, + // }); + + // it('returns true when transaction data is null and is nullable is true', async () => { + // const result = validateObject(transactionFilterObject.object, { + // ...OBJECTS_VALIDATIONS.transaction, + // properties: { + // ...OBJECTS_VALIDATIONS.transaction.properties, + // data: { + // type: 'hex', + // nullable: true, + // }, + // }, + // }); + + // expect(result).to.be.true; + // }); + + // it('throws an error if Transaction Object data param is null and isNullable is false', async () => { + // expect(() => + // validateObject(transactionFilterObject.object, { + // ...OBJECTS_VALIDATIONS.transaction, + // properties: { + // ...OBJECTS_VALIDATIONS.transaction.properties, + // data: { + // type: 'hex', + // nullable: false, + // }, + // }, + // }), + // ).to.throw(expectInvalidObject('data', 'Expected 0x prefixed hexadecimal value', 'TransactionObject', 'null')); + // }); + // }); describe('validates isValidAndNonNullableParam', async () => { it('returns false if transaction data is undefined and isnullable is true', async () => { - expect(Validator.isValidAndNonNullableParam(undefined, true)).to.be.false; + expect(isValidAndNonNullableParam(undefined, true)).to.be.false; }); it('returns false if transaction data is undefined and isnullable is false', async () => { - expect(Validator.isValidAndNonNullableParam(undefined, false)).to.be.false; + expect(isValidAndNonNullableParam(undefined, false)).to.be.false; }); it('returns false if transaction data is null and isnullable is true', async () => { - expect(Validator.isValidAndNonNullableParam(null, true)).to.be.false; + expect(isValidAndNonNullableParam(null, true)).to.be.false; }); it('returns false if transaction data is null and isnullable is false', async () => { - expect(Validator.isValidAndNonNullableParam(null, false)).to.be.true; + expect(isValidAndNonNullableParam(null, false)).to.be.true; }); it('returns false if transaction data is a valid 0x value and isnullable is false', async () => { - expect(Validator.isValidAndNonNullableParam('0x', false)).to.be.true; + expect(isValidAndNonNullableParam('0x', false)).to.be.true; }); it('returns false if transaction data is a valid 0x value and isnullable is true', async () => { - expect(Validator.isValidAndNonNullableParam('0x', true)).to.be.true; + expect(isValidAndNonNullableParam('0x', true)).to.be.true; }); }); describe('validates ethSubscribeLogsParams Object type correctly', async () => { it("throws an error if 'address' is null", async () => { expect(() => { - const validatorObject = new Validator.EthSubscribeLogsParamsObject({ address: null }); - validatorObject.validate(); + validateSchema(OBJECTS_VALIDATIONS.ethSubscribeLogsParams, { address: null }); }).to.throw( `Invalid parameter 'address' for EthSubscribeLogsParamsObject: Expected 0x prefixed string representing the address (20 bytes) or an array of addresses, value: null`, ); @@ -895,11 +862,10 @@ describe('Validator', async () => { it("throws an error if 'topics' values are not 0x prefixed", async () => { expect(() => { - const validatorObject = new Validator.EthSubscribeLogsParamsObject({ + validateSchema(OBJECTS_VALIDATIONS.ethSubscribeLogsParams, { address: '0xea4168c4cbb733ec22dea4a4bfc5f74b6fe27816', topics: ['NotHEX'], }); - validatorObject.validate(); }).to.throw( `Invalid parameter 'topics' for EthSubscribeLogsParamsObject: Expected an array or array of arrays containing ${Constants.HASH_ERROR} of a topic, value: ["NotHEX"]`, ); @@ -907,11 +873,10 @@ describe('Validator', async () => { it("throws an error if 'topics' values are null", async () => { expect(() => { - const validatorObject = new Validator.EthSubscribeLogsParamsObject({ + validateSchema(OBJECTS_VALIDATIONS.ethSubscribeLogsParams, { address: '0xea4168c4cbb733ec22dea4a4bfc5f74b6fe27816', topics: null, }); - validatorObject.validate(); }).to.throw( `Invalid parameter 'topics' for EthSubscribeLogsParamsObject: Expected an array or array of arrays containing ${Constants.HASH_ERROR} of a topic, value: null`, ); @@ -920,14 +885,13 @@ describe('Validator', async () => { it("does not throw an error if 'topics' values are 0x prefixed and 32 bytes", async () => { let errorOccurred = false; try { - const validatorObject = new Validator.EthSubscribeLogsParamsObject({ + validateSchema(OBJECTS_VALIDATIONS.ethSubscribeLogsParams, { address: '0xea4168c4cbb733ec22dea4a4bfc5f74b6fe27816', topics: [ '0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902', '0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902', ], }); - validatorObject.validate(); } catch (error) { errorOccurred = true; } @@ -938,11 +902,10 @@ describe('Validator', async () => { it("does not throw an error if 'topics' value is empty array", async () => { let errorOccurred = false; try { - const validatorObject = new Validator.EthSubscribeLogsParamsObject({ + validateSchema(OBJECTS_VALIDATIONS.ethSubscribeLogsParams, { address: '0xea4168c4cbb733ec22dea4a4bfc5f74b6fe27816', topics: [], }); - validatorObject.validate(); } catch (error) { errorOccurred = true; } @@ -953,11 +916,10 @@ describe('Validator', async () => { it("does not throw an error if 'address' is valid and topics is undefined", async () => { let errorOccurred = false; try { - const validatorObject = new Validator.EthSubscribeLogsParamsObject({ + validateSchema(OBJECTS_VALIDATIONS.ethSubscribeLogsParams, { address: '0xea4168c4cbb733ec22dea4a4bfc5f74b6fe27816', topics: undefined, }); - validatorObject.validate(); } catch (error) { errorOccurred = true; } @@ -968,10 +930,9 @@ describe('Validator', async () => { it("does not throw an error if 'address' is valid and topics is missing", async () => { let errorOccurred = false; try { - const validatorObject = new Validator.EthSubscribeLogsParamsObject({ + validateSchema(OBJECTS_VALIDATIONS.ethSubscribeLogsParams, { address: '0xea4168c4cbb733ec22dea4a4bfc5f74b6fe27816', }); - validatorObject.validate(); } catch (error) { errorOccurred = true; } @@ -982,10 +943,9 @@ describe('Validator', async () => { it("does not throw an error if 'address' is valid array and topics is missing", async () => { let errorOccurred = false; try { - const validatorObject = new Validator.EthSubscribeLogsParamsObject({ + validateSchema(OBJECTS_VALIDATIONS.ethSubscribeLogsParams, { address: ['0xea4168c4cbb733ec22dea4a4bfc5f74b6fe27816', '0xea4168c4cbb733ec22dea4a4bfc5f74b6fe27816'], }); - validatorObject.validate(); } catch (error) { errorOccurred = true; } @@ -996,7 +956,7 @@ describe('Validator', async () => { it("does not throw an error if 'address' is valid array and topics is valid array", async () => { let errorOccurred = false; try { - const validatorObject = new Validator.EthSubscribeLogsParamsObject({ + validateSchema(OBJECTS_VALIDATIONS.ethSubscribeLogsParams, { address: ['0xea4168c4cbb733ec22dea4a4bfc5f74b6fe27816', '0xea4168c4cbb733ec22dea4a4bfc5f74b6fe27816'], topics: [ '0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902', @@ -1004,7 +964,6 @@ describe('Validator', async () => { '0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902', ], }); - validatorObject.validate(); } catch (error) { errorOccurred = true; } @@ -1015,35 +974,35 @@ describe('Validator', async () => { describe('validates tracerConfig type correctly', () => { it('returns true for an empty object', () => { - expect(Validator.TYPES.tracerConfig.test({})).to.be.true; + expect(TYPES.tracerConfig.test({})).to.be.true; }); it('returns true for a valid call tracer config', () => { - expect(Validator.TYPES.tracerConfig.test({ onlyTopCall: true })).to.be.true; - expect(Validator.TYPES.tracerConfig.test({ onlyTopCall: false })).to.be.true; + expect(TYPES.tracerConfig.test({ onlyTopCall: true })).to.be.true; + expect(TYPES.tracerConfig.test({ onlyTopCall: false })).to.be.true; }); it('returns true for a valid opcode logger config', () => { - expect(Validator.TYPES.tracerConfig.test({ disableMemory: true })).to.be.true; - expect(Validator.TYPES.tracerConfig.test({ disableStack: true })).to.be.true; - expect(Validator.TYPES.tracerConfig.test({ disableStorage: true })).to.be.true; + expect(TYPES.tracerConfig.test({ disableMemory: true })).to.be.true; + expect(TYPES.tracerConfig.test({ disableStack: true })).to.be.true; + expect(TYPES.tracerConfig.test({ disableStorage: true })).to.be.true; }); it('returns false for an invalid config', () => { - expect(Validator.TYPES.tracerConfig.test({ invalidKey: true })).to.be.false; - expect(() => Validator.TYPES.tracerConfig.test({ onlyTopCall: 'true' })).to.throw( - expectInvalidParam("'onlyTopCall' for CallTracerConfig", Validator.TYPES.boolean.error, 'true'), + expect(TYPES.tracerConfig.test({ invalidKey: true })).to.be.false; + expect(() => TYPES.tracerConfig.test({ onlyTopCall: 'true' })).to.throw( + expectInvalidParam("'onlyTopCall' for CallTracerConfig", TYPES.boolean.error, 'true'), ); - expect(() => Validator.TYPES.tracerConfig.test({ disableMemory: 'true' })).to.throw( - expectInvalidParam("'disableMemory' for OpcodeLoggerConfig", Validator.TYPES.boolean.error, 'true'), + expect(() => TYPES.tracerConfig.test({ disableMemory: 'true' })).to.throw( + expectInvalidParam("'disableMemory' for OpcodeLoggerConfig", TYPES.boolean.error, 'true'), ); }); it('returns false for non-object values', () => { - expect(Validator.TYPES.tracerConfig.test(null)).to.be.false; - expect(Validator.TYPES.tracerConfig.test(undefined)).to.be.false; - expect(Validator.TYPES.tracerConfig.test(123)).to.be.false; - expect(Validator.TYPES.tracerConfig.test('string')).to.be.false; + expect(TYPES.tracerConfig.test(null)).to.be.false; + expect(TYPES.tracerConfig.test(undefined)).to.be.false; + expect(TYPES.tracerConfig.test(123)).to.be.false; + expect(TYPES.tracerConfig.test('string')).to.be.false; }); }); @@ -1053,13 +1012,13 @@ describe('Validator', async () => { tests.invalidCases.forEach(({ input, error }) => { it(`throws an error for input: ${JSON.stringify(input)}`, async () => { - expect(() => Validator.validateParams([input], validation)).to.throw(error); + expect(() => validateParams([input], validation)).to.throw(error); }); }); tests.validCases.forEach((input) => { it(`does not throw an error for input: ${JSON.stringify(input)}`, async () => { - expect(() => Validator.validateParams([input], validation)).to.not.throw; + expect(() => validateParams([input], validation)).to.not.throw; }); }); }); diff --git a/packages/server/tests/integration/server.spec.ts b/packages/server/tests/integration/server.spec.ts index 8c8728c552..20ddc407c8 100644 --- a/packages/server/tests/integration/server.spec.ts +++ b/packages/server/tests/integration/server.spec.ts @@ -9,8 +9,7 @@ import { MirrorNodeClient } from '@hashgraph/json-rpc-relay/dist/lib/clients'; import { TracerType } from '@hashgraph/json-rpc-relay/dist/lib/constants'; import { DebugImpl } from '@hashgraph/json-rpc-relay/dist/lib/debug'; import { CacheService } from '@hashgraph/json-rpc-relay/dist/lib/services/cacheService/cacheService'; -import { Validator } from '@hashgraph/json-rpc-relay/dist/lib/validators'; -import * as Constants from '@hashgraph/json-rpc-relay/dist/lib/validators'; +import { Constants, TYPES } from '@hashgraph/json-rpc-relay/dist/lib/validators'; import { CommonService } from '@hashgraph/json-rpc-relay/src/lib/services'; import Axios, { AxiosInstance } from 'axios'; import { expect } from 'chai'; @@ -807,7 +806,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -822,7 +821,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, 'Expected TransactionObject, value: 0x0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, 'Expected TransactionObject, value: 0x0'); } }); @@ -839,8 +838,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'to' for TransactionObject: ${Validator.ADDRESS_ERROR}, value: 0x1`, + Constants.ERROR_CODE, + `Invalid parameter 'to' for TransactionObject: ${Constants.ADDRESS_ERROR}, value: 0x1`, ); } }); @@ -858,8 +857,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'from' for TransactionObject: ${Validator.ADDRESS_ERROR}, value: 0x1`, + Constants.ERROR_CODE, + `Invalid parameter 'from' for TransactionObject: ${Constants.ADDRESS_ERROR}, value: 0x1`, ); } }); @@ -877,8 +876,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'gas' for TransactionObject: ${Validator.DEFAULT_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'gas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } }); @@ -896,8 +895,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'gasPrice' for TransactionObject: ${Validator.DEFAULT_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'gasPrice' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } }); @@ -915,8 +914,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'maxPriorityFeePerGas' for TransactionObject: ${Validator.DEFAULT_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'maxPriorityFeePerGas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } }); @@ -934,8 +933,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'maxFeePerGas' for TransactionObject: ${Validator.DEFAULT_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'maxFeePerGas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } }); @@ -953,8 +952,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'value' for TransactionObject: ${Validator.DEFAULT_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'value' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } }); @@ -972,8 +971,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'data' for TransactionObject: ${Validator.EVEN_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'data' for TransactionObject: ${Constants.EVEN_HEX_ERROR}, value: 123`, ); } }); @@ -991,8 +990,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 1: ${Validator.BLOCK_NUMBER_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 1: ${Constants.BLOCK_NUMBER_ERROR}, value: 123`, ); } }); @@ -1010,8 +1009,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 1: ${Validator.BLOCK_NUMBER_ERROR}, value: newest`, + Constants.ERROR_CODE, + `Invalid parameter 1: ${Constants.BLOCK_NUMBER_ERROR}, value: newest`, ); } }); @@ -1029,7 +1028,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1044,7 +1043,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, Validator.ADDRESS_ERROR + ', value: 0x0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, Constants.ADDRESS_ERROR + ', value: 0x0'); } }); @@ -1059,7 +1058,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1076,7 +1075,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `The value passed is not valid: 123. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1095,7 +1094,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `The value passed is not valid: newest. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1114,7 +1113,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1131,8 +1130,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.ADDRESS_ERROR}, value: 0xb3b20624f8f0f86eb50dd04688409e5cea4bd02d700bf6e79e9384d47d6a5a35`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.ADDRESS_ERROR}, value: 0xb3b20624f8f0f86eb50dd04688409e5cea4bd02d700bf6e79e9384d47d6a5a35`, ); } }); @@ -1148,7 +1147,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1165,7 +1164,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 1: The value passed is not valid: 123. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1184,7 +1183,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 1: The value passed is not valid: newest. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1203,7 +1202,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1220,8 +1219,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.BLOCK_NUMBER_ERROR}, value: 1`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: 1`, ); } }); @@ -1239,8 +1238,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.BLOCK_NUMBER_ERROR}, value: newest`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: newest`, ); } }); @@ -1256,7 +1255,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1273,7 +1272,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 1: Expected boolean type, value: true`, ); } @@ -1292,7 +1291,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1309,8 +1308,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.BLOCK_HASH_ERROR}, value: 0x1`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.BLOCK_HASH_ERROR}, value: 0x1`, ); } }); @@ -1326,7 +1325,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1343,7 +1342,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 1: Expected boolean type, value: true`, ); } @@ -1362,7 +1361,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1379,8 +1378,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.ADDRESS_ERROR}, value: 0x0001`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.ADDRESS_ERROR}, value: 0x0001`, ); } }); @@ -1396,7 +1395,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1413,7 +1412,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 1: The value passed is not valid: 123. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1432,7 +1431,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 1: The value passed is not valid: newest. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1451,7 +1450,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1466,7 +1465,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, 'Expected TransactionObject, value: 0x0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, 'Expected TransactionObject, value: 0x0'); } }); @@ -1483,8 +1482,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'to' for TransactionObject: ${Validator.ADDRESS_ERROR}, value: 0x1`, + Constants.ERROR_CODE, + `Invalid parameter 'to' for TransactionObject: ${Constants.ADDRESS_ERROR}, value: 0x1`, ); } }); @@ -1502,8 +1501,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'from' for TransactionObject: ${Validator.ADDRESS_ERROR}, value: 0x1`, + Constants.ERROR_CODE, + `Invalid parameter 'from' for TransactionObject: ${Constants.ADDRESS_ERROR}, value: 0x1`, ); } }); @@ -1521,8 +1520,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'gas' for TransactionObject: ${Validator.DEFAULT_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'gas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } }); @@ -1540,8 +1539,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'gasPrice' for TransactionObject: ${Validator.DEFAULT_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'gasPrice' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } }); @@ -1559,8 +1558,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'maxPriorityFeePerGas' for TransactionObject: ${Validator.DEFAULT_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'maxPriorityFeePerGas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } }); @@ -1578,8 +1577,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'maxFeePerGas' for TransactionObject: ${Validator.DEFAULT_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'maxFeePerGas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } }); @@ -1597,8 +1596,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'value' for TransactionObject: ${Validator.DEFAULT_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'value' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } }); @@ -1616,8 +1615,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'data' for TransactionObject: ${Validator.EVEN_HEX_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'data' for TransactionObject: ${Constants.EVEN_HEX_ERROR}, value: 123`, ); } }); @@ -1635,8 +1634,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 1: ${Validator.BLOCK_PARAMS_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 1: ${Constants.BLOCK_PARAMS_ERROR}, value: 123`, ); } }); @@ -1654,8 +1653,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 1: ${Validator.BLOCK_PARAMS_ERROR}, value: newest`, + Constants.ERROR_CODE, + `Invalid parameter 1: ${Constants.BLOCK_PARAMS_ERROR}, value: newest`, ); } }); @@ -1673,8 +1672,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'blockHash' for BlockHashObject: ${Validator.BLOCK_HASH_ERROR}, value: 0x123`, + Constants.ERROR_CODE, + `Invalid parameter 'blockHash' for BlockHashObject: ${Constants.BLOCK_HASH_ERROR}, value: 0x123`, ); } }); @@ -1692,8 +1691,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'blockNumber' for BlockNumberObject: ${Validator.BLOCK_NUMBER_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'blockNumber' for BlockNumberObject: ${Constants.BLOCK_NUMBER_ERROR}, value: 123`, ); } }); @@ -1711,7 +1710,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1728,8 +1727,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.DEFAULT_HEX_ERROR}, value: f868`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.DEFAULT_HEX_ERROR}, value: f868`, ); } }); @@ -1747,7 +1746,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1762,7 +1761,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); }); @@ -1779,7 +1778,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1794,7 +1793,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1811,7 +1810,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 2: Expected Array, value: {}`, ); } @@ -1830,7 +1829,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1847,8 +1846,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.BLOCK_HASH_ERROR}, value: 0x1234`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.BLOCK_HASH_ERROR}, value: 0x1234`, ); } }); @@ -1866,7 +1865,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1883,8 +1882,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.BLOCK_NUMBER_ERROR}, value: 1234`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: 1234`, ); } }); @@ -1902,8 +1901,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.BLOCK_NUMBER_ERROR}, value: newest`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: newest`, ); } }); @@ -1921,7 +1920,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1938,8 +1937,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.ADDRESS_ERROR}, value: 0000000000000000000000000000000000000001`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.ADDRESS_ERROR}, value: 0000000000000000000000000000000000000001`, ); } }); @@ -1955,7 +1954,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1972,8 +1971,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 1: ${Validator.HASH_ERROR}, value: 1234`, + Constants.ERROR_CODE, + `Invalid parameter 1: ${Constants.HASH_ERROR}, value: 1234`, ); } }); @@ -1991,7 +1990,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 2: The value passed is not valid: 123. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -2010,7 +2009,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 2: The value passed is not valid: newest. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -2027,7 +2026,8 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 2'); + console.log(error); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 2'); } }); }); @@ -2044,7 +2044,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -2061,8 +2061,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.BLOCK_HASH_ERROR}, value: 0x1a2b3c`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.BLOCK_HASH_ERROR}, value: 0x1a2b3c`, ); } }); @@ -2078,7 +2078,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -2095,8 +2095,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 1: ${Validator.DEFAULT_HEX_ERROR}, value: 08`, + Constants.ERROR_CODE, + `Invalid parameter 1: ${Constants.DEFAULT_HEX_ERROR}, value: 08`, ); } }); @@ -2114,7 +2114,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -2131,8 +2131,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.BLOCK_NUMBER_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: 123`, ); } }); @@ -2150,8 +2150,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.BLOCK_NUMBER_ERROR}, value: newest`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: newest`, ); } }); @@ -2167,7 +2167,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -2184,8 +2184,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 1: ${Validator.DEFAULT_HEX_ERROR}, value: 08`, + Constants.ERROR_CODE, + `Invalid parameter 1: ${Constants.DEFAULT_HEX_ERROR}, value: 08`, ); } }); @@ -2205,8 +2205,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.TYPES['filter'].error}, value: 0x1`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${TYPES['filter'].error}, value: 0x1`, ); } }); @@ -2224,7 +2224,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 0: Can't use both blockHash and toBlock/fromBlock`, ); } @@ -2243,8 +2243,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'blockHash' for FilterObject: ${Validator.BLOCK_HASH_ERROR}, value: 0x123`, + Constants.ERROR_CODE, + `Invalid parameter 'blockHash' for FilterObject: ${Constants.BLOCK_HASH_ERROR}, value: 0x123`, ); } }); @@ -2262,8 +2262,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'toBlock' for FilterObject: ${Validator.BLOCK_NUMBER_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'toBlock' for FilterObject: ${Constants.BLOCK_NUMBER_ERROR}, value: 123`, ); } }); @@ -2281,8 +2281,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'fromBlock' for FilterObject: ${Validator.BLOCK_NUMBER_ERROR}, value: 123`, + Constants.ERROR_CODE, + `Invalid parameter 'fromBlock' for FilterObject: ${Constants.BLOCK_NUMBER_ERROR}, value: 123`, ); } }); @@ -2300,8 +2300,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'address' for FilterObject: ${Validator.TYPES.addressFilter.error}, value: 0x012345`, + Constants.ERROR_CODE, + `Invalid parameter 'address' for FilterObject: ${TYPES.addressFilter.error}, value: 0x012345`, ); } }); @@ -2319,8 +2319,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'topics' for FilterObject: ${Validator.TYPES['topics'].error}, value: {}`, + Constants.ERROR_CODE, + `Invalid parameter 'topics' for FilterObject: ${TYPES['topics'].error}, value: {}`, ); } }); @@ -2338,8 +2338,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'topics' for FilterObject: ${Validator.TYPES['topics'].error}, value: [123]`, + Constants.ERROR_CODE, + `Invalid parameter 'topics' for FilterObject: ${TYPES['topics'].error}, value: [123]`, ); } }); @@ -2357,8 +2357,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'topics' for FilterObject: ${Validator.TYPES['topics'].error}, value: [[123]]`, + Constants.ERROR_CODE, + `Invalid parameter 'topics' for FilterObject: ${TYPES['topics'].error}, value: [[123]]`, ); } }); @@ -2562,7 +2562,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Validator.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -2579,8 +2579,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 0: The value passed is not valid: invalidHash. ${Validator.TRANSACTION_HASH_ERROR} OR ${Validator.TRANSACTION_ID_ERROR}`, + Constants.ERROR_CODE, + `Invalid parameter 0: The value passed is not valid: invalidHash. ${Constants.TRANSACTION_HASH_ERROR} OR ${Constants.TRANSACTION_ID_ERROR}`, ); } }); @@ -2598,7 +2598,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 1: Expected TracerConfigWrapper which contains a valid TracerType and/or TracerConfig, value: invalidTracerType`, ); } @@ -2617,7 +2617,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: Expected TracerConfig, value: ${JSON.stringify({ invalidConfig: true, })}`, @@ -2641,7 +2641,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: Expected TracerConfig, value: ${JSON.stringify({ enableMemory: 'must be a boolean', })}`, @@ -2665,7 +2665,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: Expected TracerConfig, value: ${JSON.stringify({ disableStack: 'must be a boolean', })}`, @@ -2689,7 +2689,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: Expected TracerConfig, value: ${JSON.stringify({ disableStorage: 'must be a boolean', })}`, @@ -2710,8 +2710,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'tracer' for TracerConfigWrapper: ${Validator.TYPES.tracerType.error}, value: invalidTracerType`, + Constants.ERROR_CODE, + `Invalid parameter 'tracer' for TracerConfigWrapper: ${TYPES.tracerType.error}, value: invalidTracerType`, ); } }); @@ -2729,8 +2729,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, - `Invalid parameter 'tracerConfig' for TracerConfigWrapper: ${Validator.TYPES.tracerConfig.error}, value: invalidTracerConfig`, + Constants.ERROR_CODE, + `Invalid parameter 'tracerConfig' for TracerConfigWrapper: ${TYPES.tracerConfig.error}, value: invalidTracerConfig`, ); } }); @@ -2748,9 +2748,9 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Validator.ERROR_CODE, + Constants.ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: ${ - Validator.TYPES.tracerConfig.error + TYPES.tracerConfig.error }, value: ${JSON.stringify({ invalidProperty: true, })}`, @@ -3114,7 +3114,7 @@ describe('RPC Server', function () { [], 400, BaseTest.invalidParamError.bind(BaseTest), - Validator.ERROR_CODE, + Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0', ); }); @@ -3124,8 +3124,8 @@ describe('RPC Server', function () { ['not-a-block-number'], 400, BaseTest.invalidParamError.bind(BaseTest), - Validator.ERROR_CODE, - `Invalid parameter 0: ${Validator.BLOCK_NUMBER_ERROR}, value: not-a-block-number`, + Constants.ERROR_CODE, + `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: not-a-block-number`, ); }); @@ -3134,8 +3134,8 @@ describe('RPC Server', function () { [blockNumberHex, { tracer: 'invalidTracerType' }], 400, BaseTest.invalidParamError.bind(BaseTest), - Validator.ERROR_CODE, - `Invalid parameter 'tracer' for TracerConfigWrapper: ${Validator.TYPES.tracerType.error}, value: invalidTracerType`, + Constants.ERROR_CODE, + `Invalid parameter 'tracer' for TracerConfigWrapper: ${TYPES.tracerType.error}, value: invalidTracerType`, ); }); @@ -3144,8 +3144,8 @@ describe('RPC Server', function () { [blockNumberHex, { tracer: TracerType.CallTracer, tracerConfig: 'not-an-object' }], 400, BaseTest.invalidParamError.bind(BaseTest), - Validator.ERROR_CODE, - `Invalid parameter 'tracerConfig' for TracerConfigWrapper: ${Validator.TYPES.tracerConfig.error}, value: not-an-object`, + Constants.ERROR_CODE, + `Invalid parameter 'tracerConfig' for TracerConfigWrapper: ${TYPES.tracerConfig.error}, value: not-an-object`, ); }); From 3caa2d2dcd4b2f21da013246ff8964c827d33813 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Thu, 3 Jul 2025 17:33:19 +0300 Subject: [PATCH 04/16] fixes tests Signed-off-by: Konstantina Blazhukova --- .../dispatcher/rpcMethodDispatcher.spec.ts | 13 +- .../tests/lib/validators/validators.spec.ts | 328 +++++++++--------- 2 files changed, 169 insertions(+), 172 deletions(-) diff --git a/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts b/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts index 60b71297be..3b740dec91 100644 --- a/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts +++ b/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts @@ -5,13 +5,12 @@ import chaiAsPromised from 'chai-as-promised'; import pino from 'pino'; import sinon from 'sinon'; -import { RPC_PARAM_VALIDATION_RULES_KEY } from '../../../src/lib/decorators'; import { RpcMethodDispatcher } from '../../../src/lib/dispatcher/rpcMethodDispatcher'; import { JsonRpcError, predefined } from '../../../src/lib/errors/JsonRpcError'; import { MirrorNodeClientError } from '../../../src/lib/errors/MirrorNodeClientError'; import { SDKClientError } from '../../../src/lib/errors/SDKClientError'; import { RequestDetails, RpcMethodRegistry } from '../../../src/lib/types'; -import { Validator } from '../../../src/lib/validators'; +import * as Validator from '../../../src/lib/validators'; import { Utils } from '../../../src/utils'; chai.use(chaiAsPromised); @@ -118,7 +117,7 @@ describe('RpcMethodDispatcher', () => { it('should validate parameters when schema exists', () => { // Set up validation schema const validationRules = { 0: { type: 'string', required: true } }; - operationHandler[RPC_PARAM_VALIDATION_RULES_KEY] = validationRules; + operationHandler[Validator.RPC_PARAM_VALIDATION_RULES_KEY] = validationRules; (dispatcher as any).precheckRpcMethod(TEST_METHOD_NAME, TEST_PARAMS, TEST_REQUEST_DETAILS); @@ -128,7 +127,7 @@ describe('RpcMethodDispatcher', () => { it('should skip validation when no schema exists', () => { // Ensure there's no validation schema - delete operationHandler[RPC_PARAM_VALIDATION_RULES_KEY]; + delete operationHandler[Validator.RPC_PARAM_VALIDATION_RULES_KEY]; (dispatcher as any).precheckRpcMethod(TEST_METHOD_NAME, TEST_PARAMS, TEST_REQUEST_DETAILS); @@ -404,7 +403,7 @@ describe('RpcMethodDispatcher', () => { // Test with schema validateParamsStub.reset(); const validationRules = { 0: { type: 'string', required: true } }; - operationHandler[RPC_PARAM_VALIDATION_RULES_KEY] = validationRules; + operationHandler[Validator.RPC_PARAM_VALIDATION_RULES_KEY] = validationRules; result = await dispatcher.dispatch(TEST_METHOD_NAME, TEST_PARAMS, TEST_REQUEST_DETAILS); expect(result).to.equal(TEST_RESULT); @@ -432,7 +431,7 @@ describe('RpcMethodDispatcher', () => { // Validation error validateParamsStub.throws(predefined.INVALID_PARAMETERS); const validationRules = { 0: { type: 'string', required: true } }; - operationHandler[RPC_PARAM_VALIDATION_RULES_KEY] = validationRules; + operationHandler[Validator.RPC_PARAM_VALIDATION_RULES_KEY] = validationRules; let result = await dispatcher.dispatch(TEST_METHOD_NAME, TEST_PARAMS, TEST_REQUEST_DETAILS); expect(result).to.be.instanceOf(JsonRpcError); @@ -440,7 +439,7 @@ describe('RpcMethodDispatcher', () => { // Execution error validateParamsStub.reset(); - delete operationHandler[RPC_PARAM_VALIDATION_RULES_KEY]; + delete operationHandler[Validator.RPC_PARAM_VALIDATION_RULES_KEY]; operationHandler.rejects(new Error('Execution failed')); result = await dispatcher.dispatch(TEST_METHOD_NAME, TEST_PARAMS, TEST_REQUEST_DETAILS); diff --git a/packages/relay/tests/lib/validators/validators.spec.ts b/packages/relay/tests/lib/validators/validators.spec.ts index 8151808757..b976def825 100644 --- a/packages/relay/tests/lib/validators/validators.spec.ts +++ b/packages/relay/tests/lib/validators/validators.spec.ts @@ -217,91 +217,89 @@ describe('Validator', async () => { }); }); - // describe('validates Filter Object type correctly', async () => { - // const validation = { 0: { type: 'filter', required: true } }; - // const error = TYPES['filter'].error; - // const object = OBJECTS_VALIDATIONS.FilterObject.name; - - // it('throws an error if the param is not an Object', async () => { - // expect(() => validateParams(['0x1'], validation)).to.throw(expectInvalidParam(0, error, '0x1')); - // expect(() => validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); - // expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, error, '')); - // expect(() => validateParams([true], validation)).to.throw(expectInvalidParam(0, error, 'true')); - // }); - - // it('throws an error if both blockHash and fromBlock/toBlock are used', async () => { - // expect(() => - // validateParams( - // [{ blockHash: '0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8', fromBlock: 'latest' }], - // validation, - // ), - // ).to.throw(expectInvalidParam(0, "Can't use both blockHash and toBlock/fromBlock")); - // }); - - // it('throws an error if the Filter Object properties are the wrong type', async () => { - // expect(() => validateParams([{ blockHash: 123 }], validation)).to.throw( - // expectInvalidObject('blockHash', Constants.BLOCK_HASH_ERROR, object, '123'), - // ); - // expect(() => validateParams([{ toBlock: 123 }], validation)).to.throw( - // expectInvalidObject('toBlock', Constants.BLOCK_NUMBER_ERROR, object, '123'), - // ); - // expect(() => validateParams([{ fromBlock: 123 }], validation)).to.throw( - // expectInvalidObject('fromBlock', Constants.BLOCK_NUMBER_ERROR, object, '123'), - // ); - // expect(() => validateParams([{ address: '0x1' }], validation)).to.throw( - // expectInvalidObject('address', TYPES.addressFilter.error, object, '0x1'), - // ); - // expect(() => validateParams([{ topics: {} }], validation)).to.throw( - // expectInvalidObject('topics', TYPES.topics.error, object, '{}'), - // ); - // expect(() => validateParams([{ topics: [123] }], validation)).to.throw( - // expectInvalidObject('topics', TYPES.topics.error, object, '[123]'), - // ); - // }); - - // it('does not throw an error for correct values', async () => { - // expect( - // validateParams( - // [{ blockHash: '0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8' }], - // validation, - // ), - // ).to.eq(undefined); - // expect(validateParams([{ toBlock: '0x2' }], validation)).to.eq(undefined); - // expect(validateParams([{ toBlock: 'latest' }], validation)).to.eq(undefined); - // expect(validateParams([{ fromBlock: '0x1' }], validation)).to.eq(undefined); - // expect(validateParams([{ fromBlock: 'earliest' }], validation)).to.eq(undefined); - // expect(validateParams([{ address: '0x4422E9088662c44604189B2aA3ae8eE282fceBB7' }], validation)).to.eq( - // undefined, - // ); - // expect( - // validateParams( - // [{ address: ['0x4422E9088662c44604189B2aA3ae8eE282fceBB7', '0x4422E9088662c44604189B2aA3ae8eE282fceBB8'] }], - // validation, - // ), - // ).to.eq(undefined); - // expect( - // validateParams( - // [{ topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'] }], - // validation, - // ), - // ).to.eq(undefined); - // expect( - // validateParams( - // [ - // { - // topics: [ - // [ - // '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', - // '0xea443924a9fba8d643a00daf0a7956ebc37fa4e9da82f07f80c34f0f5217edf9', - // ], - // ], - // }, - // ], - // validation, - // ), - // ).to.eq(undefined); - // }); - // }); + describe('validates Filter Object type correctly', async () => { + const validation = { 0: { type: 'filter', required: true } }; + const error = TYPES['filter'].error; + const name = 'FilterObject'; + + it('throws an error if the param is not an Object', async () => { + expect(() => validateParams(['0x1'], validation)).to.throw(expectInvalidParam(0, error, '0x1')); + expect(() => validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); + expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, error, '')); + expect(() => validateParams([true], validation)).to.throw(expectInvalidParam(0, error, 'true')); + }); + + it('throws an error if both blockHash and fromBlock/toBlock are used', async () => { + expect(() => + validateParams( + [{ blockHash: '0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8', fromBlock: 'latest' }], + validation, + ), + ).to.throw(expectInvalidParam(0, "Can't use both blockHash and toBlock/fromBlock")); + }); + + it('throws an error if the Filter Object properties are the wrong type', async () => { + expect(() => validateParams([{ blockHash: 123 }], validation)).to.throw( + expectInvalidObject('blockHash', Constants.BLOCK_HASH_ERROR, name, '123'), + ); + expect(() => validateParams([{ toBlock: 123 }], validation)).to.throw( + expectInvalidObject('toBlock', Constants.BLOCK_NUMBER_ERROR, name, '123'), + ); + expect(() => validateParams([{ fromBlock: 123 }], validation)).to.throw( + expectInvalidObject('fromBlock', Constants.BLOCK_NUMBER_ERROR, name, '123'), + ); + expect(() => validateParams([{ address: '0x1' }], validation)).to.throw( + expectInvalidObject('address', TYPES.addressFilter.error, name, '0x1'), + ); + expect(() => validateParams([{ topics: {} }], validation)).to.throw( + expectInvalidObject('topics', TYPES.topics.error, name, '{}'), + ); + expect(() => validateParams([{ topics: [123] }], validation)).to.throw( + expectInvalidObject('topics', TYPES.topics.error, name, '[123]'), + ); + }); + + it('does not throw an error for correct values', async () => { + expect( + validateParams( + [{ blockHash: '0xdec54931fcfe053f3ffec90c1f7fd20158420b415054f15a4d16b63c528f70a8' }], + validation, + ), + ).to.eq(undefined); + expect(validateParams([{ toBlock: '0x2' }], validation)).to.eq(undefined); + expect(validateParams([{ toBlock: 'latest' }], validation)).to.eq(undefined); + expect(validateParams([{ fromBlock: '0x1' }], validation)).to.eq(undefined); + expect(validateParams([{ fromBlock: 'earliest' }], validation)).to.eq(undefined); + expect(validateParams([{ address: '0x4422E9088662c44604189B2aA3ae8eE282fceBB7' }], validation)).to.eq(undefined); + expect( + validateParams( + [{ address: ['0x4422E9088662c44604189B2aA3ae8eE282fceBB7', '0x4422E9088662c44604189B2aA3ae8eE282fceBB8'] }], + validation, + ), + ).to.eq(undefined); + expect( + validateParams( + [{ topics: ['0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'] }], + validation, + ), + ).to.eq(undefined); + expect( + validateParams( + [ + { + topics: [ + [ + '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', + '0xea443924a9fba8d643a00daf0a7956ebc37fa4e9da82f07f80c34f0f5217edf9', + ], + ], + }, + ], + validation, + ), + ).to.eq(undefined); + }); + }); describe('validates topics type correctly', async () => { const validation = { 0: { type: 'topics' } }; @@ -485,48 +483,48 @@ describe('Validator', async () => { }); }); - // describe('validates Transaction Object type correctly', async () => { - // const validation = { 0: { type: 'transaction', required: true } }; - // const error = TYPES['transaction'].error; - // const object = OBJECTS_VALIDATIONS.transactionObject.name; - - // it('throws an error if the param is not an Object', async () => { - // expect(() => validateParams(['string'], validation)).to.throw(expectInvalidParam(0, error, 'string')); - // expect(() => validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); - // expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, error, '')); - // expect(() => validateParams([true], validation)).to.throw(expectInvalidParam(0, error, 'true')); - // }); - - // it('throws an error if the Transaction Object properties are the wrong type', async () => { - // expect(() => validateParams([{ from: '0x1234' }], validation)).to.throw( - // expectInvalidObject('from', Constants.ADDRESS_ERROR, object, '0x1234'), - // ); - // expect(() => validateParams([{ to: '0x1234' }], validation)).to.throw( - // expectInvalidObject('to', Constants.ADDRESS_ERROR, object, '0x1234'), - // ); - // expect(() => validateParams([{ gas: 123 }], validation)).to.throw( - // expectInvalidObject('gas', Constants.DEFAULT_HEX_ERROR, object, '123'), - // ); - // expect(() => validateParams([{ gasPrice: 123 }], validation)).to.throw( - // expectInvalidObject('gasPrice', Constants.DEFAULT_HEX_ERROR, object, '123'), - // ); - // expect(() => validateParams([{ maxPriorityFeePerGas: 123 }], validation)).to.throw( - // expectInvalidObject('maxPriorityFeePerGas', Constants.DEFAULT_HEX_ERROR, object, '123'), - // ); - // expect(() => validateParams([{ maxFeePerGas: 123 }], validation)).to.throw( - // expectInvalidObject('maxFeePerGas', Constants.DEFAULT_HEX_ERROR, object, '123'), - // ); - // expect(() => validateParams([{ value: '123456' }], validation)).to.throw( - // expectInvalidObject('value', Constants.DEFAULT_HEX_ERROR, object, '123456'), - // ); - // expect(() => validateParams([{ data: '123456' }], validation)).to.throw( - // expectInvalidObject('data', Constants.EVEN_HEX_ERROR, object, '123456'), - // ); - // expect(() => validateParams([{ data: '0x1234567' }], validation)).to.throw( - // expectInvalidObject('data', Constants.EVEN_HEX_ERROR, object, '0x1234567'), - // ); - // }); - // }); + describe('validates Transaction Object type correctly', async () => { + const validation = { 0: { type: 'transaction', required: true } }; + const error = TYPES['transaction'].error; + const name = 'ТransactionObject'; + + it('throws an error if the param is not an Object', async () => { + expect(() => validateParams(['string'], validation)).to.throw(expectInvalidParam(0, error, 'string')); + expect(() => validateParams([123], validation)).to.throw(expectInvalidParam(0, error, '123')); + expect(() => validateParams([[]], validation)).to.throw(expectInvalidParam(0, error, '')); + expect(() => validateParams([true], validation)).to.throw(expectInvalidParam(0, error, 'true')); + }); + + it('throws an error if the Transaction Object properties are the wrong type', async () => { + expect(() => validateParams([{ from: '0x1234' }], validation)).to.throw( + expectInvalidObject('from', Constants.ADDRESS_ERROR, name, '0x1234'), + ); + expect(() => validateParams([{ to: '0x1234' }], validation)).to.throw( + expectInvalidObject('to', Constants.ADDRESS_ERROR, name, '0x1234'), + ); + expect(() => validateParams([{ gas: 123 }], validation)).to.throw( + expectInvalidObject('gas', Constants.DEFAULT_HEX_ERROR, name, '123'), + ); + expect(() => validateParams([{ gasPrice: 123 }], validation)).to.throw( + expectInvalidObject('gasPrice', Constants.DEFAULT_HEX_ERROR, name, '123'), + ); + expect(() => validateParams([{ maxPriorityFeePerGas: 123 }], validation)).to.throw( + expectInvalidObject('maxPriorityFeePerGas', Constants.DEFAULT_HEX_ERROR, name, '123'), + ); + expect(() => validateParams([{ maxFeePerGas: 123 }], validation)).to.throw( + expectInvalidObject('maxFeePerGas', Constants.DEFAULT_HEX_ERROR, name, '123'), + ); + expect(() => validateParams([{ value: '123456' }], validation)).to.throw( + expectInvalidObject('value', Constants.DEFAULT_HEX_ERROR, name, '123456'), + ); + expect(() => validateParams([{ data: '123456' }], validation)).to.throw( + expectInvalidObject('data', Constants.EVEN_HEX_ERROR, name, '123456'), + ); + expect(() => validateParams([{ data: '0x1234567' }], validation)).to.throw( + expectInvalidObject('data', Constants.EVEN_HEX_ERROR, name, '0x1234567'), + ); + }); + }); describe('validates transactionHash type correctly', async () => { const validation = { 0: { type: 'transactionHash' } }; @@ -786,44 +784,44 @@ describe('Validator', async () => { }); }); - // describe('validates validateObject with transaction object', async () => { - // const transactionFilterObject = new TransactionObject({ - // from: '0xdd94180d1c8e069fc7e6760d5bf7dee477fe617b', - // gasPrice: '0x0', - // value: '0x0', - // data: null, - // }); - - // it('returns true when transaction data is null and is nullable is true', async () => { - // const result = validateObject(transactionFilterObject.object, { - // ...OBJECTS_VALIDATIONS.transaction, - // properties: { - // ...OBJECTS_VALIDATIONS.transaction.properties, - // data: { - // type: 'hex', - // nullable: true, - // }, - // }, - // }); - - // expect(result).to.be.true; - // }); - - // it('throws an error if Transaction Object data param is null and isNullable is false', async () => { - // expect(() => - // validateObject(transactionFilterObject.object, { - // ...OBJECTS_VALIDATIONS.transaction, - // properties: { - // ...OBJECTS_VALIDATIONS.transaction.properties, - // data: { - // type: 'hex', - // nullable: false, - // }, - // }, - // }), - // ).to.throw(expectInvalidObject('data', 'Expected 0x prefixed hexadecimal value', 'TransactionObject', 'null')); - // }); - // }); + describe('validates validateObject with transaction object', async () => { + const transactionFilterObject = { + from: '0xdd94180d1c8e069fc7e6760d5bf7dee477fe617b', + gasPrice: '0x0', + value: '0x0', + data: null, + }; + + it('returns true when transaction data is null and is nullable is true', async () => { + const result = validateObject(transactionFilterObject, { + ...OBJECTS_VALIDATIONS.transaction, + properties: { + ...OBJECTS_VALIDATIONS.transaction.properties, + data: { + type: 'hex', + nullable: true, + }, + }, + }); + + expect(result).to.be.true; + }); + + it('throws an error if Transaction Object data param is null and isNullable is false', async () => { + expect(() => + validateObject(transactionFilterObject, { + ...OBJECTS_VALIDATIONS.transaction, + properties: { + ...OBJECTS_VALIDATIONS.transaction.properties, + data: { + type: 'hex', + nullable: false, + }, + }, + }), + ).to.throw(expectInvalidObject('data', 'Expected 0x prefixed hexadecimal value', 'TransactionObject', 'null')); + }); + }); describe('validates isValidAndNonNullableParam', async () => { it('returns false if transaction data is undefined and isnullable is true', async () => { From 381f8f2d56208c50e5a4c215134873645cf3daf0 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Fri, 4 Jul 2025 11:08:30 +0300 Subject: [PATCH 05/16] fixes unit test Signed-off-by: Konstantina Blazhukova --- packages/relay/tests/lib/validators/validators.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/relay/tests/lib/validators/validators.spec.ts b/packages/relay/tests/lib/validators/validators.spec.ts index b976def825..0eb1da58f3 100644 --- a/packages/relay/tests/lib/validators/validators.spec.ts +++ b/packages/relay/tests/lib/validators/validators.spec.ts @@ -486,7 +486,7 @@ describe('Validator', async () => { describe('validates Transaction Object type correctly', async () => { const validation = { 0: { type: 'transaction', required: true } }; const error = TYPES['transaction'].error; - const name = 'ТransactionObject'; + const name = 'TransactionObject'; it('throws an error if the param is not an Object', async () => { expect(() => validateParams(['string'], validation)).to.throw(expectInvalidParam(0, error, 'string')); From 5eabe0d423796f54a56eb03adeacb759f2a82a6e Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Fri, 4 Jul 2025 11:49:56 +0300 Subject: [PATCH 06/16] removes unnecessary constants Signed-off-by: Konstantina Blazhukova --- .../relay/src/lib/validators/constants.ts | 3 - packages/server/tests/helpers/constants.ts | 2 + .../server/tests/integration/server.spec.ts | 211 +++++++++--------- 3 files changed, 107 insertions(+), 109 deletions(-) diff --git a/packages/relay/src/lib/validators/constants.ts b/packages/relay/src/lib/validators/constants.ts index 01c880f50a..7036542080 100644 --- a/packages/relay/src/lib/validators/constants.ts +++ b/packages/relay/src/lib/validators/constants.ts @@ -2,7 +2,6 @@ export const BASE_HEX_REGEX = '^0[xX][a-fA-F0-9]'; export const DEFAULT_HEX_ERROR = 'Expected 0x prefixed hexadecimal value'; -export const ERROR_CODE = -32602; export const EVEN_HEX_ERROR = `${DEFAULT_HEX_ERROR} with even length`; export const HASH_ERROR = 'Expected 0x prefixed string representing the hash (32 bytes)'; export const ADDRESS_ERROR = 'Expected 0x prefixed string representing the address (20 bytes)'; @@ -12,8 +11,6 @@ export const BLOCK_PARAMS_ERROR = `Expected ${HASH_ERROR} in object, 0x prefixed export const BLOCK_HASH_ERROR = `Expected ${HASH_ERROR} of a block`; export const TRANSACTION_HASH_ERROR = `Expected ${HASH_ERROR} of a transaction`; export const TOPIC_HASH_ERROR = `Expected ${HASH_ERROR} of a topic`; -export const TRANSACTION_ID_ERROR = `Expected a transaction ID string in the format "shard.realm.num-sss-nnn" where sss are seconds and nnn are nanoseconds`; -export const TRANSACTION_ID_REGEX = /^(\d)\.(\d)\.(\d{1,10})-(\d{1,19})-(\d{1,9})$/; export const INVALID_BLOCK_HASH_TAG_NUMBER = 'The value passed is not a valid blockHash/blockNumber/blockTag value:'; export enum TracerType { CallTracer = 'callTracer', diff --git a/packages/server/tests/helpers/constants.ts b/packages/server/tests/helpers/constants.ts index c122837ab3..0742a84415 100644 --- a/packages/server/tests/helpers/constants.ts +++ b/packages/server/tests/helpers/constants.ts @@ -165,6 +165,7 @@ const TINYBAR_TO_WEIBAR_COEF = 10_000_000_000; const CALL_EXCEPTION = 'CALL_EXCEPTION'; const FEE_HISTORY_REWARD_PERCENTILES_MAX_SIZE = 100; +const ERROR_CODE = -32602; export default { ETH_ENDPOINTS, @@ -184,4 +185,5 @@ export default { TINYBAR_TO_WEIBAR_COEF, METRICS, FEE_HISTORY_REWARD_PERCENTILES_MAX_SIZE, + ERROR_CODE, }; diff --git a/packages/server/tests/integration/server.spec.ts b/packages/server/tests/integration/server.spec.ts index 20ddc407c8..4cb73f0387 100644 --- a/packages/server/tests/integration/server.spec.ts +++ b/packages/server/tests/integration/server.spec.ts @@ -10,6 +10,9 @@ import { TracerType } from '@hashgraph/json-rpc-relay/dist/lib/constants'; import { DebugImpl } from '@hashgraph/json-rpc-relay/dist/lib/debug'; import { CacheService } from '@hashgraph/json-rpc-relay/dist/lib/services/cacheService/cacheService'; import { Constants, TYPES } from '@hashgraph/json-rpc-relay/dist/lib/validators'; + +import serverTestConstants from '../helpers/constants'; +const { ERROR_CODE } = serverTestConstants; import { CommonService } from '@hashgraph/json-rpc-relay/src/lib/services'; import Axios, { AxiosInstance } from 'axios'; import { expect } from 'chai'; @@ -806,7 +809,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -821,7 +824,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, 'Expected TransactionObject, value: 0x0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, 'Expected TransactionObject, value: 0x0'); } }); @@ -838,7 +841,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'to' for TransactionObject: ${Constants.ADDRESS_ERROR}, value: 0x1`, ); } @@ -857,7 +860,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'from' for TransactionObject: ${Constants.ADDRESS_ERROR}, value: 0x1`, ); } @@ -876,7 +879,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'gas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } @@ -895,7 +898,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'gasPrice' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } @@ -914,7 +917,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'maxPriorityFeePerGas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } @@ -933,7 +936,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'maxFeePerGas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } @@ -952,7 +955,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'value' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } @@ -971,7 +974,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'data' for TransactionObject: ${Constants.EVEN_HEX_ERROR}, value: 123`, ); } @@ -990,7 +993,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: ${Constants.BLOCK_NUMBER_ERROR}, value: 123`, ); } @@ -1009,7 +1012,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: ${Constants.BLOCK_NUMBER_ERROR}, value: newest`, ); } @@ -1028,7 +1031,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1043,7 +1046,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, Constants.ADDRESS_ERROR + ', value: 0x0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, Constants.ADDRESS_ERROR + ', value: 0x0'); } }); @@ -1058,7 +1061,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1075,7 +1078,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `The value passed is not valid: 123. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1094,7 +1097,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `The value passed is not valid: newest. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1113,7 +1116,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1130,7 +1133,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.ADDRESS_ERROR}, value: 0xb3b20624f8f0f86eb50dd04688409e5cea4bd02d700bf6e79e9384d47d6a5a35`, ); } @@ -1147,7 +1150,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1164,7 +1167,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: The value passed is not valid: 123. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1183,7 +1186,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: The value passed is not valid: newest. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1202,7 +1205,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1219,7 +1222,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: 1`, ); } @@ -1238,7 +1241,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: newest`, ); } @@ -1255,7 +1258,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1272,7 +1275,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: Expected boolean type, value: true`, ); } @@ -1291,7 +1294,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1308,7 +1311,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.BLOCK_HASH_ERROR}, value: 0x1`, ); } @@ -1325,7 +1328,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1342,7 +1345,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: Expected boolean type, value: true`, ); } @@ -1361,7 +1364,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1378,7 +1381,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.ADDRESS_ERROR}, value: 0x0001`, ); } @@ -1395,7 +1398,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1412,7 +1415,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: The value passed is not valid: 123. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1431,7 +1434,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: The value passed is not valid: newest. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -1450,7 +1453,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1465,7 +1468,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, 'Expected TransactionObject, value: 0x0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, 'Expected TransactionObject, value: 0x0'); } }); @@ -1482,7 +1485,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'to' for TransactionObject: ${Constants.ADDRESS_ERROR}, value: 0x1`, ); } @@ -1501,7 +1504,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'from' for TransactionObject: ${Constants.ADDRESS_ERROR}, value: 0x1`, ); } @@ -1520,7 +1523,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'gas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } @@ -1539,7 +1542,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'gasPrice' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } @@ -1558,7 +1561,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'maxPriorityFeePerGas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } @@ -1577,7 +1580,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'maxFeePerGas' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } @@ -1596,7 +1599,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'value' for TransactionObject: ${Constants.DEFAULT_HEX_ERROR}, value: 123`, ); } @@ -1615,7 +1618,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'data' for TransactionObject: ${Constants.EVEN_HEX_ERROR}, value: 123`, ); } @@ -1634,7 +1637,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: ${Constants.BLOCK_PARAMS_ERROR}, value: 123`, ); } @@ -1653,7 +1656,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: ${Constants.BLOCK_PARAMS_ERROR}, value: newest`, ); } @@ -1672,7 +1675,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'blockHash' for BlockHashObject: ${Constants.BLOCK_HASH_ERROR}, value: 0x123`, ); } @@ -1691,7 +1694,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'blockNumber' for BlockNumberObject: ${Constants.BLOCK_NUMBER_ERROR}, value: 123`, ); } @@ -1710,7 +1713,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1727,7 +1730,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.DEFAULT_HEX_ERROR}, value: f868`, ); } @@ -1746,7 +1749,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1761,7 +1764,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); }); @@ -1778,7 +1781,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1793,7 +1796,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1808,11 +1811,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError( - error.response, - Constants.ERROR_CODE, - `Invalid parameter 2: Expected Array, value: {}`, - ); + BaseTest.invalidParamError(error.response, ERROR_CODE, `Invalid parameter 2: Expected Array, value: {}`); } }); }); @@ -1829,7 +1828,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1846,7 +1845,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.BLOCK_HASH_ERROR}, value: 0x1234`, ); } @@ -1865,7 +1864,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1882,7 +1881,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: 1234`, ); } @@ -1901,7 +1900,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: newest`, ); } @@ -1920,7 +1919,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -1937,7 +1936,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.ADDRESS_ERROR}, value: 0000000000000000000000000000000000000001`, ); } @@ -1954,7 +1953,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -1971,7 +1970,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: ${Constants.HASH_ERROR}, value: 1234`, ); } @@ -1990,7 +1989,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 2: The value passed is not valid: 123. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -2009,7 +2008,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 2: The value passed is not valid: newest. ${Constants.BLOCK_NUMBER_ERROR} OR ${Constants.BLOCK_HASH_ERROR}`, ); } @@ -2027,7 +2026,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { console.log(error); - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 2'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 2'); } }); }); @@ -2044,7 +2043,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -2061,7 +2060,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.BLOCK_HASH_ERROR}, value: 0x1a2b3c`, ); } @@ -2078,7 +2077,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -2095,7 +2094,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: ${Constants.DEFAULT_HEX_ERROR}, value: 08`, ); } @@ -2114,7 +2113,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -2131,7 +2130,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: 123`, ); } @@ -2150,7 +2149,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: newest`, ); } @@ -2167,7 +2166,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 1'); } }); @@ -2184,7 +2183,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: ${Constants.DEFAULT_HEX_ERROR}, value: 08`, ); } @@ -2205,7 +2204,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${TYPES['filter'].error}, value: 0x1`, ); } @@ -2224,7 +2223,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: Can't use both blockHash and toBlock/fromBlock`, ); } @@ -2243,7 +2242,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'blockHash' for FilterObject: ${Constants.BLOCK_HASH_ERROR}, value: 0x123`, ); } @@ -2262,7 +2261,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'toBlock' for FilterObject: ${Constants.BLOCK_NUMBER_ERROR}, value: 123`, ); } @@ -2281,7 +2280,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'fromBlock' for FilterObject: ${Constants.BLOCK_NUMBER_ERROR}, value: 123`, ); } @@ -2300,7 +2299,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'address' for FilterObject: ${TYPES.addressFilter.error}, value: 0x012345`, ); } @@ -2319,7 +2318,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'topics' for FilterObject: ${TYPES['topics'].error}, value: {}`, ); } @@ -2338,7 +2337,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'topics' for FilterObject: ${TYPES['topics'].error}, value: [123]`, ); } @@ -2357,7 +2356,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'topics' for FilterObject: ${TYPES['topics'].error}, value: [[123]]`, ); } @@ -2562,7 +2561,7 @@ describe('RPC Server', function () { Assertions.expectedError(); } catch (error: any) { - BaseTest.invalidParamError(error.response, Constants.ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); + BaseTest.invalidParamError(error.response, ERROR_CODE, MISSING_PARAM_ERROR + ' 0'); } }); @@ -2579,8 +2578,8 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, - `Invalid parameter 0: The value passed is not valid: invalidHash. ${Constants.TRANSACTION_HASH_ERROR} OR ${Constants.TRANSACTION_ID_ERROR}`, + ERROR_CODE, + `Invalid parameter 0: The value passed is not valid: invalidHash. ${Constants.TRANSACTION_HASH_ERROR}`, ); } }); @@ -2598,7 +2597,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 1: Expected TracerConfigWrapper which contains a valid TracerType and/or TracerConfig, value: invalidTracerType`, ); } @@ -2617,7 +2616,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: Expected TracerConfig, value: ${JSON.stringify({ invalidConfig: true, })}`, @@ -2641,7 +2640,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: Expected TracerConfig, value: ${JSON.stringify({ enableMemory: 'must be a boolean', })}`, @@ -2665,7 +2664,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: Expected TracerConfig, value: ${JSON.stringify({ disableStack: 'must be a boolean', })}`, @@ -2689,7 +2688,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: Expected TracerConfig, value: ${JSON.stringify({ disableStorage: 'must be a boolean', })}`, @@ -2710,7 +2709,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'tracer' for TracerConfigWrapper: ${TYPES.tracerType.error}, value: invalidTracerType`, ); } @@ -2729,7 +2728,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: ${TYPES.tracerConfig.error}, value: invalidTracerConfig`, ); } @@ -2748,7 +2747,7 @@ describe('RPC Server', function () { } catch (error: any) { BaseTest.invalidParamError( error.response, - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: ${ TYPES.tracerConfig.error }, value: ${JSON.stringify({ @@ -3114,7 +3113,7 @@ describe('RPC Server', function () { [], 400, BaseTest.invalidParamError.bind(BaseTest), - Constants.ERROR_CODE, + ERROR_CODE, MISSING_PARAM_ERROR + ' 0', ); }); @@ -3124,7 +3123,7 @@ describe('RPC Server', function () { ['not-a-block-number'], 400, BaseTest.invalidParamError.bind(BaseTest), - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 0: ${Constants.BLOCK_NUMBER_ERROR}, value: not-a-block-number`, ); }); @@ -3134,7 +3133,7 @@ describe('RPC Server', function () { [blockNumberHex, { tracer: 'invalidTracerType' }], 400, BaseTest.invalidParamError.bind(BaseTest), - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'tracer' for TracerConfigWrapper: ${TYPES.tracerType.error}, value: invalidTracerType`, ); }); @@ -3144,7 +3143,7 @@ describe('RPC Server', function () { [blockNumberHex, { tracer: TracerType.CallTracer, tracerConfig: 'not-an-object' }], 400, BaseTest.invalidParamError.bind(BaseTest), - Constants.ERROR_CODE, + ERROR_CODE, `Invalid parameter 'tracerConfig' for TracerConfigWrapper: ${TYPES.tracerConfig.error}, value: not-an-object`, ); }); From d5f18d1723706e8b469fc0aeb65c8f2d8f820ff7 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Fri, 4 Jul 2025 15:27:22 +0300 Subject: [PATCH 07/16] fixes failing test Signed-off-by: Konstantina Blazhukova --- packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts b/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts index 3b740dec91..cb1cf734d2 100644 --- a/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts +++ b/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts @@ -387,7 +387,7 @@ describe('RpcMethodDispatcher', () => { describe('End-to-end dispatch tests', () => { it('should handle INVALID_PARAMETERS error properly', async () => { validateParamsStub.throws(predefined.INVALID_PARAMETERS); - operationHandler[RPC_PARAM_VALIDATION_RULES_KEY] = { 0: { type: 'boolean' } }; + operationHandler[Validator.RPC_PARAM_VALIDATION_RULES_KEY] = { 0: { type: 'boolean' } }; const result = await dispatcher.dispatch(TEST_METHOD_NAME, ['false', null], TEST_REQUEST_DETAILS); expect(result).to.be.instanceOf(JsonRpcError); From 6457b73c84c822a9db3a701fcf6b9ad153914041 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Fri, 4 Jul 2025 15:28:05 +0300 Subject: [PATCH 08/16] removes unused vars Signed-off-by: Konstantina Blazhukova --- packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts b/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts index cb1cf734d2..09db64bf81 100644 --- a/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts +++ b/packages/relay/tests/lib/dispatcher/rpcMethodDispatcher.spec.ts @@ -52,7 +52,7 @@ describe('RpcMethodDispatcher', () => { // Set up args rearrangement mock arrangeRpcParamsStub = sinon.stub(Utils, 'arrangeRpcParams'); - arrangeRpcParamsStub.callsFake((method, params, requestDetails) => { + arrangeRpcParamsStub.callsFake((method) => { if (method.name === 'functionStub') { return TEST_PARAMS_REARRANGED; } From f8b369629e7144a3c1533d890cd31d22061da298 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Fri, 4 Jul 2025 17:52:27 +0300 Subject: [PATCH 09/16] removes required tracerConfigWrapper for traceTransaction Signed-off-by: Konstantina Blazhukova --- packages/relay/src/lib/debug.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/relay/src/lib/debug.ts b/packages/relay/src/lib/debug.ts index 34066f58e0..4893b03f29 100644 --- a/packages/relay/src/lib/debug.ts +++ b/packages/relay/src/lib/debug.ts @@ -106,7 +106,7 @@ export class DebugImpl implements Debug { @rpcMethod @rpcParamValidationRules({ 0: { type: 'transactionHash', required: true }, - 1: { type: 'tracerConfigWrapper', required: true }, + 1: { type: 'tracerConfigWrapper', required: false }, }) @rpcParamLayoutConfig(RPC_LAYOUT.custom((params) => [params[0], params[1]])) @cache(CacheService.getInstance(CACHE_LEVEL.L1)) From f5e08e8de92bf1a43cdd6ba2fa7490e1fb4b3f96 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Mon, 7 Jul 2025 14:00:50 +0300 Subject: [PATCH 10/16] addresses PR comments Signed-off-by: Konstantina Blazhukova --- packages/relay/src/lib/validators/objectTypes.ts | 6 ++---- packages/relay/src/lib/validators/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/relay/src/lib/validators/objectTypes.ts b/packages/relay/src/lib/validators/objectTypes.ts index 7d6cbc37df..232888ec19 100644 --- a/packages/relay/src/lib/validators/objectTypes.ts +++ b/packages/relay/src/lib/validators/objectTypes.ts @@ -202,17 +202,15 @@ export const OBJECTS_VALIDATIONS: { [key: string]: IObjectSchema } = { }; export function validateSchema(schema: IObjectSchema, object: any) { + const expectedParams = Object.keys(schema.properties); + const actualParams = Object.keys(object); if (schema.failOnUnexpectedParams) { - const expectedParams = Object.keys(schema.properties); - const actualParams = Object.keys(object); const unknownParam = actualParams.find((param) => !expectedParams.includes(param)); if (unknownParam) { throw predefined.INVALID_PARAMETER(`'${unknownParam}' for ${schema.name}`, `Unknown parameter`); } } if (schema.deleteUnknownProperties) { - const expectedParams = Object.keys(schema.properties); - const actualParams = Object.keys(object); const unknownParams = actualParams.filter((param) => !expectedParams.includes(param)); for (const param of unknownParams) { delete object[param]; diff --git a/packages/relay/src/lib/validators/types.ts b/packages/relay/src/lib/validators/types.ts index 3e4fe6eb43..0867e72645 100644 --- a/packages/relay/src/lib/validators/types.ts +++ b/packages/relay/src/lib/validators/types.ts @@ -3,7 +3,7 @@ import { predefined } from '../errors/JsonRpcError'; import { ICallTracerConfig, IOpcodeLoggerConfig, ITracerConfig, ITracerConfigWrapper } from '../types'; import * as Constants from './constants'; -import { OBJECTS_VALIDATIONS, validateSchema } from './objectTypes'; +import { OBJECTS_VALIDATIONS, validateSchema, validateTracerConfigWrapper } from './objectTypes'; import { validateArray } from './utils'; export const TYPES = { @@ -145,7 +145,7 @@ export const TYPES = { tracerConfigWrapper: { test: (param: any): param is ITracerConfigWrapper => { if (param && typeof param === 'object') { - return validateSchema(OBJECTS_VALIDATIONS.tracerConfigWrapper, param); + return validateTracerConfigWrapper(param); } return false; }, From f4c0d41a33acf0ce74b6b34ea3b0104cc11f22a7 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Mon, 7 Jul 2025 15:41:16 +0300 Subject: [PATCH 11/16] fixes test Signed-off-by: Konstantina Blazhukova --- packages/server/tests/integration/server.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/server/tests/integration/server.spec.ts b/packages/server/tests/integration/server.spec.ts index 4cb73f0387..7e9d158130 100644 --- a/packages/server/tests/integration/server.spec.ts +++ b/packages/server/tests/integration/server.spec.ts @@ -2579,7 +2579,7 @@ describe('RPC Server', function () { BaseTest.invalidParamError( error.response, ERROR_CODE, - `Invalid parameter 0: The value passed is not valid: invalidHash. ${Constants.TRANSACTION_HASH_ERROR}`, + `Invalid parameter 0: ${Constants.TRANSACTION_HASH_ERROR}, value: invalidHash`, ); } }); @@ -3301,6 +3301,8 @@ class BaseTest { static invalidParamError(response: any, code: number, message: string) { expect(response.status).to.eq(400); expect(response.statusText).to.eq('Bad Request'); + console.log('response', response); + console.log('message', message); this.errorResponseChecks(response, code, message); } From 291177779e0375c13766028a1e8db60a901ffd46 Mon Sep 17 00:00:00 2001 From: konstantinabl Date: Mon, 7 Jul 2025 19:43:34 +0300 Subject: [PATCH 12/16] Update type to unknown Co-authored-by: Luis Mastrangelo Signed-off-by: konstantinabl --- packages/relay/src/lib/validators/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/relay/src/lib/validators/types.ts b/packages/relay/src/lib/validators/types.ts index 0867e72645..be428d8365 100644 --- a/packages/relay/src/lib/validators/types.ts +++ b/packages/relay/src/lib/validators/types.ts @@ -153,7 +153,7 @@ export const TYPES = { }, } satisfies { [paramTypeName: string]: { - test: (param: any) => boolean; + test: (param: unknown) => boolean; error: string; }; }; From c982144ae5699db212413d0a1fdbc08f874330e2 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Mon, 7 Jul 2025 20:08:06 +0300 Subject: [PATCH 13/16] removes unused export of validateParam and adjusts test Signed-off-by: Konstantina Blazhukova --- packages/relay/src/lib/validators/index.ts | 2 +- .../lib/decorators/rpcParamSchema.spec.ts | 22 +++++-------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/packages/relay/src/lib/validators/index.ts b/packages/relay/src/lib/validators/index.ts index 75ce037361..5f1ffb66eb 100644 --- a/packages/relay/src/lib/validators/index.ts +++ b/packages/relay/src/lib/validators/index.ts @@ -69,7 +69,7 @@ export function validateParams(params: any[], indexes: { [index: number]: IParam } } -export function validateParam(index: number | string, param: any, validation: IParamValidation): void { +function validateParam(index: number | string, param: any, validation: IParamValidation): void { const paramType = Array.isArray(validation.type) ? validation.type.map((type) => TYPES[type]) : TYPES[validation.type]; diff --git a/packages/relay/tests/lib/decorators/rpcParamSchema.spec.ts b/packages/relay/tests/lib/decorators/rpcParamSchema.spec.ts index fc09a9fbbe..993b2929d0 100644 --- a/packages/relay/tests/lib/decorators/rpcParamSchema.spec.ts +++ b/packages/relay/tests/lib/decorators/rpcParamSchema.spec.ts @@ -4,12 +4,7 @@ import { expect } from 'chai'; import { describe, it } from 'mocha'; import sinon from 'sinon'; -import { - IParamValidation, - RPC_PARAM_VALIDATION_RULES_KEY, - rpcParamValidationRules, - validateParam, -} from '../../../src/lib/validators'; +import { IParamValidation, RPC_PARAM_VALIDATION_RULES_KEY, rpcParamValidationRules } from '../../../src/lib/validators'; import * as validator from '../../../src/lib/validators'; describe('rpcParamValidationRules decorator', () => { @@ -75,11 +70,11 @@ describe('rpcParamValidationRules decorator', () => { describe('Schema validation integration', () => { // Mock validation function for testing - let validateParamStub: sinon.SinonStub; + let validateParamsStub: sinon.SinonStub; beforeEach(() => { // Create a stub for the validateParam function from validators/utils - validateParamStub = sinon.stub(validator, 'validateParam'); + validateParamsStub = sinon.stub(validator, 'validateParams'); }); it('should allow schema retrieval for validation', () => { @@ -103,17 +98,10 @@ describe('rpcParamValidationRules decorator', () => { // Validate using the schema const params = ['0xaddress', '0xblock']; - - // Simulate validation with the schema - for (const [index, param] of params.entries()) { - if (schema[index]) { - validateParam(index, param, schema[index]); - } - } + validator.validateParams(params, schema); // Verify our validation stub was called with correct parameters - expect(validateParamStub.calledWith(0, '0xaddress', schema[0])).to.be.true; - expect(validateParamStub.calledWith(1, '0xblock', schema[1])).to.be.true; + expect(validateParamsStub.calledWith(['0xaddress', '0xblock'], schema)).to.be.true; }); }); From 8e0444aab81b725693cc71cb3ab5a8ce6880f459 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Mon, 7 Jul 2025 20:13:32 +0300 Subject: [PATCH 14/16] reverts change Signed-off-by: Konstantina Blazhukova --- packages/relay/src/lib/validators/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/relay/src/lib/validators/types.ts b/packages/relay/src/lib/validators/types.ts index be428d8365..0867e72645 100644 --- a/packages/relay/src/lib/validators/types.ts +++ b/packages/relay/src/lib/validators/types.ts @@ -153,7 +153,7 @@ export const TYPES = { }, } satisfies { [paramTypeName: string]: { - test: (param: unknown) => boolean; + test: (param: any) => boolean; error: string; }; }; From 5a6bbd7d9aceafb7a6ce99be8457852b18677d31 Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Mon, 7 Jul 2025 20:54:17 +0300 Subject: [PATCH 15/16] fixes debug acceptance Signed-off-by: Konstantina Blazhukova --- packages/server/tests/acceptance/debug.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/tests/acceptance/debug.spec.ts b/packages/server/tests/acceptance/debug.spec.ts index e43f18c08c..23612ff27b 100644 --- a/packages/server/tests/acceptance/debug.spec.ts +++ b/packages/server/tests/acceptance/debug.spec.ts @@ -520,7 +520,7 @@ describe('@debug API Acceptance Tests', function () { [invalidHash], predefined.INVALID_PARAMETER( 0, - 'The value passed is not valid: 0xinvalidhash. Expected Expected 0x prefixed string representing the hash (32 bytes) of a transaction OR Expected a transaction ID string in the format "shard.realm.num-sss-nnn" where sss are seconds and nnn are nanoseconds', + 'Expected Expected 0x prefixed string representing the hash (32 bytes) of a transaction, value: 0xinvalidhash', ), requestId, ); From 3efbd6da5e21574aed771e77af559b45a271161d Mon Sep 17 00:00:00 2001 From: Konstantina Blazhukova Date: Tue, 8 Jul 2025 16:47:30 +0300 Subject: [PATCH 16/16] removes comment Signed-off-by: Konstantina Blazhukova --- packages/relay/src/lib/validators/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/relay/src/lib/validators/types.ts b/packages/relay/src/lib/validators/types.ts index 0867e72645..4a7fbaebef 100644 --- a/packages/relay/src/lib/validators/types.ts +++ b/packages/relay/src/lib/validators/types.ts @@ -43,7 +43,6 @@ export const TYPES = { test: (param: any) => { if (Object.prototype.toString.call(param) === '[object Object]') { if (Object.prototype.hasOwnProperty.call(param, 'blockHash')) { - // if (param.hasOwnProperty('blockHash')) { return validateSchema(OBJECTS_VALIDATIONS.blockHashObject, param); } return validateSchema(OBJECTS_VALIDATIONS.blockNumberObject, param);