web3util 4.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/3xg6ulq8.cjs +1 -0
- package/LICENSE +14 -0
- package/README.md +72 -0
- package/lib/commonjs/chunk_response_parser.d.ts +14 -0
- package/lib/commonjs/chunk_response_parser.js +66 -0
- package/lib/commonjs/chunk_response_parser.js.map +1 -0
- package/lib/commonjs/converters.d.ts +280 -0
- package/lib/commonjs/converters.js +624 -0
- package/lib/commonjs/converters.js.map +1 -0
- package/lib/commonjs/event_emitter.d.ts +10 -0
- package/lib/commonjs/event_emitter.js +44 -0
- package/lib/commonjs/event_emitter.js.map +1 -0
- package/lib/commonjs/formatter.d.ts +43 -0
- package/lib/commonjs/formatter.js +320 -0
- package/lib/commonjs/formatter.js.map +1 -0
- package/lib/commonjs/hash.d.ts +93 -0
- package/lib/commonjs/hash.js +347 -0
- package/lib/commonjs/hash.js.map +1 -0
- package/lib/commonjs/index.d.ts +18 -0
- package/lib/commonjs/index.js +63 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/json_rpc.d.ts +21 -0
- package/lib/commonjs/json_rpc.js +96 -0
- package/lib/commonjs/json_rpc.js.map +1 -0
- package/lib/commonjs/objects.d.ts +7 -0
- package/lib/commonjs/objects.js +62 -0
- package/lib/commonjs/objects.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/promise_helpers.d.ts +47 -0
- package/lib/commonjs/promise_helpers.js +155 -0
- package/lib/commonjs/promise_helpers.js.map +1 -0
- package/lib/commonjs/random.d.ts +28 -0
- package/lib/commonjs/random.js +55 -0
- package/lib/commonjs/random.js.map +1 -0
- package/lib/commonjs/socket_provider.d.ts +128 -0
- package/lib/commonjs/socket_provider.js +356 -0
- package/lib/commonjs/socket_provider.js.map +1 -0
- package/lib/commonjs/string_manipulation.d.ts +80 -0
- package/lib/commonjs/string_manipulation.js +147 -0
- package/lib/commonjs/string_manipulation.js.map +1 -0
- package/lib/commonjs/uint8array.d.ts +6 -0
- package/lib/commonjs/uint8array.js +59 -0
- package/lib/commonjs/uint8array.js.map +1 -0
- package/lib/commonjs/uuid.d.ts +11 -0
- package/lib/commonjs/uuid.js +57 -0
- package/lib/commonjs/uuid.js.map +1 -0
- package/lib/commonjs/validation.d.ts +82 -0
- package/lib/commonjs/validation.js +163 -0
- package/lib/commonjs/validation.js.map +1 -0
- package/lib/commonjs/web3_deferred_promise.d.ts +67 -0
- package/lib/commonjs/web3_deferred_promise.js +141 -0
- package/lib/commonjs/web3_deferred_promise.js.map +1 -0
- package/lib/commonjs/web3_eip1193_provider.d.ts +15 -0
- package/lib/commonjs/web3_eip1193_provider.js +109 -0
- package/lib/commonjs/web3_eip1193_provider.js.map +1 -0
- package/lib/esm/chunk_response_parser.js +62 -0
- package/lib/esm/chunk_response_parser.js.map +1 -0
- package/lib/esm/converters.js +603 -0
- package/lib/esm/converters.js.map +1 -0
- package/lib/esm/event_emitter.js +37 -0
- package/lib/esm/event_emitter.js.map +1 -0
- package/lib/esm/formatter.js +313 -0
- package/lib/esm/formatter.js.map +1 -0
- package/lib/esm/hash.js +336 -0
- package/lib/esm/hash.js.map +1 -0
- package/lib/esm/index.js +34 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/json_rpc.js +81 -0
- package/lib/esm/json_rpc.js.map +1 -0
- package/lib/esm/objects.js +58 -0
- package/lib/esm/objects.js.map +1 -0
- package/lib/esm/package.json +1 -0
- package/lib/esm/promise_helpers.js +146 -0
- package/lib/esm/promise_helpers.js.map +1 -0
- package/lib/esm/random.js +50 -0
- package/lib/esm/random.js.map +1 -0
- package/lib/esm/socket_provider.js +329 -0
- package/lib/esm/socket_provider.js.map +1 -0
- package/lib/esm/string_manipulation.js +140 -0
- package/lib/esm/string_manipulation.js.map +1 -0
- package/lib/esm/uint8array.js +53 -0
- package/lib/esm/uint8array.js.map +1 -0
- package/lib/esm/uuid.js +53 -0
- package/lib/esm/uuid.js.map +1 -0
- package/lib/esm/validation.js +158 -0
- package/lib/esm/validation.js.map +1 -0
- package/lib/esm/web3_deferred_promise.js +137 -0
- package/lib/esm/web3_deferred_promise.js.map +1 -0
- package/lib/esm/web3_eip1193_provider.js +105 -0
- package/lib/esm/web3_eip1193_provider.js.map +1 -0
- package/lib/types/chunk_response_parser.d.ts +15 -0
- package/lib/types/chunk_response_parser.d.ts.map +1 -0
- package/lib/types/converters.d.ts +281 -0
- package/lib/types/converters.d.ts.map +1 -0
- package/lib/types/event_emitter.d.ts +11 -0
- package/lib/types/event_emitter.d.ts.map +1 -0
- package/lib/types/formatter.d.ts +44 -0
- package/lib/types/formatter.d.ts.map +1 -0
- package/lib/types/hash.d.ts +94 -0
- package/lib/types/hash.d.ts.map +1 -0
- package/lib/types/index.d.ts +19 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/json_rpc.d.ts +22 -0
- package/lib/types/json_rpc.d.ts.map +1 -0
- package/lib/types/objects.d.ts +8 -0
- package/lib/types/objects.d.ts.map +1 -0
- package/lib/types/promise_helpers.d.ts +48 -0
- package/lib/types/promise_helpers.d.ts.map +1 -0
- package/lib/types/random.d.ts +29 -0
- package/lib/types/random.d.ts.map +1 -0
- package/lib/types/socket_provider.d.ts +129 -0
- package/lib/types/socket_provider.d.ts.map +1 -0
- package/lib/types/string_manipulation.d.ts +81 -0
- package/lib/types/string_manipulation.d.ts.map +1 -0
- package/lib/types/uint8array.d.ts +7 -0
- package/lib/types/uint8array.d.ts.map +1 -0
- package/lib/types/uuid.d.ts +12 -0
- package/lib/types/uuid.d.ts.map +1 -0
- package/lib/types/validation.d.ts +83 -0
- package/lib/types/validation.d.ts.map +1 -0
- package/lib/types/web3_deferred_promise.d.ts +68 -0
- package/lib/types/web3_deferred_promise.d.ts.map +1 -0
- package/lib/types/web3_eip1193_provider.d.ts +16 -0
- package/lib/types/web3_eip1193_provider.d.ts.map +1 -0
- package/package.json +57 -0
- package/src/chunk_response_parser.ts +99 -0
- package/src/converters.ts +713 -0
- package/src/event_emitter.ts +37 -0
- package/src/formatter.ts +402 -0
- package/src/hash.ts +398 -0
- package/src/index.ts +36 -0
- package/src/json_rpc.ts +130 -0
- package/src/objects.ts +65 -0
- package/src/promise_helpers.ts +170 -0
- package/src/random.ts +53 -0
- package/src/socket_provider.ts +581 -0
- package/src/string_manipulation.ts +166 -0
- package/src/uint8array.ts +59 -0
- package/src/uuid.ts +59 -0
- package/src/validation.ts +193 -0
- package/src/web3_deferred_promise.ts +149 -0
- package/src/web3_eip1193_provider.ts +116 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of web3.js.
|
|
3
|
+
|
|
4
|
+
web3.js is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU Lesser General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
web3.js is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU Lesser General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU Lesser General Public License
|
|
15
|
+
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
/* eslint-disable max-classes-per-file */
|
|
18
|
+
|
|
19
|
+
import EventEmitter3 from 'eventemitter3';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* This class copy the behavior of Node.js EventEmitter class.
|
|
23
|
+
* It is used to provide the same interface for the browser environment.
|
|
24
|
+
*/
|
|
25
|
+
export class EventEmitter extends EventEmitter3 {
|
|
26
|
+
// must be defined for backwards compatibility
|
|
27
|
+
private maxListeners = Number.MAX_SAFE_INTEGER;
|
|
28
|
+
|
|
29
|
+
public setMaxListeners(maxListeners: number) {
|
|
30
|
+
this.maxListeners = maxListeners;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public getMaxListeners(): number {
|
|
35
|
+
return this.maxListeners;
|
|
36
|
+
}
|
|
37
|
+
}
|
package/src/formatter.ts
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This file is part of web3.js.
|
|
3
|
+
|
|
4
|
+
web3.js is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU Lesser General Public License as published by
|
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
(at your option) any later version.
|
|
8
|
+
|
|
9
|
+
web3.js is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU Lesser General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU Lesser General Public License
|
|
15
|
+
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
import { FormatterError } from 'web3-errors';
|
|
18
|
+
import {
|
|
19
|
+
Bytes,
|
|
20
|
+
DataFormat,
|
|
21
|
+
FMT_BYTES,
|
|
22
|
+
FMT_NUMBER,
|
|
23
|
+
FormatType,
|
|
24
|
+
DEFAULT_RETURN_FORMAT,
|
|
25
|
+
} from 'web3-types';
|
|
26
|
+
import { isNullish, isObject, JsonSchema, utils, ValidationSchemaInput } from 'web3-validator';
|
|
27
|
+
import { bytesToUint8Array, bytesToHex, numberToHex, toBigInt } from './converters.js';
|
|
28
|
+
import { mergeDeep } from './objects.js';
|
|
29
|
+
import { padLeft } from './string_manipulation.js';
|
|
30
|
+
import { isUint8Array, uint8ArrayConcat } from './uint8array.js';
|
|
31
|
+
|
|
32
|
+
const { parseBaseType } = utils;
|
|
33
|
+
|
|
34
|
+
export const isDataFormat = (dataFormat: unknown): dataFormat is DataFormat =>
|
|
35
|
+
typeof dataFormat === 'object' &&
|
|
36
|
+
!isNullish(dataFormat) &&
|
|
37
|
+
'number' in dataFormat &&
|
|
38
|
+
'bytes' in dataFormat;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Finds the schema that corresponds to a specific data path within a larger JSON schema.
|
|
42
|
+
* It works by iterating over the dataPath array and traversing the JSON schema one step at a time until it reaches the end of the path.
|
|
43
|
+
*
|
|
44
|
+
* @param schema - represents a JSON schema, which is an object that describes the structure of JSON data
|
|
45
|
+
* @param dataPath - represents an array of strings that specifies the path to the data within the JSON schema
|
|
46
|
+
* @param oneOfPath - represents an optional array of two-element tuples that specifies the "oneOf" option to choose, if the schema has oneOf and the data path can match multiple subschemas
|
|
47
|
+
* @returns the JSON schema that matches the data path
|
|
48
|
+
*
|
|
49
|
+
*/
|
|
50
|
+
const findSchemaByDataPath = (
|
|
51
|
+
schema: JsonSchema,
|
|
52
|
+
dataPath: string[],
|
|
53
|
+
oneOfPath: [string, number][] = [],
|
|
54
|
+
): JsonSchema | undefined => {
|
|
55
|
+
let result: JsonSchema = { ...schema } as JsonSchema;
|
|
56
|
+
let previousDataPath: string | undefined;
|
|
57
|
+
|
|
58
|
+
for (const dataPart of dataPath) {
|
|
59
|
+
if (result.oneOf && previousDataPath) {
|
|
60
|
+
const currentDataPath = previousDataPath;
|
|
61
|
+
const path = oneOfPath.find(([key]) => key === currentDataPath);
|
|
62
|
+
if (path && path[0] === previousDataPath) {
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
64
|
+
result = result.oneOf[path[1]];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (!result.properties && !result.items) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (result.properties) {
|
|
72
|
+
result = (result.properties as Record<string, JsonSchema>)[dataPart];
|
|
73
|
+
} else if (result.items && (result.items as JsonSchema).properties) {
|
|
74
|
+
const node = (result.items as JsonSchema).properties as Record<string, JsonSchema>;
|
|
75
|
+
|
|
76
|
+
result = node[dataPart];
|
|
77
|
+
} else if (result.items && isObject(result.items)) {
|
|
78
|
+
result = result.items;
|
|
79
|
+
} else if (result.items && Array.isArray(result.items)) {
|
|
80
|
+
result = result.items[parseInt(dataPart, 10)];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (result && dataPart) previousDataPath = dataPart;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return result;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Converts a value depending on the format
|
|
90
|
+
* @param value - value to convert
|
|
91
|
+
* @param ethType - The type of the value to be parsed
|
|
92
|
+
* @param format - The format to be converted to
|
|
93
|
+
* @returns - The value converted to the specified format
|
|
94
|
+
*/
|
|
95
|
+
export const convertScalarValue = (value: unknown, ethType: string, format: DataFormat) => {
|
|
96
|
+
try {
|
|
97
|
+
const { baseType, baseTypeSize } = parseBaseType(ethType);
|
|
98
|
+
if (baseType === 'int' || baseType === 'uint') {
|
|
99
|
+
switch (format.number) {
|
|
100
|
+
case FMT_NUMBER.NUMBER:
|
|
101
|
+
return Number(toBigInt(value));
|
|
102
|
+
case FMT_NUMBER.HEX:
|
|
103
|
+
return numberToHex(toBigInt(value));
|
|
104
|
+
case FMT_NUMBER.STR:
|
|
105
|
+
return toBigInt(value).toString();
|
|
106
|
+
case FMT_NUMBER.BIGINT:
|
|
107
|
+
return toBigInt(value);
|
|
108
|
+
default:
|
|
109
|
+
throw new FormatterError(`Invalid format: ${String(format.number)}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (baseType === 'bytes') {
|
|
113
|
+
let paddedValue;
|
|
114
|
+
if (baseTypeSize) {
|
|
115
|
+
if (typeof value === 'string') paddedValue = padLeft(value, baseTypeSize * 2);
|
|
116
|
+
else if (isUint8Array(value)) {
|
|
117
|
+
paddedValue = uint8ArrayConcat(
|
|
118
|
+
new Uint8Array(baseTypeSize - value.length),
|
|
119
|
+
value,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
paddedValue = value;
|
|
124
|
+
}
|
|
125
|
+
switch (format.bytes) {
|
|
126
|
+
case FMT_BYTES.HEX:
|
|
127
|
+
return bytesToHex(bytesToUint8Array(paddedValue as Bytes));
|
|
128
|
+
case FMT_BYTES.UINT8ARRAY:
|
|
129
|
+
return bytesToUint8Array(paddedValue as Bytes);
|
|
130
|
+
default:
|
|
131
|
+
throw new FormatterError(`Invalid format: ${String(format.bytes)}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (baseType === 'string') {
|
|
136
|
+
return String(value);
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
// If someone didn't use `eth` keyword we can return original value
|
|
140
|
+
// as the scope of this code is formatting not validation
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return value;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const convertArray = ({
|
|
148
|
+
value,
|
|
149
|
+
schemaProp,
|
|
150
|
+
schema,
|
|
151
|
+
object,
|
|
152
|
+
key,
|
|
153
|
+
dataPath,
|
|
154
|
+
format,
|
|
155
|
+
oneOfPath = [],
|
|
156
|
+
}: {
|
|
157
|
+
value: unknown;
|
|
158
|
+
schemaProp: JsonSchema;
|
|
159
|
+
schema: JsonSchema;
|
|
160
|
+
object: Record<string, unknown>;
|
|
161
|
+
key: string;
|
|
162
|
+
dataPath: string[];
|
|
163
|
+
format: DataFormat;
|
|
164
|
+
oneOfPath: [string, number][];
|
|
165
|
+
}) => {
|
|
166
|
+
// If value is an array
|
|
167
|
+
if (Array.isArray(value)) {
|
|
168
|
+
let _schemaProp = schemaProp;
|
|
169
|
+
|
|
170
|
+
// TODO This is a naive approach to solving the issue of
|
|
171
|
+
// a schema using oneOf. This chunk of code was intended to handle
|
|
172
|
+
// BlockSchema.transactions
|
|
173
|
+
// TODO BlockSchema.transactions are not being formatted
|
|
174
|
+
if (schemaProp?.oneOf !== undefined) {
|
|
175
|
+
// The following code is basically saying:
|
|
176
|
+
// if the schema specifies oneOf, then we are to loop
|
|
177
|
+
// over each possible schema and check if they type of the schema
|
|
178
|
+
// matches the type of value[0], and if so we use the oneOfSchemaProp
|
|
179
|
+
// as the schema for formatting
|
|
180
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
181
|
+
schemaProp.oneOf.forEach((oneOfSchemaProp: JsonSchema, index: number) => {
|
|
182
|
+
if (
|
|
183
|
+
!Array.isArray(schemaProp?.items) &&
|
|
184
|
+
((typeof value[0] === 'object' &&
|
|
185
|
+
(oneOfSchemaProp?.items as JsonSchema)?.type === 'object') ||
|
|
186
|
+
(typeof value[0] === 'string' &&
|
|
187
|
+
(oneOfSchemaProp?.items as JsonSchema)?.type !== 'object'))
|
|
188
|
+
) {
|
|
189
|
+
_schemaProp = oneOfSchemaProp;
|
|
190
|
+
oneOfPath.push([key, index]);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (isNullish(_schemaProp?.items)) {
|
|
196
|
+
// Can not find schema for array item, delete that item
|
|
197
|
+
// eslint-disable-next-line no-param-reassign
|
|
198
|
+
delete object[key];
|
|
199
|
+
dataPath.pop();
|
|
200
|
+
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// If schema for array items is a single type
|
|
205
|
+
if (isObject(_schemaProp.items) && !isNullish(_schemaProp.items.format)) {
|
|
206
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
207
|
+
// eslint-disable-next-line no-param-reassign
|
|
208
|
+
(object[key] as unknown[])[i] = convertScalarValue(
|
|
209
|
+
value[i],
|
|
210
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
211
|
+
_schemaProp?.items?.format,
|
|
212
|
+
format,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
dataPath.pop();
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// If schema for array items is an object
|
|
221
|
+
if (!Array.isArray(_schemaProp?.items) && _schemaProp?.items?.type === 'object') {
|
|
222
|
+
for (const arrObject of value) {
|
|
223
|
+
// eslint-disable-next-line no-use-before-define
|
|
224
|
+
convert(
|
|
225
|
+
arrObject as Record<string, unknown> | unknown[],
|
|
226
|
+
schema,
|
|
227
|
+
dataPath,
|
|
228
|
+
format,
|
|
229
|
+
oneOfPath,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
dataPath.pop();
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// If schema for array is a tuple
|
|
238
|
+
if (Array.isArray(_schemaProp?.items)) {
|
|
239
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
240
|
+
// eslint-disable-next-line no-param-reassign
|
|
241
|
+
(object[key] as unknown[])[i] = convertScalarValue(
|
|
242
|
+
value[i],
|
|
243
|
+
_schemaProp.items[i].format as string,
|
|
244
|
+
format,
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
dataPath.pop();
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return false;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Converts the data to the specified format
|
|
257
|
+
* @param data - data to convert
|
|
258
|
+
* @param schema - The JSON schema that describes the structure of the data
|
|
259
|
+
* @param dataPath - A string array that specifies the path to the data within the JSON schema
|
|
260
|
+
* @param format - The format to be converted to
|
|
261
|
+
* @param oneOfPath - An optional array of two-element tuples that specifies the "oneOf" option to choose, if the schema has oneOf and the data path can match multiple subschemas
|
|
262
|
+
* @returns - The data converted to the specified format
|
|
263
|
+
*/
|
|
264
|
+
export const convert = (
|
|
265
|
+
data: Record<string, unknown> | unknown[] | unknown,
|
|
266
|
+
schema: JsonSchema,
|
|
267
|
+
dataPath: string[],
|
|
268
|
+
format: DataFormat,
|
|
269
|
+
oneOfPath: [string, number][] = [],
|
|
270
|
+
) => {
|
|
271
|
+
// If it's a scalar value
|
|
272
|
+
if (!isObject(data) && !Array.isArray(data)) {
|
|
273
|
+
return convertScalarValue(data, schema?.format as string, format);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const object = data as Record<string, unknown>;
|
|
277
|
+
// case when schema is array and `items` is object
|
|
278
|
+
if (
|
|
279
|
+
Array.isArray(object) &&
|
|
280
|
+
schema?.type === 'array' &&
|
|
281
|
+
(schema?.items as JsonSchema)?.type === 'object'
|
|
282
|
+
) {
|
|
283
|
+
convertArray({
|
|
284
|
+
value: object,
|
|
285
|
+
schemaProp: schema,
|
|
286
|
+
schema,
|
|
287
|
+
object,
|
|
288
|
+
key: '',
|
|
289
|
+
dataPath,
|
|
290
|
+
format,
|
|
291
|
+
oneOfPath,
|
|
292
|
+
});
|
|
293
|
+
} else {
|
|
294
|
+
for (const [key, value] of Object.entries(object)) {
|
|
295
|
+
dataPath.push(key);
|
|
296
|
+
let schemaProp = findSchemaByDataPath(schema, dataPath, oneOfPath);
|
|
297
|
+
|
|
298
|
+
// If value is a scaler value
|
|
299
|
+
if (isNullish(schemaProp)) {
|
|
300
|
+
delete object[key];
|
|
301
|
+
dataPath.pop();
|
|
302
|
+
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// If value is an object, recurse into it
|
|
307
|
+
if (isObject(value)) {
|
|
308
|
+
convert(value, schema, dataPath, format, oneOfPath);
|
|
309
|
+
dataPath.pop();
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// If value is an array
|
|
314
|
+
if (
|
|
315
|
+
convertArray({
|
|
316
|
+
value,
|
|
317
|
+
schemaProp,
|
|
318
|
+
schema,
|
|
319
|
+
object,
|
|
320
|
+
key,
|
|
321
|
+
dataPath,
|
|
322
|
+
format,
|
|
323
|
+
oneOfPath,
|
|
324
|
+
})
|
|
325
|
+
) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// The following code is basically saying:
|
|
330
|
+
// if the schema specifies oneOf, then we are to loop
|
|
331
|
+
// over each possible schema and check if they type of the schema specifies format
|
|
332
|
+
// and if so we use the oneOfSchemaProp as the schema for formatting
|
|
333
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
334
|
+
if (schemaProp?.format === undefined && schemaProp?.oneOf !== undefined) {
|
|
335
|
+
for (const [_index, oneOfSchemaProp] of schemaProp.oneOf.entries()) {
|
|
336
|
+
if (oneOfSchemaProp?.format !== undefined) {
|
|
337
|
+
schemaProp = oneOfSchemaProp;
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
object[key] = convertScalarValue(value, schemaProp.format as string, format);
|
|
344
|
+
|
|
345
|
+
dataPath.pop();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return object;
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Given data that can be interpreted according to the provided schema, returns equivalent data that has been formatted
|
|
354
|
+
* according to the provided return format.
|
|
355
|
+
*
|
|
356
|
+
* @param schema - how to interpret the data
|
|
357
|
+
* @param data - data to be formatted
|
|
358
|
+
* @param returnFormat - how to format the data
|
|
359
|
+
* @returns - formatted data
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
*
|
|
363
|
+
* ```js
|
|
364
|
+
* import { FMT_NUMBER, utils } from "web3";
|
|
365
|
+
*
|
|
366
|
+
* console.log(
|
|
367
|
+
* utils.format({ format: "uint" }, "221", { number: FMT_NUMBER.HEX }),
|
|
368
|
+
* );
|
|
369
|
+
* // 0xdd
|
|
370
|
+
* ```
|
|
371
|
+
*
|
|
372
|
+
*/
|
|
373
|
+
export const format = <
|
|
374
|
+
DataType extends Record<string, unknown> | unknown[] | unknown,
|
|
375
|
+
ReturnType extends DataFormat,
|
|
376
|
+
>(
|
|
377
|
+
schema: ValidationSchemaInput | JsonSchema,
|
|
378
|
+
data: DataType,
|
|
379
|
+
returnFormat: ReturnType = DEFAULT_RETURN_FORMAT as ReturnType,
|
|
380
|
+
): FormatType<DataType, ReturnType> => {
|
|
381
|
+
let dataToParse: Record<string, unknown> | unknown[] | unknown;
|
|
382
|
+
|
|
383
|
+
if (isObject(data)) {
|
|
384
|
+
dataToParse = mergeDeep({}, data);
|
|
385
|
+
} else if (Array.isArray(data)) {
|
|
386
|
+
dataToParse = [...data];
|
|
387
|
+
} else {
|
|
388
|
+
dataToParse = data;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
392
|
+
const jsonSchema: JsonSchema = isObject(schema) ? schema : utils.ethAbiToJsonSchema(schema);
|
|
393
|
+
|
|
394
|
+
if (!jsonSchema.properties && !jsonSchema.items && !jsonSchema.format) {
|
|
395
|
+
throw new FormatterError('Invalid json schema for formatting');
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return convert(dataToParse, jsonSchema, [], returnFormat) as FormatType<
|
|
399
|
+
typeof data,
|
|
400
|
+
ReturnType
|
|
401
|
+
>;
|
|
402
|
+
};
|