@chainlink/external-adapter-framework 0.5.0 → 0.5.1

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 (213) hide show
  1. package/adapter/basic.d.ts +90 -0
  2. package/adapter/basic.js +325 -0
  3. package/adapter/basic.js.map +1 -0
  4. package/adapter/endpoint.d.ts +17 -0
  5. package/adapter/endpoint.js +20 -0
  6. package/adapter/endpoint.js.map +1 -0
  7. package/adapter/index.d.ts +4 -0
  8. package/adapter/index.js +21 -0
  9. package/adapter/index.js.map +1 -0
  10. package/adapter/price.d.ts +77 -0
  11. package/adapter/price.js +88 -0
  12. package/adapter/price.js.map +1 -0
  13. package/adapter/types.d.ts +124 -0
  14. package/adapter/types.js +3 -0
  15. package/adapter/types.js.map +1 -0
  16. package/background-executor.d.ts +9 -0
  17. package/background-executor.js +97 -0
  18. package/background-executor.js.map +1 -0
  19. package/cache/factory.d.ts +6 -0
  20. package/cache/factory.js +24 -0
  21. package/cache/factory.js.map +1 -0
  22. package/cache/index.d.ts +87 -0
  23. package/cache/index.js +133 -0
  24. package/cache/index.js.map +1 -0
  25. package/cache/local.d.ts +23 -0
  26. package/cache/local.js +84 -0
  27. package/cache/local.js.map +1 -0
  28. package/cache/metrics.d.ts +27 -0
  29. package/cache/metrics.js +121 -0
  30. package/cache/metrics.js.map +1 -0
  31. package/cache/redis.d.ts +16 -0
  32. package/cache/redis.js +101 -0
  33. package/cache/redis.js.map +1 -0
  34. package/config/index.d.ts +298 -0
  35. package/config/index.js +359 -0
  36. package/config/index.js.map +1 -0
  37. package/config/provider-limits.d.ts +27 -0
  38. package/config/provider-limits.js +75 -0
  39. package/config/provider-limits.js.map +1 -0
  40. package/examples/bank-frick/accounts.d.ts +45 -0
  41. package/examples/bank-frick/accounts.js +203 -0
  42. package/examples/bank-frick/accounts.js.map +1 -0
  43. package/examples/bank-frick/config/index.d.ts +17 -0
  44. package/examples/bank-frick/config/index.js +55 -0
  45. package/examples/bank-frick/config/index.js.map +1 -0
  46. package/examples/bank-frick/index.d.ts +2 -0
  47. package/examples/bank-frick/index.js +16 -0
  48. package/examples/bank-frick/index.js.map +1 -0
  49. package/examples/bank-frick/util.d.ts +4 -0
  50. package/examples/bank-frick/util.js +40 -0
  51. package/examples/bank-frick/util.js.map +1 -0
  52. package/examples/coingecko/src/config/index.d.ts +2 -0
  53. package/examples/coingecko/src/config/index.js +6 -0
  54. package/examples/coingecko/src/config/index.js.map +1 -0
  55. package/examples/coingecko/src/config/overrides.json +10825 -0
  56. package/examples/coingecko/src/crypto-utils.d.ts +62 -0
  57. package/examples/coingecko/src/crypto-utils.js +60 -0
  58. package/examples/coingecko/src/crypto-utils.js.map +1 -0
  59. package/examples/coingecko/src/endpoint/coins.d.ts +26 -0
  60. package/examples/coingecko/src/endpoint/coins.js +37 -0
  61. package/examples/coingecko/src/endpoint/coins.js.map +1 -0
  62. package/examples/coingecko/src/endpoint/crypto-marketcap.d.ts +3 -0
  63. package/examples/coingecko/src/endpoint/crypto-marketcap.js +30 -0
  64. package/examples/coingecko/src/endpoint/crypto-marketcap.js.map +1 -0
  65. package/examples/coingecko/src/endpoint/crypto-volume.d.ts +3 -0
  66. package/examples/coingecko/src/endpoint/crypto-volume.js +30 -0
  67. package/examples/coingecko/src/endpoint/crypto-volume.js.map +1 -0
  68. package/examples/coingecko/src/endpoint/crypto.d.ts +3 -0
  69. package/examples/coingecko/src/endpoint/crypto.js +28 -0
  70. package/examples/coingecko/src/endpoint/crypto.js.map +1 -0
  71. package/examples/coingecko/src/endpoint/dominance.d.ts +3 -0
  72. package/examples/coingecko/src/endpoint/dominance.js +28 -0
  73. package/examples/coingecko/src/endpoint/dominance.js.map +1 -0
  74. package/examples/coingecko/src/endpoint/global-marketcap.d.ts +3 -0
  75. package/examples/coingecko/src/endpoint/global-marketcap.js +28 -0
  76. package/examples/coingecko/src/endpoint/global-marketcap.js.map +1 -0
  77. package/examples/coingecko/src/endpoint/index.d.ts +6 -0
  78. package/examples/coingecko/src/endpoint/index.js +16 -0
  79. package/examples/coingecko/src/endpoint/index.js.map +1 -0
  80. package/examples/coingecko/src/global-utils.d.ts +42 -0
  81. package/examples/coingecko/src/global-utils.js +47 -0
  82. package/examples/coingecko/src/global-utils.js.map +1 -0
  83. package/examples/coingecko/src/index.d.ts +4 -0
  84. package/examples/coingecko/src/index.js +19 -0
  85. package/examples/coingecko/src/index.js.map +1 -0
  86. package/examples/coingecko-old/batch-warming.d.ts +7 -0
  87. package/examples/coingecko-old/batch-warming.js +54 -0
  88. package/examples/coingecko-old/batch-warming.js.map +1 -0
  89. package/examples/coingecko-old/index.d.ts +2 -0
  90. package/examples/coingecko-old/index.js +12 -0
  91. package/examples/coingecko-old/index.js.map +1 -0
  92. package/examples/coingecko-old/rest.d.ts +12 -0
  93. package/examples/coingecko-old/rest.js +55 -0
  94. package/examples/coingecko-old/rest.js.map +1 -0
  95. package/examples/cryptocompare/src/config/index.d.ts +2 -0
  96. package/examples/cryptocompare/src/config/index.js +6 -0
  97. package/examples/cryptocompare/src/config/index.js.map +1 -0
  98. package/examples/cryptocompare/src/endpoints/crypto.d.ts +40 -0
  99. package/examples/cryptocompare/src/endpoints/crypto.js +54 -0
  100. package/examples/cryptocompare/src/endpoints/crypto.js.map +1 -0
  101. package/examples/cryptocompare/src/endpoints/index.d.ts +1 -0
  102. package/examples/cryptocompare/src/endpoints/index.js +6 -0
  103. package/examples/cryptocompare/src/endpoints/index.js.map +1 -0
  104. package/examples/cryptocompare/src/index.d.ts +4 -0
  105. package/examples/cryptocompare/src/index.js +14 -0
  106. package/examples/cryptocompare/src/index.js.map +1 -0
  107. package/examples/genesis/config/index.d.ts +7 -0
  108. package/examples/genesis/config/index.js +11 -0
  109. package/examples/genesis/config/index.js.map +1 -0
  110. package/examples/genesis/index.d.ts +2 -0
  111. package/examples/genesis/index.js +13 -0
  112. package/examples/genesis/index.js.map +1 -0
  113. package/examples/genesis/sseStream.d.ts +27 -0
  114. package/examples/genesis/sseStream.js +149 -0
  115. package/examples/genesis/sseStream.js.map +1 -0
  116. package/examples/ncfx/config/index.d.ts +12 -0
  117. package/examples/ncfx/config/index.js +16 -0
  118. package/examples/ncfx/config/index.js.map +1 -0
  119. package/examples/ncfx/index.d.ts +2 -0
  120. package/examples/ncfx/index.js +12 -0
  121. package/examples/ncfx/index.js.map +1 -0
  122. package/examples/ncfx/websocket.d.ts +37 -0
  123. package/examples/ncfx/websocket.js +74 -0
  124. package/examples/ncfx/websocket.js.map +1 -0
  125. package/index.d.ts +17 -0
  126. package/index.js +174 -0
  127. package/index.js.map +1 -0
  128. package/metrics/constants.d.ts +16 -0
  129. package/metrics/constants.js +26 -0
  130. package/metrics/constants.js.map +1 -0
  131. package/metrics/index.d.ts +19 -0
  132. package/metrics/index.js +139 -0
  133. package/metrics/index.js.map +1 -0
  134. package/metrics/util.d.ts +7 -0
  135. package/metrics/util.js +10 -0
  136. package/metrics/util.js.map +1 -0
  137. package/package.json +50 -42
  138. package/rate-limiting/background/fixed-frequency.d.ts +10 -0
  139. package/rate-limiting/background/fixed-frequency.js +36 -0
  140. package/rate-limiting/background/fixed-frequency.js.map +1 -0
  141. package/rate-limiting/index.d.ts +56 -0
  142. package/rate-limiting/index.js +86 -0
  143. package/rate-limiting/index.js.map +1 -0
  144. package/rate-limiting/metrics.d.ts +3 -0
  145. package/rate-limiting/metrics.js +45 -0
  146. package/rate-limiting/metrics.js.map +1 -0
  147. package/rate-limiting/request/simple-counting.d.ts +20 -0
  148. package/rate-limiting/request/simple-counting.js +63 -0
  149. package/rate-limiting/request/simple-counting.js.map +1 -0
  150. package/transports/batch-warming.d.ts +53 -0
  151. package/transports/batch-warming.js +136 -0
  152. package/transports/batch-warming.js.map +1 -0
  153. package/transports/index.d.ts +108 -0
  154. package/transports/index.js +56 -0
  155. package/transports/index.js.map +1 -0
  156. package/transports/inference-test.d.ts +0 -0
  157. package/transports/inference-test.js +202 -0
  158. package/transports/inference-test.js.map +1 -0
  159. package/transports/metrics.d.ts +25 -0
  160. package/transports/metrics.js +122 -0
  161. package/transports/metrics.js.map +1 -0
  162. package/transports/rest.d.ts +68 -0
  163. package/transports/rest.js +131 -0
  164. package/transports/rest.js.map +1 -0
  165. package/transports/routing.d.ts +21 -0
  166. package/transports/routing.js +50 -0
  167. package/transports/routing.js.map +1 -0
  168. package/transports/sse.d.ts +61 -0
  169. package/transports/sse.js +97 -0
  170. package/transports/sse.js.map +1 -0
  171. package/transports/util.d.ts +9 -0
  172. package/transports/util.js +87 -0
  173. package/transports/util.js.map +1 -0
  174. package/transports/websocket.d.ts +95 -0
  175. package/transports/websocket.js +164 -0
  176. package/transports/websocket.js.map +1 -0
  177. package/util/censor/censor-list.d.ts +9 -0
  178. package/util/censor/censor-list.js +13 -0
  179. package/util/censor/censor-list.js.map +1 -0
  180. package/util/index.d.ts +13 -0
  181. package/util/index.js +38 -0
  182. package/util/index.js.map +1 -0
  183. package/util/logger.d.ts +49 -0
  184. package/util/logger.js +123 -0
  185. package/util/logger.js.map +1 -0
  186. package/util/request.d.ts +138 -0
  187. package/util/request.js +3 -0
  188. package/util/request.js.map +1 -0
  189. package/util/subscription-set/expiring-sorted-set.d.ts +21 -0
  190. package/util/subscription-set/expiring-sorted-set.js +36 -0
  191. package/util/subscription-set/expiring-sorted-set.js.map +1 -0
  192. package/util/subscription-set/redis-sorted-set.d.ts +9 -0
  193. package/util/subscription-set/redis-sorted-set.js +29 -0
  194. package/util/subscription-set/redis-sorted-set.js.map +1 -0
  195. package/util/subscription-set/subscription-set.d.ts +19 -0
  196. package/util/subscription-set/subscription-set.js +28 -0
  197. package/util/subscription-set/subscription-set.js.map +1 -0
  198. package/util/test-payload-loader.d.ts +26 -0
  199. package/util/test-payload-loader.js +85 -0
  200. package/util/test-payload-loader.js.map +1 -0
  201. package/validation/error.d.ts +48 -0
  202. package/validation/error.js +78 -0
  203. package/validation/error.js.map +1 -0
  204. package/validation/index.d.ts +5 -0
  205. package/validation/index.js +102 -0
  206. package/validation/index.js.map +1 -0
  207. package/validation/input-params.d.ts +14 -0
  208. package/validation/input-params.js +3 -0
  209. package/validation/input-params.js.map +1 -0
  210. package/validation/input-validator.d.ts +16 -0
  211. package/validation/input-validator.js +123 -0
  212. package/validation/input-validator.js.map +1 -0
  213. package/README.md +0 -102
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PriceAdapter = exports.PriceEndpoint = exports.priceEndpointInputParameters = void 0;
4
+ const endpoint_1 = require("./endpoint");
5
+ const index_1 = require("./index");
6
+ /**
7
+ * Base input parameter config that any [[PriceEndpoint]] must extend
8
+ */
9
+ exports.priceEndpointInputParameters = {
10
+ base: {
11
+ aliases: ['from', 'coin'],
12
+ type: 'string',
13
+ description: 'The symbol of symbols of the currency to query',
14
+ required: true,
15
+ },
16
+ quote: {
17
+ aliases: ['to', 'market'],
18
+ type: 'string',
19
+ description: 'The symbol of the currency to convert to',
20
+ required: true,
21
+ },
22
+ };
23
+ /**
24
+ * A PriceEndpoint is a specific type of AdapterEndpoint. Meant to comply with standard practices for
25
+ * Data Feeds, its InputParameters must extend the basic ones (base/quote).
26
+ */
27
+ class PriceEndpoint extends endpoint_1.AdapterEndpoint {
28
+ constructor(params) {
29
+ super(params);
30
+ }
31
+ }
32
+ exports.PriceEndpoint = PriceEndpoint;
33
+ const buildIncludesMap = (includesFile) => {
34
+ const includesMap = {};
35
+ for (const { from, to, includes } of includesFile) {
36
+ if (!includesMap[from]) {
37
+ includesMap[from] = {};
38
+ }
39
+ includesMap[from][to] = includes[0];
40
+ }
41
+ return includesMap;
42
+ };
43
+ /**
44
+ * A PriceAdapter is a specific kind of Adapter that includes at least one PriceEnpoint.
45
+ */
46
+ class PriceAdapter extends index_1.Adapter {
47
+ constructor(params) {
48
+ // Doing this with types would be too complex to maintain
49
+ if (!params.endpoints.some((e) => e instanceof PriceEndpoint)) {
50
+ throw new Error(`This PriceAdapter's list of endpoints does not contain a valid PriceEndpoint`);
51
+ }
52
+ super(params);
53
+ if (params.includes) {
54
+ // Build includes map for constant lookups
55
+ this.includesMap = buildIncludesMap(params.includes);
56
+ const requestTransform = (req) => {
57
+ const priceRequest = req;
58
+ const requestData = priceRequest.requestContext.data;
59
+ const includesDetails = this.includesMap?.[requestData.base]?.[requestData.quote];
60
+ if (includesDetails) {
61
+ requestData.base = includesDetails.from || requestData.base;
62
+ requestData.quote = includesDetails.to || requestData.quote;
63
+ }
64
+ const inverse = includesDetails?.inverse || false;
65
+ priceRequest.requestContext.priceMeta = {
66
+ inverse,
67
+ };
68
+ };
69
+ this.requestTransforms?.push(requestTransform);
70
+ }
71
+ }
72
+ async handleRequest(req, replySent) {
73
+ const response = await super.handleRequest(req, replySent);
74
+ if (this.includesMap && req.requestContext.priceMeta.inverse) {
75
+ // We need to search in the reverse order (quote -> base) because the request transform will have inverted the pair
76
+ const inverseResult = 1 / response.result;
77
+ response.result = inverseResult;
78
+ // Check if response data has a result within it
79
+ const data = response.data;
80
+ if (data?.result) {
81
+ data.result = inverseResult;
82
+ }
83
+ }
84
+ return response;
85
+ }
86
+ }
87
+ exports.PriceAdapter = PriceAdapter;
88
+ //# sourceMappingURL=price.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price.js","sourceRoot":"","sources":["../../../src/adapter/price.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import type EventSource from 'eventsource';
2
+ import Redis from 'ioredis';
3
+ import { Cache } from '../cache';
4
+ import { AdapterConfig, BaseAdapterConfig, SettingsMap } from '../config';
5
+ import { AdapterRateLimitTier, BackgroundExecuteRateLimiter, RequestRateLimiter } from '../rate-limiting';
6
+ import { Transport, TransportGenerics } from '../transports';
7
+ import { AdapterRequest, SubscriptionSetFactory } from '../util';
8
+ import { InputParameters } from '../validation';
9
+ import { Adapter } from './basic';
10
+ import { AdapterEndpoint } from './endpoint';
11
+ export declare type CustomAdapterSettings = SettingsMap & NegatedAdapterSettings;
12
+ declare type NegatedAdapterSettings = {
13
+ [K in keyof BaseAdapterConfig]?: never;
14
+ };
15
+ /**
16
+ * Dependencies that will be injected into the Adapter on startup
17
+ */
18
+ export interface AdapterDependencies {
19
+ /** Specific instance of the Cache the adapter will use (e.g. Local, Redis, etc.) */
20
+ cache: Cache;
21
+ /** Shared instance of the request rate limiter */
22
+ requestRateLimiter: RequestRateLimiter;
23
+ /** Shared instance of the background execute rate limiter */
24
+ backgroundExecuteRateLimiter: BackgroundExecuteRateLimiter;
25
+ /** Factory to create subscription sets based on the specified cache type */
26
+ subscriptionSetFactory: SubscriptionSetFactory;
27
+ /** Redis client used for cache and subscription set */
28
+ redisClient: Redis;
29
+ /** EventSource to use for listening to server sent events. A mock EventSource can be provided as a dependency for testing */
30
+ eventSource: typeof EventSource;
31
+ }
32
+ /**
33
+ * Context that will be used on background executions of a Transport.
34
+ * For example, the endpointName used to log statements or generate Cache keys.
35
+ */
36
+ export interface AdapterContext<T extends EndpointGenerics> {
37
+ /** Endpoint instance within the adapter that the Transport is related to */
38
+ adapterEndpoint: AdapterEndpoint<T>;
39
+ /** Initialized config for the adapter that the Transport can access */
40
+ adapterConfig: AdapterConfig<T['CustomSettings']>;
41
+ }
42
+ /**
43
+ * Structure to describe rate limits specs for the Adapter
44
+ */
45
+ export interface AdapterRateLimitingConfig {
46
+ /** Adapter rate limits, gotten from the specific tier requested */
47
+ tiers: Record<string, AdapterRateLimitTier>;
48
+ }
49
+ /**
50
+ * Type to perform arbitrary modifications on an adapter request
51
+ */
52
+ export declare type RequestTransform = (req: AdapterRequest) => void;
53
+ /**
54
+ * Map of overrides objects (symbol -\> symbol) per adapter name
55
+ */
56
+ export declare type Overrides = {
57
+ [adapterName: string]: {
58
+ [symbol: string]: string;
59
+ };
60
+ };
61
+ /**
62
+ * Main structure of an External Adapter
63
+ */
64
+ export interface AdapterParams<CustomSettings extends SettingsMap> {
65
+ /** Name of the adapter */
66
+ name: Uppercase<string>;
67
+ /** If present, the string that will be used for requests with no specified endpoint */
68
+ defaultEndpoint?: string;
69
+ /**
70
+ * List of [[AdapterEndpoint]]s in the adapter. This is purposefully typed any; it's the correct type in this case.
71
+ *
72
+ * When you try to create an adapter and you provide an endpoint, if these generics were set to "unknown" instead
73
+ * what would happen is that Typescript would check if the types match, and would fail to assign unknown to the
74
+ * specific Params or Result in the transport itself.
75
+ * We also can't use generics, because if we had more than one transport with different requests (very likely)
76
+ * then those new types wouldn't match with each other.
77
+ */
78
+ endpoints: AdapterEndpoint<any>[];
79
+ /** Map of overrides to the default config values for an Adapter */
80
+ envDefaultOverrides?: Partial<BaseAdapterConfig>;
81
+ /** List of custom env vars for this particular adapter (e.g. RPC_URL) */
82
+ customSettings?: SettingsMap;
83
+ /** Configuration relevant to outbound (EA --\> DP) communication rate limiting */
84
+ rateLimiting?: AdapterRateLimitingConfig;
85
+ /** Overrides for converting the 'base' parameter that are hardcoded into the adapter. */
86
+ overrides?: Record<string, string>;
87
+ /** Transforms that will apply to the request before submitting it through the adapter request flow */
88
+ requestTransforms?: RequestTransform[];
89
+ /** Bootstrap function that will run when initializing the adapter */
90
+ bootstrap?: (adapter: Adapter<CustomSettings>) => Promise<void>;
91
+ }
92
+ /**
93
+ * Structure to describe rate limits specs for a specific adapter endpoint
94
+ */
95
+ export interface EndpointRateLimitingConfig {
96
+ /**
97
+ * How much of the total limit for the adapter will be assigned to this specific endpoint.
98
+ * Should be a non-zero positive number up to 100.
99
+ * Endpoints in the same adapter without a specific allocation will divide the remaining limits equally.
100
+ */
101
+ allocationPercentage: number;
102
+ }
103
+ /**
104
+ * Helper type structure that contains the different types passed to the generic parameters of an AdapterEndpoint
105
+ */
106
+ export declare type EndpointGenerics = TransportGenerics;
107
+ /**
108
+ * Structure to describe a specific endpoint in an [[Adapter]]
109
+ */
110
+ export interface AdapterEndpointParams<T extends EndpointGenerics> {
111
+ /** Name that will be used to match input params to this endpoint (case insensitive) */
112
+ name: string;
113
+ /** List of alternative endpoint names that will resolve to this same transport (case insensitive) */
114
+ aliases?: string[];
115
+ /** Transport that will be used to handle data processing and communication for this endpoint */
116
+ transport: Transport<T>;
117
+ /** Specification of what the body of a request hitting this endpoint should look like (used for validation) */
118
+ inputParameters: InputParameters;
119
+ /** Specific details related to the rate limiting for this endpoint in particular */
120
+ rateLimiting?: EndpointRateLimitingConfig;
121
+ /** Custom function that generates cache keys */
122
+ cacheKeyGenerator?: (data: Record<string, unknown>) => string;
123
+ }
124
+ export {};
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapter/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import { Adapter } from './adapter';
2
+ /**
3
+ * Very simple background loop that will call the [[Transport.backgroundExecute]] functions in all Transports.
4
+ * It gets the time in ms to wait as the return value from those functions, and sleeps until next execution.
5
+ *
6
+ * @param adapter - an initialized External Adapter
7
+ * @param server - the http server to attach an on close listener to
8
+ */
9
+ export declare function callBackgroundExecutes(adapter: Adapter, apiShutdownPromise?: Promise<void>): Promise<void>;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.callBackgroundExecutes = void 0;
27
+ const metrics = __importStar(require("./metrics"));
28
+ const util_1 = require("./util");
29
+ const logger = (0, util_1.makeLogger)('BackgroundExecutor');
30
+ /**
31
+ * Very simple background loop that will call the [[Transport.backgroundExecute]] functions in all Transports.
32
+ * It gets the time in ms to wait as the return value from those functions, and sleeps until next execution.
33
+ *
34
+ * @param adapter - an initialized External Adapter
35
+ * @param server - the http server to attach an on close listener to
36
+ */
37
+ async function callBackgroundExecutes(adapter, apiShutdownPromise) {
38
+ // Set up variable to check later on to see if we need to stop this background "thread"
39
+ // If no server is provided, the listener won't be set and serverClosed will always be false
40
+ let serverClosed = false;
41
+ const timeoutsMap = {};
42
+ apiShutdownPromise?.then(() => {
43
+ serverClosed = true;
44
+ for (const endpointName in timeoutsMap) {
45
+ logger.debug(`Clearing timeout for endpoint "${endpointName}"`);
46
+ timeoutsMap[endpointName].unref();
47
+ clearTimeout(timeoutsMap[endpointName]);
48
+ }
49
+ });
50
+ // Checks if an individual transport has a backgroundExecute function, and executes it if it does
51
+ const callBackgroundExecute = (endpoint, transport) => {
52
+ const backgroundExecute = transport.backgroundExecute?.bind(transport);
53
+ if (!backgroundExecute) {
54
+ logger.debug(`Endpoint "${endpoint.name}" has no background execute, skipping...`);
55
+ return;
56
+ }
57
+ const context = {
58
+ adapterEndpoint: endpoint,
59
+ adapterConfig: adapter.config,
60
+ };
61
+ const handler = async () => {
62
+ if (serverClosed) {
63
+ logger.info('Server closed, stopping recursive backgroundExecute handler chain');
64
+ return;
65
+ }
66
+ // Count number of background executions per endpoint
67
+ metrics.bgExecuteTotal.labels({ endpoint: endpoint.name }).inc();
68
+ // Time the duration of the background execute process excluding sleep time
69
+ const metricsTimer = metrics.bgExecuteDurationSeconds
70
+ .labels({ endpoint: endpoint.name })
71
+ .startTimer();
72
+ logger.debug(`Calling background execute for endpoint "${endpoint.name}"`);
73
+ const timeToWait = await backgroundExecute(context);
74
+ logger.debug(`Finished background execute for endpoint "${endpoint.name}", sleeping for ${timeToWait}ms`);
75
+ metricsTimer();
76
+ timeoutsMap[endpoint.name] = setTimeout(handler, timeToWait);
77
+ };
78
+ // Start recursive async calls
79
+ handler();
80
+ };
81
+ for (const endpoint of adapter.endpoints) {
82
+ const { transport } = endpoint;
83
+ // Check if transport is a MetaTransport by casting and checking a known property (transports)
84
+ const castMeta = transport;
85
+ if (castMeta.transports) {
86
+ logger.debug(`Encountered MetaTransport ${transport.constructor.name}, calling backgroundExecute on all transports`);
87
+ for (const nestedTransport of Object.values(castMeta.transports)) {
88
+ callBackgroundExecute(endpoint, nestedTransport);
89
+ }
90
+ }
91
+ else {
92
+ callBackgroundExecute(endpoint, transport);
93
+ }
94
+ }
95
+ }
96
+ exports.callBackgroundExecutes = callBackgroundExecutes;
97
+ //# sourceMappingURL=background-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"background-executor.js","sourceRoot":"","sources":["../../src/background-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import Redis from 'ioredis';
2
+ import { LocalCache } from './local';
3
+ import { RedisCache } from './redis';
4
+ export declare class CacheFactory {
5
+ static buildCache(cacheType: string, redisClient?: Redis): LocalCache<unknown> | RedisCache<unknown> | undefined;
6
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CacheFactory = void 0;
4
+ const util_1 = require("../util");
5
+ const local_1 = require("./local");
6
+ const redis_1 = require("./redis");
7
+ const logger = (0, util_1.makeLogger)('CacheFactory');
8
+ class CacheFactory {
9
+ static buildCache(cacheType, redisClient) {
10
+ logger.info(`Using "${cacheType}" cache.`);
11
+ switch (cacheType) {
12
+ case 'local':
13
+ return new local_1.LocalCache();
14
+ case 'redis': {
15
+ if (!redisClient) {
16
+ throw new Error('Redis client undefined. Cannot create Redis cache');
17
+ }
18
+ return new redis_1.RedisCache(redisClient);
19
+ }
20
+ }
21
+ }
22
+ }
23
+ exports.CacheFactory = CacheFactory;
24
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/cache/factory.ts"],"names":[],"mappings":";;;AACA,kCAAoC;AACpC,mCAAoC;AACpC,mCAAoC;AAEpC,MAAM,MAAM,GAAG,IAAA,iBAAU,EAAC,cAAc,CAAC,CAAA;AACzC,MAAa,YAAY;IACvB,MAAM,CAAC,UAAU,CAAC,SAAiB,EAAE,WAAmB;QACtD,MAAM,CAAC,IAAI,CAAC,UAAU,SAAS,UAAU,CAAC,CAAA;QAC1C,QAAQ,SAAS,EAAE;YACjB,KAAK,OAAO;gBACV,OAAO,IAAI,kBAAU,EAAE,CAAA;YACzB,KAAK,OAAO,CAAC,CAAC;gBACZ,IAAI,CAAC,WAAW,EAAE;oBAChB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;iBACrE;gBACD,OAAO,IAAI,kBAAU,CAAC,WAAW,CAAC,CAAA;aACnC;SACF;IACH,CAAC;CACF;AAdD,oCAcC"}
@@ -0,0 +1,87 @@
1
+ import { AdapterEndpoint } from '../adapter';
2
+ import { AdapterConfig, SettingsMap } from '../config';
3
+ import { AdapterResponse, sleep } from '../util';
4
+ export * from './factory';
5
+ export * from './local';
6
+ export * from './redis';
7
+ /**
8
+ * An object describing an entry in the cache.
9
+ * @typeParam T - the type of the entry's value
10
+ */
11
+ export interface CacheEntry<T> {
12
+ key: string;
13
+ value: T;
14
+ }
15
+ /**
16
+ * Generic interface for a local or remote Cache.
17
+ * @typeParam T - the type of the cache entries' values
18
+ */
19
+ export interface Cache<T = unknown> {
20
+ /**
21
+ * Gets an item from the Cache.
22
+ *
23
+ * @param key - the key of the desired entry for which to fetch its value
24
+ * @returns a Promise of the entry's value, or undefined if not found / expired.
25
+ */
26
+ get: (key: string) => Promise<T | undefined>;
27
+ /**
28
+ * Sets an item in the Cache.
29
+ *
30
+ * @param key - the key of the new entry
31
+ * @param value - the value of the new entry
32
+ * @param ttl - the time in milliseconds until the entry expires
33
+ * @returns an empty Promise that resolves when the entry has been set
34
+ */
35
+ set: (key: string, value: T, ttl: number) => Promise<void>;
36
+ /**
37
+ * Sets a list of items in the Cache.
38
+ *
39
+ * @param entries - a list of cache entries
40
+ * @param ttl - the time in milliseconds until the entries expire
41
+ * @returns an empty Promise that resolves when all entries have been set
42
+ */
43
+ setMany: (entries: CacheEntry<T>[], ttl: number) => Promise<void>;
44
+ /**
45
+ * Deletes the specified item from the Cache
46
+ *
47
+ * @param key - the key of the entry to be deleted
48
+ * @returns an empty Promise that resolves when the entry has been deleted
49
+ */
50
+ delete: (key: string) => Promise<void>;
51
+ }
52
+ export declare const calculateCacheKey: <T extends import("../transports").TransportGenerics>({ adapterEndpoint, adapterConfig, }: {
53
+ adapterEndpoint: AdapterEndpoint<T>;
54
+ adapterConfig: AdapterConfig<T["CustomSettings"]>;
55
+ }, data: unknown) => string;
56
+ export declare const calculateFeedId: <T extends import("../transports").TransportGenerics>({ adapterEndpoint, adapterConfig, }: {
57
+ adapterEndpoint: AdapterEndpoint<T>;
58
+ adapterConfig: AdapterConfig<T["CustomSettings"]>;
59
+ }, data: unknown) => string;
60
+ /**
61
+ * Calculates a unique key from the provided data.
62
+ *
63
+ * @param data - the request data/body, i.e. the adapter input params
64
+ * @param paramNames - the keys from adapter endpoint input parameters
65
+ * @returns the calculated unique key
66
+ *
67
+ * @example
68
+ * ```
69
+ * calculateKey({ base: 'ETH', quote: 'BTC' }, ['base','quote'])
70
+ * // equals `|base:eth|quote:btc`
71
+ * ```
72
+ */
73
+ export declare const calculateKey: <CustomSettings extends SettingsMap>(data: unknown, paramNames: string[], adapterConfig: AdapterConfig<CustomSettings>) => string;
74
+ export declare const calculateStaleness: (expirationTimestamp: number | undefined, ttl: number) => number;
75
+ /**
76
+ * Polls the provided Cache for an AdapterResponse set in the provided key. If the maximum
77
+ * amount of retries is exceeded, it returns undefined instead.
78
+ *
79
+ * @param cache - a Cache instance
80
+ * @param key - the key generated from an AdapterRequest that corresponds to the desired AdapterResponse
81
+ * @param retry - current retry, only for internal use
82
+ * @returns the AdapterResponse if found, else undefined
83
+ */
84
+ export declare const pollResponseFromCache: (cache: Cache<AdapterResponse>, key: string, options: {
85
+ maxRetries: number;
86
+ sleep: number;
87
+ }, retry?: number) => Promise<AdapterResponse | undefined>;
package/cache/index.js ADDED
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.pollResponseFromCache = exports.calculateStaleness = exports.calculateKey = exports.calculateFeedId = exports.calculateCacheKey = void 0;
18
+ const util_1 = require("../util");
19
+ __exportStar(require("./factory"), exports);
20
+ __exportStar(require("./local"), exports);
21
+ __exportStar(require("./redis"), exports);
22
+ const logger = (0, util_1.makeLogger)('Cache');
23
+ // Uses calculateKey to generate a unique key from the endpoint name, data, and input parameters
24
+ const calculateCacheKey = ({ adapterEndpoint, adapterConfig, }, data) => {
25
+ const paramNames = Object.keys(adapterEndpoint.inputParameters);
26
+ if (paramNames.length === 0) {
27
+ logger.trace(`Using default cache key ${adapterConfig.DEFAULT_CACHE_KEY}`);
28
+ return adapterConfig.DEFAULT_CACHE_KEY;
29
+ }
30
+ const cacheKey = `${adapterEndpoint.name}-${(0, exports.calculateKey)(data, paramNames, adapterConfig)}`;
31
+ logger.trace(`Generated cache key for request: "${cacheKey}"`);
32
+ return cacheKey;
33
+ };
34
+ exports.calculateCacheKey = calculateCacheKey;
35
+ const calculateFeedId = ({ adapterEndpoint, adapterConfig, }, data) => {
36
+ const paramNames = Object.keys(adapterEndpoint.inputParameters);
37
+ if (paramNames.length === 0) {
38
+ logger.trace(`Cannot generate Feed ID without input parameters`);
39
+ return 'N/A';
40
+ }
41
+ return (0, exports.calculateKey)(data, paramNames, adapterConfig);
42
+ };
43
+ exports.calculateFeedId = calculateFeedId;
44
+ /**
45
+ * Calculates a unique key from the provided data.
46
+ *
47
+ * @param data - the request data/body, i.e. the adapter input params
48
+ * @param paramNames - the keys from adapter endpoint input parameters
49
+ * @returns the calculated unique key
50
+ *
51
+ * @example
52
+ * ```
53
+ * calculateKey({ base: 'ETH', quote: 'BTC' }, ['base','quote'])
54
+ * // equals `|base:eth|quote:btc`
55
+ * ```
56
+ */
57
+ const calculateKey = (data, paramNames, adapterConfig) => {
58
+ if (data && typeof data !== 'object') {
59
+ throw new Error('Data to calculate cache key should be an object');
60
+ }
61
+ const params = data;
62
+ let cacheKey = '';
63
+ for (const paramName of paramNames) {
64
+ const param = params[paramName];
65
+ if (param === undefined) {
66
+ continue;
67
+ }
68
+ cacheKey += `|${paramName}:`;
69
+ switch (typeof param) {
70
+ case 'string':
71
+ cacheKey += param.toLowerCase();
72
+ break;
73
+ case 'number':
74
+ case 'boolean':
75
+ cacheKey += param.toString();
76
+ break;
77
+ case 'object':
78
+ // Force cache keys to only use performant properties of the input params.
79
+ // If the object were to be used, we'd have to sort its properties.
80
+ logger.debug(`Property "${paramName}" in request parameters is of type object, and won't be used in the cacheKey`);
81
+ }
82
+ }
83
+ if (cacheKey.length > adapterConfig.MAX_COMMON_KEY_SIZE) {
84
+ logger.warn(`Generated cache key for adapter request is bigger than the MAX_COMMON_KEY_SIZE and will be truncated`);
85
+ cacheKey = cacheKey.slice(0, adapterConfig.MAX_COMMON_KEY_SIZE);
86
+ }
87
+ return cacheKey;
88
+ };
89
+ exports.calculateKey = calculateKey;
90
+ // Calculate the amount of time a non-expired entry has been in the cache
91
+ const calculateStaleness = (expirationTimestamp, ttl) => {
92
+ if (expirationTimestamp) {
93
+ const createTimestamp = expirationTimestamp - ttl;
94
+ return (Date.now() - createTimestamp) / 1000;
95
+ }
96
+ else {
97
+ // If expirationTimestamp is not available, staleness cannot be calculated
98
+ // Defaults to ttl for metrics purposes
99
+ return ttl;
100
+ }
101
+ };
102
+ exports.calculateStaleness = calculateStaleness;
103
+ /**
104
+ * Polls the provided Cache for an AdapterResponse set in the provided key. If the maximum
105
+ * amount of retries is exceeded, it returns undefined instead.
106
+ *
107
+ * @param cache - a Cache instance
108
+ * @param key - the key generated from an AdapterRequest that corresponds to the desired AdapterResponse
109
+ * @param retry - current retry, only for internal use
110
+ * @returns the AdapterResponse if found, else undefined
111
+ */
112
+ const pollResponseFromCache = async (cache, key, options, retry = 0) => {
113
+ if (retry > options.maxRetries) {
114
+ // Ideally this shouldn't happen often (p99 of reqs should be found in the cache)
115
+ logger.info('Exceeded max cache polling retries');
116
+ return undefined;
117
+ }
118
+ logger.trace('Getting response from cache...');
119
+ const response = await cache.get(key);
120
+ if (response) {
121
+ logger.trace('Got response from cache');
122
+ return response;
123
+ }
124
+ if (options.maxRetries === 0) {
125
+ logger.debug(`Response not found, retries disabled`);
126
+ return undefined;
127
+ }
128
+ logger.debug(`Response not found, sleeping ${options.sleep} milliseconds...`);
129
+ await (0, util_1.sleep)(options.sleep);
130
+ return (0, exports.pollResponseFromCache)(cache, key, options, retry + 1);
131
+ };
132
+ exports.pollResponseFromCache = pollResponseFromCache;
133
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cache/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { Cache, CacheEntry } from './index';
2
+ /**
3
+ * Type for a value stored in a LocalCache entry.
4
+ *
5
+ * @typeParam T - the type for the entry's value
6
+ */
7
+ export interface LocalCacheEntry<T> {
8
+ expirationTimestamp: number;
9
+ value: T;
10
+ }
11
+ /**
12
+ * Local implementation of a Cache. It uses a simple js Object, storing entries with both
13
+ * a value and an expiration timestamp. Expired entries are deleted on reads (i.e. no background gc/upkeep).
14
+ *
15
+ * @typeParam T - the type for the entries' values
16
+ */
17
+ export declare class LocalCache<T = unknown> implements Cache<T> {
18
+ store: Record<string, LocalCacheEntry<T>>;
19
+ get(key: string): Promise<T | undefined>;
20
+ delete(key: string): Promise<void>;
21
+ set(key: string, value: T, ttl: number): Promise<void>;
22
+ setMany(entries: CacheEntry<T>[], ttl: number): Promise<void>;
23
+ }