@chainlink/external-adapter-framework 0.0.6 → 0.0.8

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 (237) hide show
  1. package/adapter.d.ts +88 -0
  2. package/adapter.js +112 -0
  3. package/background-executor.d.ts +11 -0
  4. package/background-executor.js +45 -0
  5. package/cache/factory.d.ts +6 -0
  6. package/cache/factory.js +57 -0
  7. package/cache/index.d.ts +90 -0
  8. package/cache/index.js +169 -0
  9. package/cache/local.d.ts +23 -0
  10. package/cache/local.js +83 -0
  11. package/cache/metrics.d.ts +27 -0
  12. package/cache/metrics.js +120 -0
  13. package/cache/redis.d.ts +16 -0
  14. package/cache/redis.js +100 -0
  15. package/chainlink-external-adapter-framework-v0.0.8.tgz +0 -0
  16. package/config/index.d.ts +195 -0
  17. package/config/index.js +365 -0
  18. package/config/provider-limits.d.ts +31 -0
  19. package/config/provider-limits.js +75 -0
  20. package/examples/coingecko/batch-warming.d.ts +2 -0
  21. package/examples/coingecko/batch-warming.js +52 -0
  22. package/examples/coingecko/index.d.ts +2 -0
  23. package/examples/coingecko/index.js +10 -0
  24. package/examples/coingecko/rest.d.ts +2 -0
  25. package/examples/coingecko/rest.js +50 -0
  26. package/examples/ncfx/config/index.d.ts +12 -0
  27. package/examples/ncfx/config/index.js +15 -0
  28. package/examples/ncfx/index.d.ts +2 -0
  29. package/examples/ncfx/index.js +10 -0
  30. package/examples/ncfx/websocket.d.ts +36 -0
  31. package/examples/ncfx/websocket.js +72 -0
  32. package/index.d.ts +12 -0
  33. package/index.js +92 -0
  34. package/metrics/constants.d.ts +16 -0
  35. package/metrics/constants.js +25 -0
  36. package/metrics/index.d.ts +15 -0
  37. package/metrics/index.js +123 -0
  38. package/metrics/util.d.ts +3 -0
  39. package/metrics/util.js +9 -0
  40. package/package/adapter.d.ts +88 -0
  41. package/package/adapter.js +112 -0
  42. package/package/background-executor.d.ts +11 -0
  43. package/package/background-executor.js +45 -0
  44. package/package/cache/factory.d.ts +6 -0
  45. package/package/cache/factory.js +57 -0
  46. package/package/cache/index.d.ts +90 -0
  47. package/package/cache/index.js +169 -0
  48. package/package/cache/local.d.ts +23 -0
  49. package/package/cache/local.js +83 -0
  50. package/package/cache/metrics.d.ts +27 -0
  51. package/package/cache/metrics.js +120 -0
  52. package/package/cache/redis.d.ts +16 -0
  53. package/package/cache/redis.js +100 -0
  54. package/package/config/index.d.ts +195 -0
  55. package/package/config/index.js +365 -0
  56. package/package/config/provider-limits.d.ts +31 -0
  57. package/package/config/provider-limits.js +75 -0
  58. package/package/examples/coingecko/batch-warming.d.ts +2 -0
  59. package/package/examples/coingecko/batch-warming.js +52 -0
  60. package/package/examples/coingecko/index.d.ts +2 -0
  61. package/package/examples/coingecko/index.js +10 -0
  62. package/package/examples/coingecko/rest.d.ts +2 -0
  63. package/package/examples/coingecko/rest.js +50 -0
  64. package/package/examples/ncfx/config/index.d.ts +12 -0
  65. package/package/examples/ncfx/config/index.js +15 -0
  66. package/package/examples/ncfx/index.d.ts +2 -0
  67. package/package/examples/ncfx/index.js +10 -0
  68. package/package/examples/ncfx/websocket.d.ts +36 -0
  69. package/package/examples/ncfx/websocket.js +72 -0
  70. package/package/index.d.ts +12 -0
  71. package/package/index.js +92 -0
  72. package/package/metrics/constants.d.ts +16 -0
  73. package/package/metrics/constants.js +25 -0
  74. package/package/metrics/index.d.ts +15 -0
  75. package/package/metrics/index.js +123 -0
  76. package/package/metrics/util.d.ts +3 -0
  77. package/package/metrics/util.js +9 -0
  78. package/package/package.json +69 -0
  79. package/package/rate-limiting/background/fixed-frequency.d.ts +10 -0
  80. package/package/rate-limiting/background/fixed-frequency.js +37 -0
  81. package/package/rate-limiting/index.d.ts +54 -0
  82. package/package/rate-limiting/index.js +63 -0
  83. package/package/rate-limiting/metrics.d.ts +3 -0
  84. package/package/rate-limiting/metrics.js +44 -0
  85. package/package/rate-limiting/request/simple-counting.d.ts +20 -0
  86. package/package/rate-limiting/request/simple-counting.js +62 -0
  87. package/package/test.d.ts +1 -0
  88. package/package/test.js +6 -0
  89. package/package/transports/batch-warming.d.ts +34 -0
  90. package/package/transports/batch-warming.js +101 -0
  91. package/package/transports/index.d.ts +87 -0
  92. package/package/transports/index.js +87 -0
  93. package/package/transports/metrics.d.ts +21 -0
  94. package/package/transports/metrics.js +105 -0
  95. package/package/transports/rest.d.ts +43 -0
  96. package/package/transports/rest.js +129 -0
  97. package/package/transports/util.d.ts +8 -0
  98. package/package/transports/util.js +85 -0
  99. package/package/transports/websocket.d.ts +80 -0
  100. package/package/transports/websocket.js +169 -0
  101. package/package/util/expiring-sorted-set.d.ts +21 -0
  102. package/package/util/expiring-sorted-set.js +47 -0
  103. package/package/util/index.d.ts +11 -0
  104. package/package/util/index.js +35 -0
  105. package/package/util/logger.d.ts +42 -0
  106. package/package/util/logger.js +62 -0
  107. package/package/util/request.d.ts +55 -0
  108. package/package/util/request.js +2 -0
  109. package/package/validation/error.d.ts +50 -0
  110. package/package/validation/error.js +79 -0
  111. package/package/validation/index.d.ts +5 -0
  112. package/package/validation/index.js +86 -0
  113. package/package/validation/input-params.d.ts +15 -0
  114. package/package/validation/input-params.js +30 -0
  115. package/package/validation/override-functions.d.ts +3 -0
  116. package/package/validation/override-functions.js +40 -0
  117. package/package/validation/preset-tokens.json +23 -0
  118. package/package/validation/validator.d.ts +47 -0
  119. package/package/validation/validator.js +303 -0
  120. package/package.json +1 -1
  121. package/rate-limiting/background/fixed-frequency.d.ts +10 -0
  122. package/rate-limiting/background/fixed-frequency.js +37 -0
  123. package/rate-limiting/index.d.ts +54 -0
  124. package/rate-limiting/index.js +63 -0
  125. package/rate-limiting/metrics.d.ts +3 -0
  126. package/rate-limiting/metrics.js +44 -0
  127. package/rate-limiting/request/simple-counting.d.ts +20 -0
  128. package/rate-limiting/request/simple-counting.js +62 -0
  129. package/test.d.ts +1 -0
  130. package/test.js +6 -0
  131. package/transports/batch-warming.d.ts +34 -0
  132. package/transports/batch-warming.js +101 -0
  133. package/transports/index.d.ts +87 -0
  134. package/transports/index.js +87 -0
  135. package/transports/metrics.d.ts +21 -0
  136. package/transports/metrics.js +105 -0
  137. package/transports/rest.d.ts +43 -0
  138. package/transports/rest.js +129 -0
  139. package/transports/util.d.ts +8 -0
  140. package/transports/util.js +85 -0
  141. package/transports/websocket.d.ts +80 -0
  142. package/transports/websocket.js +169 -0
  143. package/util/expiring-sorted-set.d.ts +21 -0
  144. package/util/expiring-sorted-set.js +47 -0
  145. package/util/index.d.ts +11 -0
  146. package/util/index.js +35 -0
  147. package/util/logger.d.ts +42 -0
  148. package/util/logger.js +62 -0
  149. package/util/request.d.ts +55 -0
  150. package/util/request.js +2 -0
  151. package/validation/error.d.ts +50 -0
  152. package/validation/error.js +79 -0
  153. package/validation/index.d.ts +5 -0
  154. package/validation/index.js +86 -0
  155. package/validation/input-params.d.ts +15 -0
  156. package/validation/input-params.js +30 -0
  157. package/validation/override-functions.d.ts +3 -0
  158. package/validation/override-functions.js +40 -0
  159. package/validation/preset-tokens.json +23 -0
  160. package/validation/validator.d.ts +47 -0
  161. package/validation/validator.js +303 -0
  162. package/.c8rc.json +0 -3
  163. package/.eslintignore +0 -9
  164. package/.eslintrc.js +0 -96
  165. package/.github/README.MD +0 -17
  166. package/.github/actions/setup/action.yaml +0 -13
  167. package/.github/workflows/main.yaml +0 -39
  168. package/.github/workflows/publish.yaml +0 -17
  169. package/.prettierignore +0 -13
  170. package/.yarnrc +0 -0
  171. package/README.md +0 -103
  172. package/docker-compose.yaml +0 -35
  173. package/src/adapter.ts +0 -236
  174. package/src/background-executor.ts +0 -53
  175. package/src/cache/factory.ts +0 -28
  176. package/src/cache/index.ts +0 -236
  177. package/src/cache/local.ts +0 -73
  178. package/src/cache/metrics.ts +0 -112
  179. package/src/cache/redis.ts +0 -93
  180. package/src/config/index.ts +0 -501
  181. package/src/config/provider-limits.ts +0 -130
  182. package/src/examples/coingecko/batch-warming.ts +0 -79
  183. package/src/examples/coingecko/index.ts +0 -9
  184. package/src/examples/coingecko/rest.ts +0 -77
  185. package/src/examples/ncfx/config/index.ts +0 -12
  186. package/src/examples/ncfx/index.ts +0 -9
  187. package/src/examples/ncfx/websocket.ts +0 -100
  188. package/src/index.ts +0 -106
  189. package/src/metrics/constants.ts +0 -23
  190. package/src/metrics/index.ts +0 -116
  191. package/src/metrics/util.ts +0 -11
  192. package/src/rate-limiting/background/fixed-frequency.ts +0 -47
  193. package/src/rate-limiting/index.ts +0 -100
  194. package/src/rate-limiting/metrics.ts +0 -18
  195. package/src/rate-limiting/request/simple-counting.ts +0 -76
  196. package/src/test.ts +0 -5
  197. package/src/transports/batch-warming.ts +0 -121
  198. package/src/transports/index.ts +0 -173
  199. package/src/transports/metrics.ts +0 -95
  200. package/src/transports/rest.ts +0 -161
  201. package/src/transports/util.ts +0 -63
  202. package/src/transports/websocket.ts +0 -238
  203. package/src/util/expiring-sorted-set.ts +0 -52
  204. package/src/util/index.ts +0 -20
  205. package/src/util/logger.ts +0 -69
  206. package/src/util/request.ts +0 -115
  207. package/src/validation/error.ts +0 -116
  208. package/src/validation/index.ts +0 -101
  209. package/src/validation/input-params.ts +0 -45
  210. package/src/validation/override-functions.ts +0 -44
  211. package/src/validation/preset-tokens.json +0 -23
  212. package/src/validation/validator.ts +0 -384
  213. package/test/adapter.test.ts +0 -27
  214. package/test/background-executor.test.ts +0 -109
  215. package/test/cache/cache-key.test.ts +0 -96
  216. package/test/cache/helper.ts +0 -101
  217. package/test/cache/local.test.ts +0 -54
  218. package/test/cache/redis.test.ts +0 -89
  219. package/test/correlation.test.ts +0 -114
  220. package/test/index.test.ts +0 -37
  221. package/test/metrics/feed-id.test.ts +0 -33
  222. package/test/metrics/helper.ts +0 -14
  223. package/test/metrics/labels.test.ts +0 -36
  224. package/test/metrics/metrics.test.ts +0 -267
  225. package/test/metrics/redis-metrics.test.ts +0 -113
  226. package/test/metrics/warmer-metrics.test.ts +0 -192
  227. package/test/metrics/ws-metrics.test.ts +0 -225
  228. package/test/rate-limit-config.test.ts +0 -243
  229. package/test/transports/batch.test.ts +0 -465
  230. package/test/transports/rest.test.ts +0 -242
  231. package/test/transports/websocket.test.ts +0 -183
  232. package/test/tsconfig.json +0 -5
  233. package/test/util.ts +0 -76
  234. package/test/validation.test.ts +0 -169
  235. package/test.sh +0 -20
  236. package/tsconfig.json +0 -24
  237. package/typedoc.json +0 -6
@@ -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;
package/.c8rc.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "reporter": ["lcov", "text"]
3
- }
package/.eslintignore DELETED
@@ -1,9 +0,0 @@
1
- # don't ever lint node_modules
2
- node_modules
3
- # don't lint build output (make sure it's set to your correct build folder name)
4
- dist
5
- # don't lint coverage output
6
- coverage
7
-
8
- .yarn
9
- .vscode
package/.eslintrc.js DELETED
@@ -1,96 +0,0 @@
1
- // https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/README.md
2
- module.exports = {
3
- root: true,
4
- parser: '@typescript-eslint/parser',
5
- plugins: ['@typescript-eslint', 'eslint-plugin-tsdoc'],
6
- extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
7
- rules: {
8
- 'tsdoc/syntax': 'warn',
9
-
10
- // Problems
11
- 'array-callback-return': [
12
- 'error',
13
- {
14
- allowImplicit: false,
15
- checkForEach: true,
16
- },
17
- ],
18
- 'no-constant-binary-expression': 'error',
19
- 'no-constructor-return': 'error',
20
- 'no-duplicate-imports': 'error',
21
- 'no-promise-executor-return': 'error',
22
- 'no-self-compare': 'error',
23
- 'no-template-curly-in-string': 'error',
24
- 'no-unmodified-loop-condition': 'error',
25
- 'no-unreachable-loop': 'error',
26
- 'no-unused-private-class-members': 'error',
27
- 'require-atomic-updates': 'error',
28
-
29
- // Suggestions
30
- 'capitalized-comments': ['error', 'always', { ignoreConsecutiveComments: true }],
31
- complexity: ['error', 25], // TODO: Should be lower (15?), but validator has complex methods
32
- curly: 'error',
33
- 'default-case-last': 'error',
34
- 'default-param-last': 'error',
35
- eqeqeq: ['error', 'smart'],
36
- 'func-names': 'error',
37
- 'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
38
- 'grouped-accessor-pairs': ['error', 'getBeforeSet'],
39
- 'max-depth': ['error', 4], // TODO: Should be lower (3), but validator has complex methods
40
- 'max-nested-callbacks': ['error', 2],
41
- 'max-params': ['error', 4], // TODO: Should be lower (3), but validator has complex methods,
42
- 'new-cap': ['error', { newIsCapExceptions: ['ctor'] }],
43
- 'no-caller': 'error',
44
- 'no-confusing-arrow': [
45
- 'error',
46
- {
47
- allowParens: true,
48
- },
49
- ],
50
- 'no-console': ['warn'], // We want this to debug, but the check workflow should accept no warns
51
- 'no-div-regex': 'error',
52
- 'no-eval': 'error',
53
- 'no-extend-native': 'error',
54
- 'no-extra-bind': 'error',
55
- 'no-extra-label': 'error',
56
- 'no-extra-semi': 'error',
57
- 'no-floating-decimal': 'error',
58
- 'no-implied-eval': 'error',
59
- 'no-invalid-this': 'error',
60
- 'no-labels': 'error',
61
- 'no-lonely-if': 'error',
62
- 'no-multi-assign': 'error',
63
- 'no-multi-str': 'error',
64
- 'no-nested-ternary': 'error',
65
- 'no-new': 'error',
66
- 'no-new-func': 'error',
67
- 'no-new-object': 'error',
68
- 'no-new-wrappers': 'error',
69
- 'no-param-reassign': 'error',
70
- 'no-proto': 'error',
71
- 'no-return-assign': 'error',
72
- 'no-return-await': 'error',
73
- 'no-sequences': 'error',
74
- 'no-shadow': 'off',
75
- '@typescript-eslint/no-shadow': 'error', // https://stackoverflow.com/questions/63961803/eslint-says-all-enums-in-typescript-app-are-already-declared-in-the-upper-scope
76
- 'no-unneeded-ternary': 'error',
77
- 'no-useless-call': 'error',
78
- 'no-useless-computed-key': 'error',
79
- 'no-useless-concat': 'error',
80
- 'no-useless-rename': 'error',
81
- 'no-var': 'error',
82
- 'operator-assignment': ['error', 'always'],
83
- 'prefer-arrow-callback': 'error',
84
- 'prefer-const': 'error',
85
- 'prefer-exponentiation-operator': 'error',
86
- 'prefer-object-spread': 'error',
87
- 'prefer-promise-reject-errors': 'error',
88
- 'prefer-regex-literals': 'error',
89
- 'prefer-rest-params': 'error',
90
- 'prefer-spread': 'error',
91
- 'prefer-template': 'error',
92
- 'spaced-comment': ['error', 'always'],
93
- 'symbol-description': 'error',
94
- yoda: 'error',
95
- },
96
- }
package/.github/README.MD DELETED
@@ -1,17 +0,0 @@
1
- # Github workflows for EAv3 Framework
2
-
3
- **Please note that this work is in progress. The README may not be accurate**
4
-
5
- ## Overview
6
- This directory contains a basic GitHub workflow that builds, tests, and ultimately publishes the EAv3 Framework to NPM
7
- 1. Setup (caches dependencies to speed up other steps)
8
- 2. Build/Prepare/Preflight (all the following happen at the same time)
9
- 1. yarn build => publish artifact of build
10
- 2. yarn lint
11
- 3. yarn test
12
- 3. Publish (currently unimplemented)
13
-
14
- ### Some steps that still need to be added in:
15
- 1. Check that changelog has an entry matching the current version in package.json
16
- 2. Check if a package is already published to NPM, and DON'T overwrite it unless a parameter explicitly allowing an overwrite has been passed
17
- 3. npm-check step that produces a report as an artifact
@@ -1,13 +0,0 @@
1
- name: 'Setup'
2
- description: 'Sets up the project, installs dependencies, and builds'
3
- runs:
4
- using: 'composite'
5
- steps:
6
- - uses: actions/setup-node@v3
7
- with:
8
- node-version: 16.x
9
- registry-url: https://registry.npmjs.org
10
- always-auth: true
11
- cache: yarn
12
- - run: yarn install --frozen-lockfile
13
- shell: bash
@@ -1,39 +0,0 @@
1
- # This is the entry point for CI. It will setup the application, then run lint, test, and eventually publish if not the master or main branch
2
- name: 'Main'
3
- on:
4
- push:
5
- branches:
6
- - master
7
- pull_request: ~
8
-
9
- jobs:
10
- setup: # Load the dependencies cache for all jobs
11
- runs-on: ubuntu-latest
12
- steps:
13
- - uses: actions/checkout@v3
14
- - uses: ./.github/actions/setup
15
- build:
16
- needs: setup
17
- runs-on: ubuntu-latest
18
- concurrency: build-${{ github.ref}}
19
- steps:
20
- - uses: actions/checkout@v3
21
- - uses: ./.github/actions/setup
22
- - run: yarn build
23
- lint:
24
- needs: setup
25
- runs-on: ubuntu-latest
26
- concurrency: lint-${{ github.ref }}
27
- steps:
28
- - uses: actions/checkout@v3
29
- - uses: ./.github/actions/setup
30
- - run: yarn lint
31
- - run: yarn prettier --check **/*.{ts,md}
32
- test:
33
- needs: setup
34
- concurrency: test-${{ github.ref }}
35
- runs-on: ubuntu-latest
36
- steps:
37
- - uses: actions/checkout@v3
38
- - uses: ./.github/actions/setup
39
- - run: yarn test
@@ -1,17 +0,0 @@
1
- # This is the entry point for CI. It will setup the application, then run lint, test, and eventually publish if not the master or main branch
2
- name: 'Publish'
3
- on:
4
- workflow_dispatch:
5
- push:
6
- branches:
7
- - master
8
- jobs:
9
- publish: # Load the dependencies cache for all jobs
10
- runs-on: ubuntu-latest
11
- environment: main
12
- steps:
13
- - uses: actions/checkout@v3
14
- - uses: ./.github/actions/setup
15
- - run: npm publish --access restricted #scoped packages are restricted by default, but this is set because not all branches currently have a scoped package name
16
- env:
17
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/.prettierignore DELETED
@@ -1,13 +0,0 @@
1
- # don't ever lint node_modules
2
- node_modules
3
- # don't lint build output (make sure it's set to your correct build folder name)
4
- dist
5
- # don't lint nyc coverage output
6
- coverage
7
- test-payload.json
8
- .yarn
9
- .vscode
10
- .pnp.cjs
11
- .pnp.loader.mjs
12
-
13
- packages/k6/k8s/templates
package/.yarnrc DELETED
File without changes
package/README.md DELETED
@@ -1,103 +0,0 @@
1
- # EA Framework v3
2
-
3
- External adapters and its core framework serve as middleware to facilitate connections between Chainlink Nodes and Data Providers (DP). Their main purpose is threefold:
4
-
5
- - Abstract provider specific details, specifically:
6
- - Transport (REST, WebSockets, RPC, SSE, etc.)
7
- - Authentication (login flows, keys)
8
- - Accept normalized request payloads and translate into the provider's interface (this also includes things like symbols/tickers)
9
- - Parse provider responses into the desired data points (e.g. price from crypto endpoint)
10
- - Make the overall system more efficient by using as few resources (e.g. API credits, networking traffic, CPU usage) as possible to fetch data, achieved by features like:
11
- - Caching: since DPs update data at various times and a request to their API incurs a certain latency, EAs keep a cache of values to
12
- - Provide responses to the Chainlink Nodes as quickly as possible
13
- - Communicate with DPs only when necessary
14
- - Cache Warming: in order to make as many of the requests to EAs be fulfilled from the cache, EAs fetch values from DPs asynchronously to keep the local ones fresh.
15
- - Batching: the CL Node requests feeds individually, but it's common for DPs to provide batch endpoints to get many data points at once. With Batching, EAs keep track of incoming requests and consolidate them into one batched request.
16
- - Rate limiting: the EA framework additionally checks request rates (frequency) to make sure they fall within acceptable limits (like quotas for the DP's API, or adjusting based on the NOP's API tier).
17
- - Perform off chain computations (think aggregations, indexing, or any sort of data processing)
18
-
19
- By providing a framework that gives users easy access to those features, we reduce the complexity required for Nodes to communicate with DPs since by using EAs there is only one standardized way to do so, while at the same time optimizing said communication so it's as resource efficient as possible. It also makes internal and external development easier and faster, by serving as a strict guideline to implement and add new providers.
20
-
21
- ## Qs
22
-
23
- - Store entire response in cache?
24
- - Check for valid result in adapter response?
25
-
26
- ## Env vars
27
-
28
- These are all existing env vars, marked DONE if they have been ported to this version, or N/A if the new version disregards them altogether.
29
-
30
- | Name | State | Comments |
31
- | :----------------------------------------- | :---: | :----------------------------------------------------------- |
32
- | API_TIMEOUT | N/A | Only used for WS with handler.noHTtp = true |
33
- | BASE_URL | √ | |
34
- | CACHE_ENABLED | N/A | Cache is integral to this fw, not including this for now |
35
- | CACHE_KEY_IGNORED_PROPS | ?? | Do we want this to be available in v3. Used for feed id |
36
- | CACHE_KEY_GROUP | ?? | Dunno if this applies to this fw |
37
- | CACHE_MAX_AGE | √ | |
38
- | CACHE_MAX_ITEMS | - | Should add when replacing obj in local impl with LRU package |
39
- | CACHE_MIN_AGE | - | Used for rate limiting |
40
- | CACHE_REDIS_CONNECTION_TIMEOUT | - | TODO: Redis |
41
- | CACHE_REDIS_HOST | - | TODO: Redis |
42
- | CACHE_REDIS_MAX_QUEUED_ITEMS | - | TODO: Redis |
43
- | CACHE_REDIS_MAX_RECONNECT_COOLDOWN | - | TODO: Redis |
44
- | CACHE_REDIS_PASSWORD | - | TODO: Redis |
45
- | CACHE_REDIS_PATH | - | TODO: Redis |
46
- | CACHE_REDIS_PORT | - | TODO: Redis |
47
- | CACHE_REDIS_TIMEOUT | - | TODO: Redis |
48
- | CACHE_REDIS_URL | - | TODO: Redis |
49
- | CACHE_TYPE | - | TODO: Cache factory |
50
- | CACHE_UPDATE_AGE_ON_GET | N/A | No longer used in EA currently, apparently |
51
- | DEBUG | | |
52
- | DEFAULT_WS_HEARTBEAT_INTERVAL | | |
53
- | EA_HOST | | |
54
- | EA_PORT | √ | |
55
- | ENV_ADAPTER_URL | | |
56
- | ENV_API_ENDPOINT | | |
57
- | ENV_API_KEY | | |
58
- | ENV_API_TIMEOUT | | |
59
- | ENV_API_VERBOSE | | |
60
- | ENV_WS_API_ENDPOINT | | |
61
- | ENV_WS_API_KEY | | |
62
- | ERROR_CAPACITY | | |
63
- | EXPERIMENTAL_METRICS_ENABLED | √ | Maintaining for backwards compatibility. Defaults to true |
64
- | LEGACY_ENV_ADAPTER_URL | | |
65
- | LOG_LEVEL | | |
66
- | METRICS_ENABLED | √ | Defaults to true |
67
- | METRICS_NAME | √ | |
68
- | METRICS_PORT | √ | |
69
- | METRICS_USE_BASE_URL | √ | |
70
- | NODE_ENV | | |
71
- | npm_package_version | | |
72
- | RATE_LIMIT_API_TIER | | |
73
- | RATE_LIMIT_CAPACITY | | |
74
- | RATE_LIMIT_CAPACITY_MINUTE | | |
75
- | RATE_LIMIT_CAPACITY_SECOND | | |
76
- | RATE_LIMIT_ENABLED | | |
77
- | RECORD | | |
78
- | REQUEST_COALESCING_ENABLED | | |
79
- | REQUEST_COALESCING_ENTROPY_MAX | | |
80
- | REQUEST_COALESCING_INTERVAL | | |
81
- | REQUEST_COALESCING_INTERVAL_COEFFICIENT | | |
82
- | REQUEST_COALESCING_INTERVAL_MAX | | |
83
- | REQUEST_COALESCING_MAX_RETRIES | | |
84
- | RETRY | | |
85
- | SERVER_RATE_LIMIT_MAX | | |
86
- | SERVER_SLOW_DOWN_AFTER_FACTOR | | |
87
- | SERVER_SLOW_DOWN_DELAY_MS | | |
88
- | TIMEOUT | | |
89
- | WARMUP_ENABLED | | |
90
- | WARMUP_INTERVAL | | |
91
- | WARMUP_SUBSCRIPTION_TTL | | |
92
- | WARMUP_UNHEALTHY_THRESHOLD | | |
93
- | WS_CONNECTION_KEY | | |
94
- | WS_CONNECTION_LIMIT | | |
95
- | WS_CONNECTION_RETRY_DELAY | | |
96
- | WS_CONNECTION_RETRY_LIMIT | | |
97
- | WS_CONNECTION_TTL | | |
98
- | WS_ENABLED | N/A | Shouldn't be part of this fw |
99
- | WS_SUBSCRIPTION_LIMIT | | |
100
- | WS_SUBSCRIPTION_PRIORITY_LIST | | |
101
- | WS_SUBSCRIPTION_TTL | | |
102
- | WS_SUBSCRIPTION_UNRESPONSIVE_TTL | | |
103
- | WS_TIME_UNTIL_HANDLE_NEXT_MESSAGE_OVERRIDE | | |
@@ -1,35 +0,0 @@
1
- # Very basic stack to demonstrate horizontal scaling
2
- services:
3
- redis:
4
- image: redis
5
- container_name: redis
6
-
7
- coingecko-reader:
8
- image: node:alpine
9
- ports:
10
- - 8080
11
- deploy:
12
- mode: replicated
13
- replicas: 2
14
- environment:
15
- - DISABLE_BACKGROUND_EXECUTOR=true
16
- volumes:
17
- - ./:/home/node/app
18
- command: node /home/node/app/dist/test.js
19
-
20
- coingecko-writer:
21
- image: node:alpine
22
- volumes:
23
- - ./:/home/node/app
24
- environment:
25
- - DISABLE_REST_API=true
26
- command: node /home/node/app/dist/test.js
27
-
28
- lb:
29
- image: dockercloud/haproxy
30
- links:
31
- - coingecko-reader
32
- ports:
33
- - '80:80'
34
- volumes:
35
- - /var/run/docker.sock:/var/run/docker.sock