@chainlink/external-adapter-framework 0.0.67 → 0.0.69

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.
Files changed (44) hide show
  1. package/adapter.d.ts +156 -0
  2. package/adapter.js +200 -0
  3. package/adapter.js.map +1 -0
  4. package/cache/redis.d.ts +8 -1
  5. package/cache/redis.js +39 -22
  6. package/cache/redis.js.map +1 -1
  7. package/config/index.d.ts +1 -1
  8. package/examples/bank-frick/config/index.d.ts +1 -1
  9. package/examples/coingecko/batch-warming.d.ts +7 -0
  10. package/examples/coingecko/batch-warming.js +54 -0
  11. package/examples/coingecko/batch-warming.js.map +1 -0
  12. package/examples/coingecko/index.d.ts +2 -0
  13. package/examples/coingecko/index.js +12 -0
  14. package/examples/coingecko/index.js.map +1 -0
  15. package/examples/coingecko/rest.d.ts +12 -0
  16. package/examples/coingecko/rest.js +55 -0
  17. package/examples/coingecko/rest.js.map +1 -0
  18. package/examples/coingecko/src/crypto-utils.d.ts +3 -3
  19. package/examples/coingecko/src/crypto-utils.js.map +1 -1
  20. package/examples/coingecko/src/cryptoUtils.d.ts +31 -0
  21. package/examples/coingecko/src/cryptoUtils.js +60 -0
  22. package/examples/coingecko/src/endpoint/coins.js.map +1 -1
  23. package/examples/coingecko/src/endpoint/crypto-marketcap.js.map +1 -1
  24. package/examples/coingecko/src/endpoint/crypto-volume.js.map +1 -1
  25. package/examples/coingecko/src/endpoint/crypto.js.map +1 -1
  26. package/examples/coingecko/src/endpoint/dominance.js.map +1 -1
  27. package/examples/coingecko/src/endpoint/global-marketcap.js.map +1 -1
  28. package/examples/coingecko/src/global-utils.d.ts +3 -3
  29. package/examples/coingecko/src/global-utils.js.map +1 -1
  30. package/examples/coingecko/src/globalUtils.d.ts +27 -0
  31. package/examples/coingecko/src/globalUtils.js +46 -0
  32. package/examples/coingecko/src/index.d.ts +1 -1
  33. package/examples/cryptocompare/src/index.d.ts +1 -1
  34. package/examples/genesis/sseStream.js.map +1 -1
  35. package/index.d.ts +1 -2
  36. package/index.js.map +1 -1
  37. package/package.json +2 -2
  38. package/rate-limiting/index.d.ts +2 -2
  39. package/transports/metrics.d.ts +1 -1
  40. package/transports/rest.d.ts +0 -1
  41. package/transports/rest.js.map +1 -1
  42. package/validation/preset-tokens.json +23 -0
  43. package/validation/validator.d.ts +47 -0
  44. package/validation/validator.js +303 -0
@@ -0,0 +1,303 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Validator = void 0;
7
+ const error_1 = require("./error");
8
+ const input_params_1 = require("./input-params");
9
+ const util_1 = require("../util");
10
+ const preset_tokens_json_1 = __importDefault(require("./preset-tokens.json"));
11
+ // Don't want to get requester in just yet, only copying the static method 'errored'
12
+ const requesterErrored = (jobRunID = '1', error = undefined, statusCode = 500, feedID = undefined) => {
13
+ if (error instanceof error_1.AdapterError) {
14
+ error.jobRunID = jobRunID;
15
+ if (feedID) {
16
+ error.feedID = feedID;
17
+ }
18
+ return error.toJSONResponse();
19
+ }
20
+ if (error instanceof Error) {
21
+ return new error_1.AdapterError({
22
+ jobRunID,
23
+ statusCode,
24
+ message: error.message,
25
+ cause: error,
26
+ feedID,
27
+ }).toJSONResponse();
28
+ }
29
+ return new error_1.AdapterError({ jobRunID, statusCode, message: error, feedID }).toJSONResponse();
30
+ };
31
+ class Validator {
32
+ constructor(input = { id: '1', data: {} }, inputConfigs = {}, inputOptions = {}, validatorOptions = {}) {
33
+ // OverrideSymbol = (adapter: string, symbol?: string | string[]): string | string[] => {
34
+ // Const defaultSymbol = symbol || this.validated.data.base
35
+ // If (!defaultSymbol) this.throwInvalid(`Required parameter not supplied: base`)
36
+ // // TODO: Will never be reached, because the presetSymbols are used as default overrides
37
+ // If (!this.validated.overrides) return defaultSymbol
38
+ // If (!Array.isArray(defaultSymbol))
39
+ // Return (
40
+ // This.validated.overrides.get(adapter.toLowerCase())?.get(defaultSymbol.toLowerCase()) ||
41
+ // DefaultSymbol
42
+ // )
43
+ // Const multiple: string[] = []
44
+ // For (const sym of defaultSymbol) {
45
+ // Const overrided = this.validated.overrides.get(adapter.toLowerCase())?.get(sym.toLowerCase())
46
+ // If (!overrided) multiple.push(sym)
47
+ // Else multiple.push(overrided)
48
+ // }
49
+ // Return multiple
50
+ // }
51
+ // OverrideToken = (symbol: string, network = 'ethereum'): string | undefined => {
52
+ // Return this.validated.tokenOverrides?.get(network.toLowerCase())?.get(symbol.toLowerCase())
53
+ // }
54
+ // OverrideIncludes = (from: string, to: string): IncludePair | undefined => {
55
+ // // Search through `presetIncludes` to find matching override for adapter and to/from pairing.
56
+ // Const pairs = (
57
+ // This.validated.includes?.filter(
58
+ // (val: string | Includes) => typeof val !== 'string',
59
+ // ) as Includes[]
60
+ // ).filter(
61
+ // (pair) =>
62
+ // Pair.from.toLowerCase() === from.toLowerCase() &&
63
+ // Pair.to.toLowerCase() === to.toLowerCase(),
64
+ // )
65
+ // If (!pairs || !pairs[0] || !pairs[0].includes || !pairs[0].includes[0]) {
66
+ // Return
67
+ // }
68
+ // Return pairs[0].includes[0]
69
+ // }
70
+ // OverrideReverseLookup = (adapter: string, type: OverrideType, symbol: string): string => {
71
+ // Const overrides: Map<string, string> | undefined = this.validated?.[type]?.get(
72
+ // Adapter.toLowerCase(),
73
+ // )
74
+ // If (!overrides) return symbol
75
+ // Let originalSymbol: string | undefined
76
+ // Overrides.forEach((overridden, original) => {
77
+ // If (overridden.toLowerCase() === symbol.toLowerCase()) originalSymbol = original
78
+ // })
79
+ // Return originalSymbol || symbol
80
+ // }
81
+ this.formatOverride = (param) => {
82
+ const _throwInvalid = () => this.throwInvalid(`Parameter supplied with wrong format: "override"`);
83
+ if (!(0, util_1.isObject)(param)) {
84
+ _throwInvalid();
85
+ }
86
+ const _isValid = Object.values(param).every(util_1.isObject);
87
+ if (!_isValid) {
88
+ _throwInvalid();
89
+ }
90
+ const _keyToLowerCase = (entry) => {
91
+ return [entry[0].toLowerCase(), entry[1]];
92
+ };
93
+ return new Map(Object.entries(param)
94
+ .map(_keyToLowerCase)
95
+ .map(([key, value]) => [key, new Map(Object.entries(value).map(_keyToLowerCase))]));
96
+ };
97
+ this.formatIncludeOverrides = (param) => {
98
+ const _throwInvalid = () => this.throwInvalid(`Parameter supplied with wrong format: "includes"`);
99
+ if (!(0, util_1.isArray)(param)) {
100
+ _throwInvalid();
101
+ }
102
+ const _isValid = Object.values(param).every((val) => (0, util_1.isObject)(val) || typeof val === 'string');
103
+ if (!_isValid) {
104
+ _throwInvalid();
105
+ }
106
+ return param;
107
+ };
108
+ this.throwInvalid = (message) => {
109
+ throw new error_1.AdapterError({ jobRunID: this.validated.id, statusCode: 400, message });
110
+ };
111
+ this.input = { ...input };
112
+ if (!this.input.id) {
113
+ this.input.id = '1';
114
+ } // TODO Please remove these once "no any" strict typing is enabled
115
+ if (!this.input.data) {
116
+ this.input.data = {};
117
+ }
118
+ this.inputConfigs = { ...input_params_1.baseInputParameters, ...inputConfigs };
119
+ this.inputOptions = { ...inputOptions };
120
+ this.validatorOptions = {
121
+ shouldThrowError: true,
122
+ includes: [],
123
+ overrides: {},
124
+ ...validatorOptions,
125
+ };
126
+ this.validated = { id: this.input.id, data: {} };
127
+ this.validateInput();
128
+ this.validateOverrides('overrides', this.validatorOptions.overrides);
129
+ this.validateOverrides('tokenOverrides', preset_tokens_json_1.default);
130
+ this.validateIncludeOverrides();
131
+ this.checkDuplicateInputParams(inputConfigs);
132
+ }
133
+ validateInput() {
134
+ try {
135
+ for (const key in this.inputConfigs) {
136
+ this.validateObjectParam(key, this.validatorOptions.shouldThrowError);
137
+ }
138
+ }
139
+ catch (e) {
140
+ this.parseError(e);
141
+ }
142
+ }
143
+ validateOverrides(path, preset) {
144
+ try {
145
+ if (!this.input.data?.[path]) {
146
+ this.validated[path] = this.formatOverride(preset);
147
+ return;
148
+ }
149
+ this.validated[path] = this.formatOverride({ ...preset, ...this.input.data[path] });
150
+ }
151
+ catch (e) {
152
+ this.parseError(e);
153
+ }
154
+ }
155
+ checkDuplicateInputParams(inputConfig) {
156
+ let aliases = [];
157
+ for (const key in inputConfig) {
158
+ const param = inputConfig[key];
159
+ if (Array.isArray(param)) {
160
+ aliases = aliases.concat(param);
161
+ }
162
+ else if (typeof inputConfig === 'boolean') {
163
+ return;
164
+ }
165
+ else {
166
+ aliases.push(key);
167
+ if (typeof param === 'object' && 'aliases' in param && Array.isArray(param.aliases)) {
168
+ aliases = aliases.concat(param.aliases);
169
+ }
170
+ }
171
+ }
172
+ if (aliases.length !== new Set(aliases).size) {
173
+ this.throwInvalid('Duplicate Input Aliases');
174
+ }
175
+ }
176
+ validateIncludeOverrides() {
177
+ try {
178
+ this.validated.includes = this.formatIncludeOverrides([
179
+ ...(Array.isArray(this.input.data?.includes) ? this.input.data.includes : []),
180
+ ...(this.validatorOptions.includes || []),
181
+ ]);
182
+ }
183
+ catch (e) {
184
+ this.parseError(e);
185
+ }
186
+ }
187
+ parseError(error) {
188
+ if (!(error instanceof Error)) {
189
+ return;
190
+ }
191
+ const message = 'Error validating input.';
192
+ if (error instanceof error_1.AdapterError) {
193
+ this.error = error;
194
+ }
195
+ else {
196
+ this.error = new error_1.AdapterError({
197
+ jobRunID: this.validated.id,
198
+ statusCode: 400,
199
+ message,
200
+ cause: error,
201
+ });
202
+ }
203
+ this.errored = requesterErrored(this.validated.id, this.error);
204
+ if (this.validatorOptions.shouldThrowError) {
205
+ throw this.error;
206
+ }
207
+ }
208
+ validateObjectParam(key, shouldThrowError = true) {
209
+ const inputConfig = this.inputConfigs[key];
210
+ const usedKey = this.getUsedKey(key, inputConfig.aliases ?? []);
211
+ const param = usedKey
212
+ ? this.input.data[usedKey] ?? inputConfig.default
213
+ : inputConfig.default;
214
+ if (shouldThrowError) {
215
+ const paramIsDefined = !(param === undefined || param === null || param === '');
216
+ if (inputConfig.required && !paramIsDefined) {
217
+ this.throwInvalid(`Required parameter ${key} must be non-null and non-empty`);
218
+ }
219
+ if (paramIsDefined) {
220
+ if (inputConfig.type) {
221
+ const primitiveTypes = ['boolean', 'number', 'bigint', 'string'];
222
+ if (![...primitiveTypes, 'array', 'object'].includes(inputConfig.type)) {
223
+ this.throwInvalid(`${key} parameter has unrecognized type ${inputConfig.type}`);
224
+ }
225
+ if (primitiveTypes.includes(inputConfig.type) && typeof param !== inputConfig.type) {
226
+ this.throwInvalid(`${key} parameter must be of type ${inputConfig.type}`);
227
+ }
228
+ if (inputConfig.type === 'array' && (!Array.isArray(param) || param.length === 0)) {
229
+ this.throwInvalid(`${key} parameter must be a non-empty array`);
230
+ }
231
+ if (inputConfig.type === 'object' &&
232
+ (!param ||
233
+ Array.isArray(param) ||
234
+ typeof param !== inputConfig.type ||
235
+ Object.keys(param).length === 0)) {
236
+ this.throwInvalid(`${key} parameter must be an object with at least one property`);
237
+ }
238
+ }
239
+ // If (inputConfig.options) {
240
+ // Const tolcase = (o: any) => (typeof o === 'string' ? o.toLowerCase() : o)
241
+ // Const formattedOptions = inputConfig.options.map(tolcase)
242
+ // Const formattedParam = tolcase(param)
243
+ // If (!formattedOptions.includes(formattedParam))
244
+ // This.throwInvalid(
245
+ // `${key} parameter '${formattedParam}' is not in the set of available options: ${formattedOptions.join(
246
+ // ',',
247
+ // )}`,
248
+ // )
249
+ // }
250
+ // For (const dependency of inputConfig.dependsOn ?? []) {
251
+ // Const usedDependencyKey = this.getUsedKey(
252
+ // Dependency,
253
+ // (this.inputConfigs[dependency] as InputParameter).aliases ?? [],
254
+ // )
255
+ // If (!usedDependencyKey) this.throwInvalid(`${key} dependency ${dependency} not supplied`)
256
+ // }
257
+ // For (const exclusive of inputConfig.exclusive ?? []) {
258
+ // Const usedExclusiveKey = this.getUsedKey(
259
+ // Exclusive,
260
+ // (this.inputConfigs[exclusive] as InputParameter).aliases ?? [],
261
+ // )
262
+ // If (usedExclusiveKey)
263
+ // This.throwInvalid(`${key} cannot be supplied concurrently with ${exclusive}`)
264
+ // }
265
+ }
266
+ }
267
+ this.validated.data[key] = param;
268
+ }
269
+ validateOptionalParam(param, key, options) {
270
+ if (param && options) {
271
+ if (!Array.isArray(options)) {
272
+ this.throwInvalid(`Parameter options for ${key} must be of an Array type`);
273
+ }
274
+ if (!options.includes(param)) {
275
+ this.throwInvalid(`${param} is not a supported ${key} option. Must be one of ${options}`);
276
+ }
277
+ }
278
+ this.validated.data[key] = param;
279
+ }
280
+ validateRequiredParam(param, key, options) {
281
+ if (typeof param === 'undefined' || param === '') {
282
+ this.throwInvalid(`Required parameter not supplied: ${key}`);
283
+ }
284
+ if (options) {
285
+ if (!Array.isArray(options)) {
286
+ this.throwInvalid(`Parameter options for ${key} must be of an Array type`);
287
+ }
288
+ if (!options.includes(param)) {
289
+ this.throwInvalid(`${param} is not a supported ${key} option. Must be one of ${options.join(' || ')}`);
290
+ }
291
+ }
292
+ this.validated.data[key] = param;
293
+ }
294
+ getUsedKey(key, keyArray) {
295
+ const comparisonArray = [...keyArray];
296
+ if (!comparisonArray.includes(key)) {
297
+ comparisonArray.push(key);
298
+ }
299
+ const inputParamKeys = Object.keys(this.input.data);
300
+ return inputParamKeys.find((k) => comparisonArray.includes(k));
301
+ }
302
+ }
303
+ exports.Validator = Validator;