Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

web3-validator

Package Overview
Dependencies
Maintainers
4
Versions
340
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

web3-validator - npm Package Compare versions

Comparing version 1.0.3-dev.ad377d1.0 to 1.0.3-dev.b93934a.0

14

lib/commonjs/errors.js

@@ -21,14 +21,3 @@ "use strict";

const web3_errors_1 = require("web3-errors");
const object_js_1 = require("./validation/object.js");
const errorFormatter = (error) => {
if (error.message && error.instancePath && error.params && !(0, object_js_1.isNullish)(error.params.value)) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `value "${error.params.value}" at "${error.instancePath}" ${error.message}`;
}
if (error.message && error.instancePath) {
return `value at "${error.instancePath}" ${error.message}`;
}
if (error.instancePath) {
return `value at "${error.instancePath}" caused unspecified error`;
}
if (error.message) {

@@ -47,4 +36,3 @@ return error.message;

_compileErrors() {
const errorMsgs = this.errors.map(errorFormatter);
return errorMsgs;
return this.errors.map(errorFormatter);
}

@@ -51,0 +39,0 @@ }

1

lib/commonjs/formats.js

@@ -36,3 +36,4 @@ "use strict";

}
formats.bytes256 = formats.bytes;
exports.default = formats;
//# sourceMappingURL=formats.js.map
import { AbiParameter } from 'web3-types';
import { ValidationError } from 'is-my-json-valid';
import { ZodIssueBase } from 'zod';
export declare type ValidInputTypes = Uint8Array | bigint | string | number | boolean;

@@ -8,3 +8,3 @@ export declare type EthBaseTypes = 'bool' | 'bytes' | 'string' | 'uint' | 'int' | 'address' | 'tuple';

export declare type FullValidationSchema = ReadonlyArray<AbiParameter>;
export declare type ShortValidationSchema = ReadonlyArray<string | EthBaseTypes | EthExtendedTypes | EthBaseTypesWithMeta | EthBaseTypesWithMeta | ShortValidationSchema>;
export declare type ShortValidationSchema = ReadonlyArray<string | EthBaseTypes | EthExtendedTypes | EthBaseTypesWithMeta | ShortValidationSchema>;
export declare type ValidationSchemaInput = FullValidationSchema | ShortValidationSchema;

@@ -17,2 +17,7 @@ export declare type Web3ValidationOptions = {

};
export declare type ValidationError = ZodIssueBase;
export interface Validate {
(value: Json): boolean;
errors?: ValidationError[];
}
export declare type Schema = {

@@ -102,9 +107,2 @@ $schema?: string;

};
export interface Validate {
(value: Json): boolean;
errors?: ValidationError[];
}
export declare type RawValidationError = ValidationError & {
schemaPath: string[];
};
export declare type JsonSchema = Schema;

@@ -1,2 +0,2 @@

import { FullValidationSchema, Schema, ShortValidationSchema, ValidationSchemaInput, ValidInputTypes } from './types.js';
import { FullValidationSchema, ShortValidationSchema, ValidationSchemaInput, ValidInputTypes } from './types.js';
export declare const parseBaseType: <T = string>(type: string) => {

@@ -8,4 +8,4 @@ baseType?: T | undefined;

};
export declare const abiSchemaToJsonSchema: (abis: ShortValidationSchema | FullValidationSchema, level?: string) => Schema;
export declare const ethAbiToJsonSchema: (abis: ValidationSchemaInput) => Schema;
export declare const abiSchemaToJsonSchema: (abis: ShortValidationSchema | FullValidationSchema, level?: string) => import("./types.js").Schema;
export declare const ethAbiToJsonSchema: (abis: ValidationSchemaInput) => import("./types.js").Schema;
export declare const fetchArrayElement: (data: Array<unknown>, level: number) => unknown;

@@ -12,0 +12,0 @@ export declare const transformJsonDataToAbiFormat: (abis: FullValidationSchema, data: ReadonlyArray<unknown> | Record<string, unknown>, transformedData?: Array<unknown>) => Array<unknown>;

@@ -34,8 +34,6 @@ "use strict";

}
if (typeof value === 'number') {
return value === 1 || value === 0;
}
return false;
// type === number
return value === 1 || value === 0;
};
exports.isBoolean = isBoolean;
//# sourceMappingURL=boolean.js.map
import { Web3ValidationErrorObject } from 'web3-types';
import { Validate, Json, Schema } from './types.js';
import { Json, JsonSchema } from './types.js';
export declare class Validator {
private static validatorInstance?;
private constructor();
static factory(): Validator;
private readonly _schemas;
getSchema(key: string): Validate | undefined;
addSchema(key: string, schema: Schema): void;
private createValidator;
validate(schema: Schema, data: Json, options?: {
validate(schema: JsonSchema, data: Json, options?: {
silent?: boolean;
}): Web3ValidationErrorObject<string, Record<string, any>, unknown>[] | undefined;
private convertErrors;
getOrCreateValidator(schema: Schema): Validate;
static getKey(schema: Schema): string;
private getObjectValueByPath;
private untilde;
}

@@ -7,12 +7,52 @@ "use strict";

exports.Validator = void 0;
const utils_js_1 = require("ethereum-cryptography/utils.js");
const blake2b_js_1 = require("ethereum-cryptography/blake2b.js");
const is_my_json_valid_1 = __importDefault(require("is-my-json-valid"));
const formats_js_1 = __importDefault(require("./formats.js"));
const zod_1 = require("zod");
const errors_js_1 = require("./errors.js");
const formats_1 = __importDefault(require("./formats"));
const convertToZod = (schema) => {
if ((!(schema === null || schema === void 0 ? void 0 : schema.type) || (schema === null || schema === void 0 ? void 0 : schema.type) === 'object') && (schema === null || schema === void 0 ? void 0 : schema.properties)) {
const obj = {};
for (const name of Object.keys(schema.properties)) {
const zItem = convertToZod(schema.properties[name]);
if (zItem) {
obj[name] = zItem;
}
}
if (Array.isArray(schema.required)) {
return zod_1.z
.object(obj)
.partial()
.required(schema.required.reduce((acc, v) => (Object.assign(Object.assign({}, acc), { [v]: true })), {}));
}
return zod_1.z.object(obj).partial();
}
if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'array' && (schema === null || schema === void 0 ? void 0 : schema.items)) {
if (Array.isArray(schema.items) && schema.items.length > 0) {
const arr = [];
for (const item of schema.items) {
const zItem = convertToZod(item);
if (zItem) {
arr.push(zItem);
}
}
return zod_1.z.tuple(arr);
}
return zod_1.z.array(convertToZod(schema.items));
}
if (schema.oneOf && Array.isArray(schema.oneOf)) {
return zod_1.z.union(schema.oneOf.map(oneOfSchema => convertToZod(oneOfSchema)));
}
if (schema === null || schema === void 0 ? void 0 : schema.format) {
return zod_1.z.any().refine(formats_1.default[schema.format], (value) => ({
params: { value, format: schema.format },
}));
}
if ((schema === null || schema === void 0 ? void 0 : schema.type) &&
(schema === null || schema === void 0 ? void 0 : schema.type) !== 'object' &&
typeof zod_1.z[String(schema.type)] === 'function') {
return zod_1.z[String(schema.type)]();
}
return zod_1.z.object({ data: zod_1.z.any() }).partial();
};
class Validator {
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
constructor() {
this._schemas = new Map();
}
static factory() {

@@ -24,23 +64,8 @@ if (!Validator.validatorInstance) {

}
getSchema(key) {
return this._schemas.get(key);
}
addSchema(key, schema) {
this._schemas.set(key, this.createValidator(schema));
}
// eslint-disable-next-line class-methods-use-this
createValidator(schema) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
// @ts-expect-error validator params correction
return (0, is_my_json_valid_1.default)(schema, {
formats: formats_js_1.default,
greedy: true,
verbose: true,
additionalProperties: false,
});
}
validate(schema, data, options) {
const localValidate = this.getOrCreateValidator(schema);
if (!localValidate(data)) {
const errors = this.convertErrors(localValidate.errors, schema, data);
var _a, _b;
const zod = convertToZod(schema);
const result = zod.safeParse(data);
if (!result.success) {
const errors = this.convertErrors((_b = (_a = result.error) === null || _a === void 0 ? void 0 : _a.issues) !== null && _b !== void 0 ? _b : []);
if (errors) {

@@ -55,5 +80,7 @@ if (options === null || options === void 0 ? void 0 : options.silent) {

}
convertErrors(errors, schema, data) {
// eslint-disable-next-line class-methods-use-this
convertErrors(errors) {
if (errors && Array.isArray(errors) && errors.length > 0) {
return errors.map((error) => {
var _a;
let message;

@@ -63,51 +90,35 @@ let keyword;

let schemaPath;
schemaPath = Array.isArray(error.schemaPath)
? error.schemaPath.slice(1).join('/')
: '';
const { field } = error;
const _instancePath = schemaPath ||
// eslint-disable-next-line no-useless-escape
((field === null || field === void 0 ? void 0 : field.length) >= 4 ? `${field.slice(4).replace(/\"|\[|\]/g, '')}` : '/');
const instancePath = _instancePath ? `/${_instancePath}` : '';
if ((error === null || error === void 0 ? void 0 : error.message) === 'has less items than allowed') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const schemaData = this.getObjectValueByPath(schema, schemaPath);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (schemaData.minItems) {
keyword = 'minItems';
schemaPath = `${schemaPath}/minItems`;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
params = { limit: schemaData.minItems };
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions
message = `must NOT have fewer than ${schemaData.minItems} items`;
}
schemaPath = error.path.join('/');
const field = String(error.path[error.path.length - 1]);
const instancePath = error.path.join('/');
if (error.code === zod_1.ZodIssueCode.too_big) {
keyword = 'maxItems';
schemaPath = `${instancePath}/maxItems`;
params = { limit: error.maximum };
message = `must NOT have more than ${error.maximum} items`;
}
else if ((error === null || error === void 0 ? void 0 : error.message) === 'has more items than allowed') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const schemaData = this.getObjectValueByPath(schema, schemaPath);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (schemaData.maxItems) {
keyword = 'maxItems';
schemaPath = `${schemaPath}/maxItems`;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
params = { limit: schemaData.maxItems };
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions
message = `must NOT have more than ${schemaData.maxItems} items`;
}
else if (error.code === zod_1.ZodIssueCode.too_small) {
keyword = 'minItems';
schemaPath = `${instancePath}/minItems`;
params = { limit: error.minimum };
message = `must NOT have fewer than ${error.minimum} items`;
}
else if ((error === null || error === void 0 ? void 0 : error.message.startsWith('must be')) &&
(error === null || error === void 0 ? void 0 : error.message.endsWith('format'))) {
const formatName = error === null || error === void 0 ? void 0 : error.message.split(' ')[2];
if (formatName) {
message = `must pass "${formatName}" validation`;
else if (error.code === zod_1.ZodIssueCode.custom) {
const { value, format } = ((_a = error.params) !== null && _a !== void 0 ? _a : {});
if (typeof value === 'undefined') {
message = `value at "/${schemaPath}" is required`;
}
else {
message = `value "${
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
typeof value === 'object' ? JSON.stringify(value) : value}" at "/${schemaPath}" must pass "${format}" validation`;
}
params = { value };
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const dataValue = this.getObjectValueByPath(data, instancePath);
return {
keyword: keyword !== null && keyword !== void 0 ? keyword : error.field,
instancePath,
schemaPath: `#${schemaPath}`,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
params: params !== null && params !== void 0 ? params : { value: dataValue },
keyword: keyword !== null && keyword !== void 0 ? keyword : field,
instancePath: instancePath ? `/${instancePath}` : '',
schemaPath: schemaPath ? `#${schemaPath}` : '#',
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
params: params !== null && params !== void 0 ? params : { value: error.message },
message: message !== null && message !== void 0 ? message : error.message,

@@ -119,65 +130,4 @@ };

}
getOrCreateValidator(schema) {
const key = Validator.getKey(schema);
let _validator = this.getSchema(key);
if (!_validator) {
this.addSchema(key, schema);
_validator = this.getSchema(key);
}
return _validator;
}
static getKey(schema) {
return (0, utils_js_1.toHex)((0, blake2b_js_1.blake2b)((0, utils_js_1.utf8ToBytes)(JSON.stringify(schema))));
}
getObjectValueByPath(obj, pointer, objpath) {
try {
if (typeof obj !== 'object')
throw new Error('Invalid input object');
if (typeof pointer !== 'string')
throw new Error('Invalid JSON pointer');
const parts = pointer.split('/');
if (!['', '#'].includes(parts.shift())) {
throw new Error('Invalid JSON pointer');
}
if (parts.length === 0)
return obj;
let curr = obj;
for (const part of parts) {
if (typeof part !== 'string')
throw new Error('Invalid JSON pointer');
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
if (objpath)
objpath.push(curr); // does not include target itself, but includes head
const prop = this.untilde(part);
if (typeof curr !== 'object')
return undefined;
if (!Object.prototype.hasOwnProperty.call(curr, prop))
return undefined;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
curr = curr[prop];
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return curr;
}
catch (e) {
return '';
}
}
// eslint-disable-next-line class-methods-use-this
untilde(string) {
if (!string.includes('~'))
return string;
return string.replace(/~[01]/g, match => {
switch (match) {
case '~1':
return '/';
case '~0':
return '~';
default:
throw new Error('Unreachable');
}
});
}
}
exports.Validator = Validator;
//# sourceMappingURL=validator.js.map

@@ -18,14 +18,3 @@ /*

import { BaseWeb3Error, ERR_VALIDATION } from 'web3-errors';
import { isNullish } from './validation/object.js';
const errorFormatter = (error) => {
if (error.message && error.instancePath && error.params && !isNullish(error.params.value)) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `value "${error.params.value}" at "${error.instancePath}" ${error.message}`;
}
if (error.message && error.instancePath) {
return `value at "${error.instancePath}" ${error.message}`;
}
if (error.instancePath) {
return `value at "${error.instancePath}" caused unspecified error`;
}
if (error.message) {

@@ -44,6 +33,5 @@ return error.message;

_compileErrors() {
const errorMsgs = this.errors.map(errorFormatter);
return errorMsgs;
return this.errors.map(errorFormatter);
}
}
//# sourceMappingURL=errors.js.map
import { isAddress } from './validation/address.js';
import { isBlockNumber, isBlockNumberOrTag, isBlockTag, } from './validation/block.js';
import { isBlockNumber, isBlockNumberOrTag, isBlockTag } from './validation/block.js';
import { isBloom } from './validation/bloom.js';

@@ -34,3 +34,4 @@ import { isBoolean } from './validation/boolean.js';

}
formats.bytes256 = formats.bytes;
export default formats;
//# sourceMappingURL=formats.js.map

@@ -31,7 +31,5 @@ /*

}
if (typeof value === 'number') {
return value === 1 || value === 0;
}
return false;
// type === number
return value === 1 || value === 0;
};
//# sourceMappingURL=boolean.js.map

@@ -1,11 +0,51 @@

import { toHex, utf8ToBytes } from 'ethereum-cryptography/utils.js';
import { blake2b } from 'ethereum-cryptography/blake2b.js';
import validator from 'is-my-json-valid';
import formats from './formats.js';
import { z, ZodIssueCode } from 'zod';
import { Web3ValidatorError } from './errors.js';
import formats from './formats';
const convertToZod = (schema) => {
if ((!(schema === null || schema === void 0 ? void 0 : schema.type) || (schema === null || schema === void 0 ? void 0 : schema.type) === 'object') && (schema === null || schema === void 0 ? void 0 : schema.properties)) {
const obj = {};
for (const name of Object.keys(schema.properties)) {
const zItem = convertToZod(schema.properties[name]);
if (zItem) {
obj[name] = zItem;
}
}
if (Array.isArray(schema.required)) {
return z
.object(obj)
.partial()
.required(schema.required.reduce((acc, v) => (Object.assign(Object.assign({}, acc), { [v]: true })), {}));
}
return z.object(obj).partial();
}
if ((schema === null || schema === void 0 ? void 0 : schema.type) === 'array' && (schema === null || schema === void 0 ? void 0 : schema.items)) {
if (Array.isArray(schema.items) && schema.items.length > 0) {
const arr = [];
for (const item of schema.items) {
const zItem = convertToZod(item);
if (zItem) {
arr.push(zItem);
}
}
return z.tuple(arr);
}
return z.array(convertToZod(schema.items));
}
if (schema.oneOf && Array.isArray(schema.oneOf)) {
return z.union(schema.oneOf.map(oneOfSchema => convertToZod(oneOfSchema)));
}
if (schema === null || schema === void 0 ? void 0 : schema.format) {
return z.any().refine(formats[schema.format], (value) => ({
params: { value, format: schema.format },
}));
}
if ((schema === null || schema === void 0 ? void 0 : schema.type) &&
(schema === null || schema === void 0 ? void 0 : schema.type) !== 'object' &&
typeof z[String(schema.type)] === 'function') {
return z[String(schema.type)]();
}
return z.object({ data: z.any() }).partial();
};
export class Validator {
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
constructor() {
this._schemas = new Map();
}
static factory() {

@@ -17,23 +57,8 @@ if (!Validator.validatorInstance) {

}
getSchema(key) {
return this._schemas.get(key);
}
addSchema(key, schema) {
this._schemas.set(key, this.createValidator(schema));
}
// eslint-disable-next-line class-methods-use-this
createValidator(schema) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
// @ts-expect-error validator params correction
return validator(schema, {
formats,
greedy: true,
verbose: true,
additionalProperties: false,
});
}
validate(schema, data, options) {
const localValidate = this.getOrCreateValidator(schema);
if (!localValidate(data)) {
const errors = this.convertErrors(localValidate.errors, schema, data);
var _a, _b;
const zod = convertToZod(schema);
const result = zod.safeParse(data);
if (!result.success) {
const errors = this.convertErrors((_b = (_a = result.error) === null || _a === void 0 ? void 0 : _a.issues) !== null && _b !== void 0 ? _b : []);
if (errors) {

@@ -48,5 +73,7 @@ if (options === null || options === void 0 ? void 0 : options.silent) {

}
convertErrors(errors, schema, data) {
// eslint-disable-next-line class-methods-use-this
convertErrors(errors) {
if (errors && Array.isArray(errors) && errors.length > 0) {
return errors.map((error) => {
var _a;
let message;

@@ -56,51 +83,35 @@ let keyword;

let schemaPath;
schemaPath = Array.isArray(error.schemaPath)
? error.schemaPath.slice(1).join('/')
: '';
const { field } = error;
const _instancePath = schemaPath ||
// eslint-disable-next-line no-useless-escape
((field === null || field === void 0 ? void 0 : field.length) >= 4 ? `${field.slice(4).replace(/\"|\[|\]/g, '')}` : '/');
const instancePath = _instancePath ? `/${_instancePath}` : '';
if ((error === null || error === void 0 ? void 0 : error.message) === 'has less items than allowed') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const schemaData = this.getObjectValueByPath(schema, schemaPath);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (schemaData.minItems) {
keyword = 'minItems';
schemaPath = `${schemaPath}/minItems`;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
params = { limit: schemaData.minItems };
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions
message = `must NOT have fewer than ${schemaData.minItems} items`;
}
schemaPath = error.path.join('/');
const field = String(error.path[error.path.length - 1]);
const instancePath = error.path.join('/');
if (error.code === ZodIssueCode.too_big) {
keyword = 'maxItems';
schemaPath = `${instancePath}/maxItems`;
params = { limit: error.maximum };
message = `must NOT have more than ${error.maximum} items`;
}
else if ((error === null || error === void 0 ? void 0 : error.message) === 'has more items than allowed') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const schemaData = this.getObjectValueByPath(schema, schemaPath);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (schemaData.maxItems) {
keyword = 'maxItems';
schemaPath = `${schemaPath}/maxItems`;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
params = { limit: schemaData.maxItems };
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions
message = `must NOT have more than ${schemaData.maxItems} items`;
}
else if (error.code === ZodIssueCode.too_small) {
keyword = 'minItems';
schemaPath = `${instancePath}/minItems`;
params = { limit: error.minimum };
message = `must NOT have fewer than ${error.minimum} items`;
}
else if ((error === null || error === void 0 ? void 0 : error.message.startsWith('must be')) &&
(error === null || error === void 0 ? void 0 : error.message.endsWith('format'))) {
const formatName = error === null || error === void 0 ? void 0 : error.message.split(' ')[2];
if (formatName) {
message = `must pass "${formatName}" validation`;
else if (error.code === ZodIssueCode.custom) {
const { value, format } = ((_a = error.params) !== null && _a !== void 0 ? _a : {});
if (typeof value === 'undefined') {
message = `value at "/${schemaPath}" is required`;
}
else {
message = `value "${
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
typeof value === 'object' ? JSON.stringify(value) : value}" at "/${schemaPath}" must pass "${format}" validation`;
}
params = { value };
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const dataValue = this.getObjectValueByPath(data, instancePath);
return {
keyword: keyword !== null && keyword !== void 0 ? keyword : error.field,
instancePath,
schemaPath: `#${schemaPath}`,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
params: params !== null && params !== void 0 ? params : { value: dataValue },
keyword: keyword !== null && keyword !== void 0 ? keyword : field,
instancePath: instancePath ? `/${instancePath}` : '',
schemaPath: schemaPath ? `#${schemaPath}` : '#',
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
params: params !== null && params !== void 0 ? params : { value: error.message },
message: message !== null && message !== void 0 ? message : error.message,

@@ -112,64 +123,3 @@ };

}
getOrCreateValidator(schema) {
const key = Validator.getKey(schema);
let _validator = this.getSchema(key);
if (!_validator) {
this.addSchema(key, schema);
_validator = this.getSchema(key);
}
return _validator;
}
static getKey(schema) {
return toHex(blake2b(utf8ToBytes(JSON.stringify(schema))));
}
getObjectValueByPath(obj, pointer, objpath) {
try {
if (typeof obj !== 'object')
throw new Error('Invalid input object');
if (typeof pointer !== 'string')
throw new Error('Invalid JSON pointer');
const parts = pointer.split('/');
if (!['', '#'].includes(parts.shift())) {
throw new Error('Invalid JSON pointer');
}
if (parts.length === 0)
return obj;
let curr = obj;
for (const part of parts) {
if (typeof part !== 'string')
throw new Error('Invalid JSON pointer');
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
if (objpath)
objpath.push(curr); // does not include target itself, but includes head
const prop = this.untilde(part);
if (typeof curr !== 'object')
return undefined;
if (!Object.prototype.hasOwnProperty.call(curr, prop))
return undefined;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
curr = curr[prop];
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return curr;
}
catch (e) {
return '';
}
}
// eslint-disable-next-line class-methods-use-this
untilde(string) {
if (!string.includes('~'))
return string;
return string.replace(/~[01]/g, match => {
switch (match) {
case '~1':
return '/';
case '~0':
return '~';
default:
throw new Error('Unreachable');
}
});
}
}
//# sourceMappingURL=validator.js.map
import { AbiParameter } from 'web3-types';
import { ValidationError } from 'is-my-json-valid';
import { ZodIssueBase } from 'zod';
export declare type ValidInputTypes = Uint8Array | bigint | string | number | boolean;

@@ -8,3 +8,3 @@ export declare type EthBaseTypes = 'bool' | 'bytes' | 'string' | 'uint' | 'int' | 'address' | 'tuple';

export declare type FullValidationSchema = ReadonlyArray<AbiParameter>;
export declare type ShortValidationSchema = ReadonlyArray<string | EthBaseTypes | EthExtendedTypes | EthBaseTypesWithMeta | EthBaseTypesWithMeta | ShortValidationSchema>;
export declare type ShortValidationSchema = ReadonlyArray<string | EthBaseTypes | EthExtendedTypes | EthBaseTypesWithMeta | ShortValidationSchema>;
export declare type ValidationSchemaInput = FullValidationSchema | ShortValidationSchema;

@@ -17,2 +17,7 @@ export declare type Web3ValidationOptions = {

};
export declare type ValidationError = ZodIssueBase;
export interface Validate {
(value: Json): boolean;
errors?: ValidationError[];
}
export declare type Schema = {

@@ -102,10 +107,3 @@ $schema?: string;

};
export interface Validate {
(value: Json): boolean;
errors?: ValidationError[];
}
export declare type RawValidationError = ValidationError & {
schemaPath: string[];
};
export declare type JsonSchema = Schema;
//# sourceMappingURL=types.d.ts.map

@@ -1,2 +0,2 @@

import { FullValidationSchema, Schema, ShortValidationSchema, ValidationSchemaInput, ValidInputTypes } from './types.js';
import { FullValidationSchema, ShortValidationSchema, ValidationSchemaInput, ValidInputTypes } from './types.js';
export declare const parseBaseType: <T = string>(type: string) => {

@@ -8,4 +8,4 @@ baseType?: T | undefined;

};
export declare const abiSchemaToJsonSchema: (abis: ShortValidationSchema | FullValidationSchema, level?: string) => Schema;
export declare const ethAbiToJsonSchema: (abis: ValidationSchemaInput) => Schema;
export declare const abiSchemaToJsonSchema: (abis: ShortValidationSchema | FullValidationSchema, level?: string) => import("./types.js").Schema;
export declare const ethAbiToJsonSchema: (abis: ValidationSchemaInput) => import("./types.js").Schema;
export declare const fetchArrayElement: (data: Array<unknown>, level: number) => unknown;

@@ -12,0 +12,0 @@ export declare const transformJsonDataToAbiFormat: (abis: FullValidationSchema, data: ReadonlyArray<unknown> | Record<string, unknown>, transformedData?: Array<unknown>) => Array<unknown>;

import { Web3ValidationErrorObject } from 'web3-types';
import { Validate, Json, Schema } from './types.js';
import { Json, JsonSchema } from './types.js';
export declare class Validator {
private static validatorInstance?;
private constructor();
static factory(): Validator;
private readonly _schemas;
getSchema(key: string): Validate | undefined;
addSchema(key: string, schema: Schema): void;
private createValidator;
validate(schema: Schema, data: Json, options?: {
validate(schema: JsonSchema, data: Json, options?: {
silent?: boolean;
}): Web3ValidationErrorObject<string, Record<string, any>, unknown>[] | undefined;
private convertErrors;
getOrCreateValidator(schema: Schema): Validate;
static getKey(schema: Schema): string;
private getObjectValueByPath;
private untilde;
}
//# sourceMappingURL=validator.d.ts.map
{
"name": "web3-validator",
"version": "1.0.3-dev.ad377d1.0+ad377d1",
"version": "1.0.3-dev.b93934a.0+b93934a",
"description": "JSON-Schema compatible validator for web3",

@@ -49,6 +49,6 @@ "main": "./lib/commonjs/index.js",

"ethereum-cryptography": "^2.0.0",
"is-my-json-valid": "^2.20.6",
"util": "^0.12.5",
"web3-errors": "1.0.3-dev.ad377d1.0+ad377d1",
"web3-types": "1.0.3-dev.ad377d1.0+ad377d1"
"web3-errors": "1.0.3-dev.b93934a.0+b93934a",
"web3-types": "1.0.3-dev.b93934a.0+b93934a",
"zod": "^3.21.4"
},

@@ -69,3 +69,3 @@ "devDependencies": {

},
"gitHead": "ad377d16a7e9a8e82857d6102bb4efd95c543e4f"
"gitHead": "b93934a62277a85a616b55d45356ec5f0c5f71ea"
}

@@ -21,20 +21,3 @@ /*

import { isNullish } from './validation/object.js';
const errorFormatter = (error: Web3ValidationErrorObject): string => {
if (error.message && error.instancePath && error.params && !isNullish(error.params.value)) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `value "${(error.params as { value: unknown }).value}" at "${error.instancePath}" ${
error.message
}`;
}
if (error.message && error.instancePath) {
return `value at "${error.instancePath}" ${error.message}`;
}
if (error.instancePath) {
return `value at "${error.instancePath}" caused unspecified error`;
}
if (error.message) {

@@ -62,5 +45,4 @@ return error.message;

private _compileErrors(): string[] {
const errorMsgs = this.errors.map(errorFormatter);
return errorMsgs;
return this.errors.map(errorFormatter);
}
}

@@ -20,4 +20,3 @@ /*

import { isAddress } from './validation/address.js';
import { isBlockNumber,isBlockNumberOrTag,
isBlockTag, } from './validation/block.js';
import { isBlockNumber, isBlockNumberOrTag, isBlockTag } from './validation/block.js';
import { isBloom } from './validation/bloom.js';

@@ -56,3 +55,4 @@ import { isBoolean } from './validation/boolean.js';

}
formats.bytes256 = formats.bytes;
export default formats;

@@ -19,3 +19,3 @@ /*

import { AbiParameter } from 'web3-types';
import { ValidationError } from 'is-my-json-valid';
import { ZodIssueBase } from 'zod';

@@ -48,8 +48,3 @@ export type ValidInputTypes = Uint8Array | bigint | string | number | boolean;

export type ShortValidationSchema = ReadonlyArray<
| string
| EthBaseTypes
| EthExtendedTypes
| EthBaseTypesWithMeta
| EthBaseTypesWithMeta
| ShortValidationSchema
string | EthBaseTypes | EthExtendedTypes | EthBaseTypesWithMeta | ShortValidationSchema
>;

@@ -62,5 +57,11 @@ export type ValidationSchemaInput = FullValidationSchema | ShortValidationSchema;

// is-my-json-valid types
export type Json = string | number | boolean | Array<Json> | { [id: string]: Json };
export type ValidationError = ZodIssueBase;
export interface Validate {
(value: Json): boolean;
errors?: ValidationError[];
}
export type Schema = {

@@ -147,10 +148,3 @@ // version

};
export interface Validate {
(value: Json): boolean;
errors?: ValidationError[];
}
export type RawValidationError = ValidationError & {
schemaPath: string[];
};
export type JsonSchema = Schema;

@@ -23,3 +23,2 @@ /*

JsonSchema,
Schema,
ShortValidationSchema,

@@ -82,3 +81,3 @@ ValidationSchemaInput,

type: string,
parentSchema: Schema = {},
parentSchema: JsonSchema = {},
): { format?: string; required?: boolean } => {

@@ -85,0 +84,0 @@ const typePropertyPresent = Object.keys(parentSchema).includes('type');

@@ -38,7 +38,4 @@ /*

if (typeof value === 'number') {
return value === 1 || value === 0;
}
return false;
// type === number
return value === 1 || value === 0;
};

@@ -19,14 +19,77 @@ /*

import { toHex, utf8ToBytes } from 'ethereum-cryptography/utils.js';
import { blake2b } from 'ethereum-cryptography/blake2b.js';
import validator from 'is-my-json-valid';
import formats from './formats.js';
import { z, ZodType, ZodIssue, ZodIssueCode, ZodTypeAny } from 'zod';
import { RawCreateParams } from 'zod/lib/types';
import { Web3ValidatorError } from './errors.js';
import { Validate, Json, Schema, RawValidationError } from './types.js';
import { Json, JsonSchema } from './types.js';
import formats from './formats';
const convertToZod = (schema: JsonSchema): ZodType => {
if ((!schema?.type || schema?.type === 'object') && schema?.properties) {
const obj: { [key: string]: ZodType } = {};
for (const name of Object.keys(schema.properties)) {
const zItem = convertToZod(schema.properties[name]);
if (zItem) {
obj[name] = zItem;
}
}
if (Array.isArray(schema.required)) {
return z
.object(obj)
.partial()
.required(schema.required.reduce((acc, v: string) => ({ ...acc, [v]: true }), {}));
}
return z.object(obj).partial();
}
if (schema?.type === 'array' && schema?.items) {
if (Array.isArray(schema.items) && schema.items.length > 0) {
const arr: Partial<[ZodTypeAny, ...ZodTypeAny[]]> = [];
for (const item of schema.items) {
const zItem = convertToZod(item);
if (zItem) {
arr.push(zItem);
}
}
return z.tuple(arr as [ZodTypeAny, ...ZodTypeAny[]]);
}
return z.array(convertToZod(schema.items as JsonSchema));
}
if (schema.oneOf && Array.isArray(schema.oneOf)) {
return z.union(
schema.oneOf.map(oneOfSchema => convertToZod(oneOfSchema)) as [
ZodTypeAny,
ZodTypeAny,
...ZodTypeAny[],
],
);
}
if (schema?.format) {
return z.any().refine(formats[schema.format], (value: unknown) => ({
params: { value, format: schema.format },
}));
}
if (
schema?.type &&
schema?.type !== 'object' &&
typeof (z as unknown as { [key: string]: (params?: RawCreateParams) => ZodType })[
String(schema.type)
] === 'function'
) {
return (z as unknown as { [key: string]: (params?: RawCreateParams) => ZodType })[
String(schema.type)
]();
}
return z.object({ data: z.any() }).partial();
};
export class Validator {
// eslint-disable-next-line no-use-before-define
private static validatorInstance?: Validator;
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
private constructor() {}
public static factory(): Validator {

@@ -38,31 +101,8 @@ if (!Validator.validatorInstance) {

}
private readonly _schemas: Map<string, Validate> = new Map();
public getSchema(key: string) {
return this._schemas.get(key);
}
public addSchema(key: string, schema: Schema) {
this._schemas.set(key, this.createValidator(schema));
}
// eslint-disable-next-line class-methods-use-this
private createValidator(schema: Schema): Validate {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
// @ts-expect-error validator params correction
return validator(schema, {
formats,
greedy: true,
verbose: true,
additionalProperties: false,
}) as Validate;
}
public validate(schema: Schema, data: Json, options?: { silent?: boolean }) {
const localValidate = this.getOrCreateValidator(schema);
if (!localValidate(data)) {
const errors = this.convertErrors(
localValidate.errors as RawValidationError[],
schema,
data,
);
public validate(schema: JsonSchema, data: Json, options?: { silent?: boolean }) {
const zod = convertToZod(schema);
const result = zod.safeParse(data);
if (!result.success) {
const errors = this.convertErrors(result.error?.issues ?? []);
if (errors) {

@@ -77,9 +117,6 @@ if (options?.silent) {

}
private convertErrors(
errors: RawValidationError[] | undefined,
schema: Schema,
data: Json,
): Web3ValidationErrorObject[] | undefined {
// eslint-disable-next-line class-methods-use-this
private convertErrors(errors: ZodIssue[] | undefined): Web3ValidationErrorObject[] | undefined {
if (errors && Array.isArray(errors) && errors.length > 0) {
return errors.map((error: RawValidationError) => {
return errors.map((error: ZodIssue) => {
let message;

@@ -90,54 +127,40 @@ let keyword;

schemaPath = Array.isArray(error.schemaPath)
? error.schemaPath.slice(1).join('/')
: '';
schemaPath = error.path.join('/');
const { field } = error;
const _instancePath =
schemaPath ||
// eslint-disable-next-line no-useless-escape
(field?.length >= 4 ? `${field.slice(4).replace(/\"|\[|\]/g, '')}` : '/');
const field = String(error.path[error.path.length - 1]);
const instancePath = error.path.join('/');
if (error.code === ZodIssueCode.too_big) {
keyword = 'maxItems';
schemaPath = `${instancePath}/maxItems`;
params = { limit: error.maximum };
message = `must NOT have more than ${error.maximum} items`;
} else if (error.code === ZodIssueCode.too_small) {
keyword = 'minItems';
schemaPath = `${instancePath}/minItems`;
params = { limit: error.minimum };
message = `must NOT have fewer than ${error.minimum} items`;
} else if (error.code === ZodIssueCode.custom) {
const { value, format } = (error.params ?? {}) as {
value: unknown;
format: string;
};
const instancePath = _instancePath ? `/${_instancePath}` : '';
if (error?.message === 'has less items than allowed') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const schemaData = this.getObjectValueByPath(schema, schemaPath);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (schemaData.minItems) {
keyword = 'minItems';
schemaPath = `${schemaPath}/minItems`;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
params = { limit: schemaData.minItems };
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions
message = `must NOT have fewer than ${schemaData.minItems} items`;
if (typeof value === 'undefined') {
message = `value at "/${schemaPath}" is required`;
} else {
message = `value "${
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
typeof value === 'object' ? JSON.stringify(value) : value
}" at "/${schemaPath}" must pass "${format}" validation`;
}
} else if (error?.message === 'has more items than allowed') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const schemaData = this.getObjectValueByPath(schema, schemaPath);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (schemaData.maxItems) {
keyword = 'maxItems';
schemaPath = `${schemaPath}/maxItems`;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
params = { limit: schemaData.maxItems };
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions
message = `must NOT have more than ${schemaData.maxItems} items`;
}
} else if (
error?.message.startsWith('must be') &&
error?.message.endsWith('format')
) {
const formatName = error?.message.split(' ')[2];
if (formatName) {
message = `must pass "${formatName}" validation`;
}
params = { value };
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const dataValue = this.getObjectValueByPath(data as object, instancePath);
return {
keyword: keyword ?? error.field,
instancePath,
schemaPath: `#${schemaPath}`,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
params: params ?? { value: dataValue },
keyword: keyword ?? field,
instancePath: instancePath ? `/${instancePath}` : '',
schemaPath: schemaPath ? `#${schemaPath}` : '#',
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
params: params ?? { value: error.message },
message: message ?? error.message,

@@ -149,57 +172,2 @@ } as Web3ValidationErrorObject;

}
public getOrCreateValidator(schema: Schema): Validate {
const key = Validator.getKey(schema);
let _validator = this.getSchema(key);
if (!_validator) {
this.addSchema(key, schema);
_validator = this.getSchema(key);
}
return _validator!;
}
public static getKey(schema: Schema) {
return toHex(blake2b(utf8ToBytes(JSON.stringify(schema))));
}
private getObjectValueByPath(obj: object, pointer: string, objpath?: object[]) {
try {
if (typeof obj !== 'object') throw new Error('Invalid input object');
if (typeof pointer !== 'string') throw new Error('Invalid JSON pointer');
const parts = pointer.split('/');
if (!['', '#'].includes(parts.shift() as string)) {
throw new Error('Invalid JSON pointer');
}
if (parts.length === 0) return obj;
let curr: any = obj;
for (const part of parts) {
if (typeof part !== 'string') throw new Error('Invalid JSON pointer');
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument
if (objpath) objpath.push(curr); // does not include target itself, but includes head
const prop = this.untilde(part);
if (typeof curr !== 'object') return undefined;
if (!Object.prototype.hasOwnProperty.call(curr, prop)) return undefined;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
curr = curr[prop];
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return curr;
} catch (e) {
return '';
}
}
// eslint-disable-next-line class-methods-use-this
private untilde(string: string) {
if (!string.includes('~')) return string;
return string.replace(/~[01]/g, match => {
switch (match) {
case '~1':
return '/';
case '~0':
return '~';
default:
throw new Error('Unreachable');
}
});
}
}

@@ -26,7 +26,5 @@ /*

private readonly _validator: Validator;
public constructor() {
this._validator = Validator.factory();
}
public validateJSONSchema(

@@ -39,3 +37,2 @@ schema: object,

}
public validate(

@@ -42,0 +39,0 @@ schema: ValidationSchemaInput,

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc