@chainlink/external-adapter-framework 0.11.1 → 0.12.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.
- package/README.md +1 -1
- package/package.json +2 -7
- package/transports/websocket.d.ts +6 -5
- package/transports/websocket.js +21 -10
- package/transports/websocket.js.map +1 -1
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chainlink/external-adapter-framework",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"ajv": "8.11.0",
|
|
8
8
|
"axios": "0.27.2",
|
|
9
9
|
"eventsource": "2.0.2",
|
|
10
|
-
"fastify": "4.
|
|
10
|
+
"fastify": "4.9.2",
|
|
11
11
|
"ioredis": "5.2.3",
|
|
12
12
|
"pino": "8.6.1",
|
|
13
13
|
"pino-pretty": "9.1.0",
|
|
@@ -30,10 +30,8 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@sinonjs/fake-timers": "9.1.2",
|
|
32
32
|
"@types/eventsource": "1.1.9",
|
|
33
|
-
"@types/jest": "29.1.1",
|
|
34
33
|
"@types/node": "18.8.2",
|
|
35
34
|
"@types/sinonjs__fake-timers": "8.1.2",
|
|
36
|
-
"@types/supertest": "2.0.12",
|
|
37
35
|
"@types/ws": "8.5.3",
|
|
38
36
|
"@typescript-eslint/eslint-plugin": "5.39.0",
|
|
39
37
|
"@typescript-eslint/parser": "5.39.0",
|
|
@@ -42,14 +40,11 @@
|
|
|
42
40
|
"eslint": "8.24.0",
|
|
43
41
|
"eslint-config-prettier": "8.5.0",
|
|
44
42
|
"eslint-plugin-tsdoc": "0.2.17",
|
|
45
|
-
"jest": "29.1.2",
|
|
46
43
|
"mock-socket": "9.1.5",
|
|
47
44
|
"mocksse": "1.0.4",
|
|
48
45
|
"nock": "13.2.9",
|
|
49
46
|
"prettier": "2.7.1",
|
|
50
|
-
"supertest": "6.3.0",
|
|
51
47
|
"ts-node": "10.9.1",
|
|
52
|
-
"ts-jest": "29.0.3",
|
|
53
48
|
"ts-node-dev": "2.0.0",
|
|
54
49
|
"typedoc": "0.23.15",
|
|
55
50
|
"typescript": "4.8.4"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import WebSocket, { ClientOptions, RawData } from 'ws';
|
|
2
|
-
import {
|
|
2
|
+
import { AdapterDependencies, EndpointContext } from '../adapter';
|
|
3
3
|
import { Cache } from '../cache';
|
|
4
4
|
import { AdapterConfig } from '../config';
|
|
5
5
|
import { BackgroundExecuteRateLimiter } from '../rate-limiting';
|
|
@@ -18,7 +18,7 @@ export declare class WebSocketClassProvider {
|
|
|
18
18
|
*/
|
|
19
19
|
export interface WebSocketTransportConfig<T extends WebsocketTransportGenerics> {
|
|
20
20
|
/** Endpoint to which to open the WS connection*/
|
|
21
|
-
url: (context: EndpointContext<T
|
|
21
|
+
url: (context: EndpointContext<T>, desiredSubs: T['Request']['Params'][]) => Promise<string> | string;
|
|
22
22
|
/** Optional parameters used when establishing the WebSocket connection */
|
|
23
23
|
options?: (context: EndpointContext<T>) => Promise<ClientOptions> | ClientOptions;
|
|
24
24
|
/** Map of handlers for different WS lifecycle events */
|
|
@@ -41,21 +41,21 @@ export interface WebSocketTransportConfig<T extends WebsocketTransportGenerics>
|
|
|
41
41
|
message: (message: T['Provider']['WsMessage'], context: EndpointContext<T>) => ProviderResult<T>[] | undefined;
|
|
42
42
|
};
|
|
43
43
|
/** Map of "builders", functions that will be used to prepare specific WS messages */
|
|
44
|
-
builders
|
|
44
|
+
builders?: {
|
|
45
45
|
/**
|
|
46
46
|
* Builds a WS message that will be sent to subscribe to a specific feed
|
|
47
47
|
*
|
|
48
48
|
* @param params - the body of the adapter request
|
|
49
49
|
* @returns the WS message (can be any type as long as the [[WebSocket]] doesn't complain)
|
|
50
50
|
*/
|
|
51
|
-
subscribeMessage
|
|
51
|
+
subscribeMessage?: (params: T['Request']['Params']) => unknown;
|
|
52
52
|
/**
|
|
53
53
|
* Builds a WS message that will be sent to unsubscribe to a specific feed
|
|
54
54
|
*
|
|
55
55
|
* @param params - the body of the adapter request
|
|
56
56
|
* @returns the WS message (can be any type as long as the [[WebSocket]] doesn't complain)
|
|
57
57
|
*/
|
|
58
|
-
unsubscribeMessage
|
|
58
|
+
unsubscribeMessage?: (params: T['Request']['Params']) => unknown;
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
@@ -86,6 +86,7 @@ export declare class WebSocketTransport<T extends WebsocketTransportGenerics> im
|
|
|
86
86
|
subscriptionSet: SubscriptionSet<T['Request']['Params']>;
|
|
87
87
|
localSubscriptions: T['Request']['Params'][];
|
|
88
88
|
wsConnection: WebSocket;
|
|
89
|
+
currentUrl: string;
|
|
89
90
|
constructor(config: WebSocketTransportConfig<T>);
|
|
90
91
|
initialize(dependencies: AdapterDependencies, config: AdapterConfig<T['CustomSettings']>, endpointName: string): Promise<void>;
|
|
91
92
|
registerRequest(req: AdapterRequest<T['Request']>, config: AdapterConfig<T['CustomSettings']>): Promise<void>;
|
package/transports/websocket.js
CHANGED
|
@@ -55,6 +55,7 @@ class WebSocketTransport {
|
|
|
55
55
|
// The double sets serve to create a simple polling mechanism instead of needing a subscription
|
|
56
56
|
// This one would not; this is always local state
|
|
57
57
|
this.localSubscriptions = [];
|
|
58
|
+
this.currentUrl = '';
|
|
58
59
|
}
|
|
59
60
|
async initialize(dependencies, config, endpointName) {
|
|
60
61
|
this.cache = dependencies.cache;
|
|
@@ -134,10 +135,10 @@ class WebSocketTransport {
|
|
|
134
135
|
const unsubscribes = this.localSubscriptions.filter((s) => !desiredSubs.map((ds) => JSON.stringify(ds)).includes(JSON.stringify(s)));
|
|
135
136
|
logger.debug(`${subscribes.length} new subscriptions; ${unsubscribes.length} to unsubscribe`);
|
|
136
137
|
if (subscribes.length) {
|
|
137
|
-
logger.trace(`Will subscribe to: ${subscribes}`);
|
|
138
|
+
logger.trace(`Will subscribe to: ${JSON.stringify(subscribes)}`);
|
|
138
139
|
}
|
|
139
140
|
if (unsubscribes.length) {
|
|
140
|
-
logger.trace(`Will unsubscribe to: ${unsubscribes}`);
|
|
141
|
+
logger.trace(`Will unsubscribe to: ${JSON.stringify(unsubscribes)}`);
|
|
141
142
|
}
|
|
142
143
|
// New subs && no connection -> connect -> add subs
|
|
143
144
|
// No new subs && no connection -> skip
|
|
@@ -147,17 +148,27 @@ class WebSocketTransport {
|
|
|
147
148
|
logger.debug('No entries in subscription set and no established connection, skipping');
|
|
148
149
|
return this.rateLimiter.msUntilNextExecution(context.endpointName);
|
|
149
150
|
}
|
|
150
|
-
|
|
151
|
+
const urlFromConfig = await this.config.url(context, desiredSubs);
|
|
152
|
+
const urlChanged = this.currentUrl !== urlFromConfig;
|
|
153
|
+
let connectionClosed = this.connectionClosed();
|
|
154
|
+
// Check if we should close the current connection
|
|
155
|
+
if (!connectionClosed && urlChanged) {
|
|
156
|
+
logger.info(`Websocket url has changed from ${this.currentUrl} to ${urlFromConfig}, closing connection...`);
|
|
157
|
+
this.wsConnection.close();
|
|
158
|
+
connectionClosed = true;
|
|
159
|
+
}
|
|
160
|
+
// Check if we need to open a new connection
|
|
161
|
+
if (connectionClosed && desiredSubs.length) {
|
|
151
162
|
logger.debug('No established connection and new subscriptions available, connecting to WS');
|
|
152
|
-
const url = await this.config.url(context);
|
|
153
|
-
if (!url) {
|
|
154
|
-
throw new Error('Got no URL from url builder or WS_API_ENDPOINT');
|
|
155
|
-
}
|
|
156
163
|
const options = this.config.options && (await this.config.options(context));
|
|
157
|
-
|
|
164
|
+
this.currentUrl = urlFromConfig;
|
|
165
|
+
await this.establishWsConnection(context, urlFromConfig, options);
|
|
166
|
+
}
|
|
167
|
+
if (this.config.builders) {
|
|
168
|
+
logger.debug('Sending subs/unsubs if there are any');
|
|
169
|
+
const { subscribeMessage, unsubscribeMessage } = this.config.builders;
|
|
170
|
+
await this.sendMessages(context, subscribeMessage ? subscribes.map(subscribeMessage) : subscribes, unsubscribeMessage ? unsubscribes.map(unsubscribeMessage) : unsubscribes);
|
|
158
171
|
}
|
|
159
|
-
logger.debug('Sending subs/unsubs if there are any');
|
|
160
|
-
await this.sendMessages(context, subscribes.map(this.config.builders.subscribeMessage), unsubscribes.map(this.config.builders.unsubscribeMessage));
|
|
161
172
|
// Record WS message and subscription metrics
|
|
162
173
|
transportMetrics.recordWsMessageMetrics(context, subscribes, unsubscribes);
|
|
163
174
|
logger.debug('Setting local state to cache value');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../../src/transports/websocket.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAAsD;AAW7C,oBAXF,YAAS,CAWE;AANlB,kCAAqD;AAErD,yBAA+E;AAC/E,4DAA6C;AAK7C,MAAM,MAAM,GAAG,IAAA,iBAAU,EAAC,oBAAoB,CAAC,CAAA;AAQ/C,MAAa,sBAAsB;IAGjC,MAAM,CAAC,GAAG,CAAC,IAAoB;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAED,MAAM,CAAC,GAAG;QACR,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;;AATH,wDAUC;AATQ,2BAAI,GAAmB,YAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../../src/transports/websocket.ts"],"names":[],"mappings":"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"}
|