@acala-network/chopsticks 0.9.9 → 0.9.11-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.
@@ -104,7 +104,8 @@ const setupContext = async (argv, overrideParent = false)=>{
104
104
  runtimeLogLevel: argv['runtime-log-level'],
105
105
  registeredTypes: argv['registered-types'],
106
106
  offchainWorker: argv['offchain-worker'],
107
- maxMemoryBlockCount: argv['max-memory-block-count']
107
+ maxMemoryBlockCount: argv['max-memory-block-count'],
108
+ processQueuedMessages: argv['process-queued-messages']
108
109
  });
109
110
  // load block from db
110
111
  if (chain.db) {
@@ -82,6 +82,7 @@ export declare const dryRunSchema: z.ZodObject<{
82
82
  'runtime-log-level': z.ZodOptional<z.ZodNumber>;
83
83
  'offchain-worker': z.ZodOptional<z.ZodBoolean>;
84
84
  resume: z.ZodOptional<z.ZodUnion<[z.ZodIntersection<z.ZodString, z.ZodType<`0x${string}`, z.ZodTypeDef, `0x${string}`>>, z.ZodNumber, z.ZodBoolean]>>;
85
+ 'process-queued-messages': z.ZodOptional<z.ZodBoolean>;
85
86
  }, "strip", z.ZodTypeAny, {
86
87
  port: number;
87
88
  'build-block-mode': import("@acala-network/chopsticks-core").BuildBlockMode;
@@ -119,6 +120,7 @@ export declare const dryRunSchema: z.ZodObject<{
119
120
  'runtime-log-level'?: number | undefined;
120
121
  'offchain-worker'?: boolean | undefined;
121
122
  resume?: number | boolean | `0x${string}` | undefined;
123
+ 'process-queued-messages'?: boolean | undefined;
122
124
  }, {
123
125
  extrinsic?: string | undefined;
124
126
  address?: string | undefined;
@@ -156,6 +158,7 @@ export declare const dryRunSchema: z.ZodObject<{
156
158
  'runtime-log-level'?: number | undefined;
157
159
  'offchain-worker'?: boolean | undefined;
158
160
  resume?: number | boolean | `0x${string}` | undefined;
161
+ 'process-queued-messages'?: boolean | undefined;
159
162
  }>;
160
163
  export type DryRunSchemaType = z.infer<typeof dryRunSchema>;
161
164
  export * from './cli.js';
@@ -78,6 +78,7 @@ export declare const configSchema: z.ZodObject<{
78
78
  'runtime-log-level': z.ZodOptional<z.ZodNumber>;
79
79
  'offchain-worker': z.ZodOptional<z.ZodBoolean>;
80
80
  resume: z.ZodOptional<z.ZodUnion<[z.ZodIntersection<z.ZodString, z.ZodType<`0x${string}`, z.ZodTypeDef, `0x${string}`>>, z.ZodNumber, z.ZodBoolean]>>;
81
+ 'process-queued-messages': z.ZodOptional<z.ZodBoolean>;
81
82
  }, "strip", ZodTypeAny, {
82
83
  port: number;
83
84
  'build-block-mode': BuildBlockMode;
@@ -108,6 +109,7 @@ export declare const configSchema: z.ZodObject<{
108
109
  'runtime-log-level'?: number | undefined;
109
110
  'offchain-worker'?: boolean | undefined;
110
111
  resume?: number | boolean | `0x${string}` | undefined;
112
+ 'process-queued-messages'?: boolean | undefined;
111
113
  }, {
112
114
  port?: number | undefined;
113
115
  endpoint?: string | string[] | undefined;
@@ -138,6 +140,7 @@ export declare const configSchema: z.ZodObject<{
138
140
  'runtime-log-level'?: number | undefined;
139
141
  'offchain-worker'?: boolean | undefined;
140
142
  resume?: number | boolean | `0x${string}` | undefined;
143
+ 'process-queued-messages'?: boolean | undefined;
141
144
  }>;
142
145
  export type Config = z.infer<typeof configSchema>;
143
146
  export declare const getYargsOptions: (zodShape: ZodRawShape) => {
@@ -91,6 +91,9 @@ const configSchema = _zod.z.object({
91
91
  _zod.z.boolean()
92
92
  ], {
93
93
  description: 'Resume from the specified block hash or block number in db. If true, it will resume from the latest block in db. Note this will override the block option'
94
+ }).optional(),
95
+ 'process-queued-messages': _zod.z.boolean({
96
+ description: 'Produce extra block when queued messages are detected. Default to true. Set to false to disable it.'
94
97
  }).optional()
95
98
  });
96
99
  const getZodType = (option)=>{
@@ -3,7 +3,7 @@ export type Handler = (data: {
3
3
  method: string;
4
4
  params: string[];
5
5
  }, subscriptionManager: SubscriptionManager) => Promise<any>;
6
- export declare const createServer: (handler: Handler, port?: number) => Promise<{
6
+ export declare const createServer: (handler: Handler, port: number) => Promise<{
7
7
  port: number;
8
8
  close: () => Promise<void>;
9
9
  }>;
@@ -11,8 +11,17 @@ Object.defineProperty(exports, "createServer", {
11
11
  const _ws = require("ws");
12
12
  const _chopstickscore = require("@acala-network/chopsticks-core");
13
13
  const _zod = require("zod");
14
+ const _nodehttp = /*#__PURE__*/ _interop_require_default(require("node:http"));
14
15
  const _logger = require("./logger.js");
15
- const logger = _logger.defaultLogger.child({
16
+ function _interop_require_default(obj) {
17
+ return obj && obj.__esModule ? obj : {
18
+ default: obj
19
+ };
20
+ }
21
+ const httpLogger = _logger.defaultLogger.child({
22
+ name: 'http'
23
+ });
24
+ const wsLogger = _logger.defaultLogger.child({
16
25
  name: 'ws'
17
26
  });
18
27
  const singleRequest = _zod.z.object({
@@ -33,34 +42,103 @@ const parseRequest = (request)=>{
33
42
  return undefined;
34
43
  }
35
44
  };
36
- const createWS = async (port)=>{
37
- const wss = new _ws.WebSocketServer({
38
- port,
39
- maxPayload: 1024 * 1024 * 100
40
- });
41
- const promise = new Promise((resolve)=>{
42
- wss.on('listening', ()=>{
43
- resolve([
44
- wss,
45
- wss.address().port
46
- ]);
47
- });
48
- wss.on('error', (_)=>{
49
- resolve([]);
45
+ const readBody = (request)=>new Promise((resolve)=>{
46
+ const bodyParts = [];
47
+ request.on('data', (chunk)=>{
48
+ bodyParts.push(chunk);
49
+ }).on('end', ()=>{
50
+ resolve(Buffer.concat(bodyParts).toString());
50
51
  });
51
52
  });
52
- return promise;
53
+ const respond = (res, data)=>{
54
+ res.writeHead(200, {
55
+ 'Access-Control-Allow-Origin': '*',
56
+ 'Access-Control-Allow-Methods': 'POST',
57
+ 'Access-Control-Allow-Headers': '*',
58
+ 'Content-Type': 'application/json'
59
+ });
60
+ if (data) {
61
+ res.write(data);
62
+ }
63
+ res.end();
53
64
  };
54
65
  const createServer = async (handler, port)=>{
55
66
  let wss;
56
67
  let listenPort;
68
+ const emptySubscriptionManager = {
69
+ subscribe: ()=>{
70
+ throw new Error('Subscription is not supported');
71
+ },
72
+ unsubscribe: ()=>{
73
+ throw new Error('Subscription is not supported');
74
+ }
75
+ };
76
+ const server = _nodehttp.default.createServer(async (req, res)=>{
77
+ if (req.method === 'OPTIONS') {
78
+ return respond(res);
79
+ }
80
+ try {
81
+ if (req.method !== 'POST') {
82
+ throw new Error('Only POST method is supported');
83
+ }
84
+ const body = await readBody(req);
85
+ const parsed = await requestSchema.safeParseAsync(parseRequest(body));
86
+ if (!parsed.success) {
87
+ httpLogger.error('Invalid request: %s', body);
88
+ throw new Error('Invalid request: ' + body);
89
+ }
90
+ httpLogger.trace({
91
+ req: parsed.data
92
+ }, 'Received request');
93
+ let response;
94
+ if (Array.isArray(parsed.data)) {
95
+ response = await Promise.all(parsed.data.map((req)=>{
96
+ const result = handler(req, emptySubscriptionManager);
97
+ return {
98
+ id: req.id,
99
+ jsonrpc: '2.0',
100
+ result
101
+ };
102
+ }));
103
+ } else {
104
+ const result = await handler(parsed.data, emptySubscriptionManager);
105
+ response = {
106
+ id: parsed.data.id,
107
+ jsonrpc: '2.0',
108
+ result
109
+ };
110
+ }
111
+ respond(res, JSON.stringify(response));
112
+ } catch (err) {
113
+ respond(res, JSON.stringify({
114
+ jsonrpc: '2.0',
115
+ id: 1,
116
+ error: {
117
+ message: err.message
118
+ }
119
+ }));
120
+ }
121
+ });
57
122
  for(let i = 0; i < 10; i++){
58
- const preferPort = (port ?? 0) > 0 ? (port ?? 0) + i : 0;
59
- logger.debug('Try starting on port %d', preferPort);
60
- const [maybeWss, maybeListenPort] = await createWS(preferPort);
61
- if (maybeWss && maybeListenPort) {
62
- wss = maybeWss;
63
- listenPort = maybeListenPort;
123
+ const preferPort = port ? port + i : undefined;
124
+ wsLogger.debug('Try starting on port %d', preferPort);
125
+ const success = await new Promise((resolve)=>{
126
+ server.once('error', (e)=>{
127
+ if (e.code === 'EADDRINUSE') {
128
+ server.close();
129
+ resolve(false);
130
+ }
131
+ });
132
+ server.listen(preferPort, ()=>{
133
+ wss = new _ws.WebSocketServer({
134
+ server,
135
+ maxPayload: 1024 * 1024 * 100
136
+ });
137
+ listenPort = server.address().port;
138
+ resolve(true);
139
+ });
140
+ });
141
+ if (success) {
64
142
  break;
65
143
  }
66
144
  }
@@ -68,7 +146,7 @@ const createServer = async (handler, port)=>{
68
146
  throw new Error(`Failed to create WebsocketServer at port ${port}`);
69
147
  }
70
148
  wss.on('connection', (ws)=>{
71
- logger.debug('New connection');
149
+ wsLogger.debug('New connection');
72
150
  const send = (data)=>{
73
151
  if (ws.readyState === _ws.WebSocket.OPEN) {
74
152
  ws.send(JSON.stringify(data));
@@ -80,7 +158,7 @@ const createServer = async (handler, port)=>{
80
158
  subscriptions[subid] = onCancel;
81
159
  return (data)=>{
82
160
  if (subscriptions[subid]) {
83
- logger.trace({
161
+ wsLogger.trace({
84
162
  method,
85
163
  subid,
86
164
  data: (0, _logger.truncate)(data)
@@ -104,13 +182,13 @@ const createServer = async (handler, port)=>{
104
182
  }
105
183
  };
106
184
  const processRequest = async (req)=>{
107
- logger.trace({
185
+ wsLogger.trace({
108
186
  id: req.id,
109
187
  method: req.method
110
188
  }, 'Received message');
111
189
  try {
112
190
  const resp = await handler(req, subscriptionManager);
113
- logger.trace({
191
+ wsLogger.trace({
114
192
  id: req.id,
115
193
  method: req.method,
116
194
  result: (0, _logger.truncate)(resp)
@@ -121,7 +199,7 @@ const createServer = async (handler, port)=>{
121
199
  result: resp ?? null
122
200
  };
123
201
  } catch (e) {
124
- logger.info('Error handling request: %o', e.stack);
202
+ wsLogger.info('Error handling request: %o', e.stack);
125
203
  return {
126
204
  id: req.id,
127
205
  jsonrpc: '2.0',
@@ -133,14 +211,14 @@ const createServer = async (handler, port)=>{
133
211
  }
134
212
  };
135
213
  ws.on('close', ()=>{
136
- logger.debug('Connection closed');
214
+ wsLogger.debug('Connection closed');
137
215
  for (const [subid, onCancel] of Object.entries(subscriptions)){
138
216
  onCancel(subid);
139
217
  }
140
218
  ws.removeAllListeners();
141
219
  });
142
220
  ws.on('error', ()=>{
143
- logger.debug('Connection error');
221
+ wsLogger.debug('Connection error');
144
222
  for (const [subid, onCancel] of Object.entries(subscriptions)){
145
223
  onCancel(subid);
146
224
  }
@@ -149,7 +227,7 @@ const createServer = async (handler, port)=>{
149
227
  ws.on('message', async (message)=>{
150
228
  const parsed = await requestSchema.safeParseAsync(parseRequest(message.toString()));
151
229
  if (!parsed.success) {
152
- logger.info('Invalid request: %s', message);
230
+ wsLogger.error('Invalid request: %s', message);
153
231
  send({
154
232
  id: null,
155
233
  jsonrpc: '2.0',
@@ -162,13 +240,13 @@ const createServer = async (handler, port)=>{
162
240
  }
163
241
  const { data: req } = parsed;
164
242
  if (Array.isArray(req)) {
165
- logger.trace({
243
+ wsLogger.trace({
166
244
  req
167
245
  }, 'Received batch request');
168
246
  const resp = await Promise.all(req.map(processRequest));
169
247
  send(resp);
170
248
  } else {
171
- logger.trace({
249
+ wsLogger.trace({
172
250
  req
173
251
  }, 'Received single request');
174
252
  const resp = await processRequest(req);
@@ -178,15 +256,10 @@ const createServer = async (handler, port)=>{
178
256
  });
179
257
  return {
180
258
  port: listenPort,
181
- close: ()=>new Promise((resolve, reject)=>{
182
- wss?.clients.forEach((socket)=>socket.close());
183
- wss?.close((err)=>{
184
- if (err) {
185
- reject(err);
186
- } else {
187
- resolve();
188
- }
189
- });
190
- })
259
+ close: async ()=>{
260
+ server.close();
261
+ server.closeAllConnections();
262
+ server.unref();
263
+ }
191
264
  };
192
265
  };
@@ -40,7 +40,8 @@ export const setupContext = async (argv, overrideParent = false)=>{
40
40
  runtimeLogLevel: argv['runtime-log-level'],
41
41
  registeredTypes: argv['registered-types'],
42
42
  offchainWorker: argv['offchain-worker'],
43
- maxMemoryBlockCount: argv['max-memory-block-count']
43
+ maxMemoryBlockCount: argv['max-memory-block-count'],
44
+ processQueuedMessages: argv['process-queued-messages']
44
45
  });
45
46
  // load block from db
46
47
  if (chain.db) {
@@ -82,6 +82,7 @@ export declare const dryRunSchema: z.ZodObject<{
82
82
  'runtime-log-level': z.ZodOptional<z.ZodNumber>;
83
83
  'offchain-worker': z.ZodOptional<z.ZodBoolean>;
84
84
  resume: z.ZodOptional<z.ZodUnion<[z.ZodIntersection<z.ZodString, z.ZodType<`0x${string}`, z.ZodTypeDef, `0x${string}`>>, z.ZodNumber, z.ZodBoolean]>>;
85
+ 'process-queued-messages': z.ZodOptional<z.ZodBoolean>;
85
86
  }, "strip", z.ZodTypeAny, {
86
87
  port: number;
87
88
  'build-block-mode': import("@acala-network/chopsticks-core").BuildBlockMode;
@@ -119,6 +120,7 @@ export declare const dryRunSchema: z.ZodObject<{
119
120
  'runtime-log-level'?: number | undefined;
120
121
  'offchain-worker'?: boolean | undefined;
121
122
  resume?: number | boolean | `0x${string}` | undefined;
123
+ 'process-queued-messages'?: boolean | undefined;
122
124
  }, {
123
125
  extrinsic?: string | undefined;
124
126
  address?: string | undefined;
@@ -156,6 +158,7 @@ export declare const dryRunSchema: z.ZodObject<{
156
158
  'runtime-log-level'?: number | undefined;
157
159
  'offchain-worker'?: boolean | undefined;
158
160
  resume?: number | boolean | `0x${string}` | undefined;
161
+ 'process-queued-messages'?: boolean | undefined;
159
162
  }>;
160
163
  export type DryRunSchemaType = z.infer<typeof dryRunSchema>;
161
164
  export * from './cli.js';
@@ -78,6 +78,7 @@ export declare const configSchema: z.ZodObject<{
78
78
  'runtime-log-level': z.ZodOptional<z.ZodNumber>;
79
79
  'offchain-worker': z.ZodOptional<z.ZodBoolean>;
80
80
  resume: z.ZodOptional<z.ZodUnion<[z.ZodIntersection<z.ZodString, z.ZodType<`0x${string}`, z.ZodTypeDef, `0x${string}`>>, z.ZodNumber, z.ZodBoolean]>>;
81
+ 'process-queued-messages': z.ZodOptional<z.ZodBoolean>;
81
82
  }, "strip", ZodTypeAny, {
82
83
  port: number;
83
84
  'build-block-mode': BuildBlockMode;
@@ -108,6 +109,7 @@ export declare const configSchema: z.ZodObject<{
108
109
  'runtime-log-level'?: number | undefined;
109
110
  'offchain-worker'?: boolean | undefined;
110
111
  resume?: number | boolean | `0x${string}` | undefined;
112
+ 'process-queued-messages'?: boolean | undefined;
111
113
  }, {
112
114
  port?: number | undefined;
113
115
  endpoint?: string | string[] | undefined;
@@ -138,6 +140,7 @@ export declare const configSchema: z.ZodObject<{
138
140
  'runtime-log-level'?: number | undefined;
139
141
  'offchain-worker'?: boolean | undefined;
140
142
  resume?: number | boolean | `0x${string}` | undefined;
143
+ 'process-queued-messages'?: boolean | undefined;
141
144
  }>;
142
145
  export type Config = z.infer<typeof configSchema>;
143
146
  export declare const getYargsOptions: (zodShape: ZodRawShape) => {
@@ -59,6 +59,9 @@ export const configSchema = z.object({
59
59
  z.boolean()
60
60
  ], {
61
61
  description: 'Resume from the specified block hash or block number in db. If true, it will resume from the latest block in db. Note this will override the block option'
62
+ }).optional(),
63
+ 'process-queued-messages': z.boolean({
64
+ description: 'Produce extra block when queued messages are detected. Default to true. Set to false to disable it.'
62
65
  }).optional()
63
66
  });
64
67
  const getZodType = (option)=>{
@@ -3,7 +3,7 @@ export type Handler = (data: {
3
3
  method: string;
4
4
  params: string[];
5
5
  }, subscriptionManager: SubscriptionManager) => Promise<any>;
6
- export declare const createServer: (handler: Handler, port?: number) => Promise<{
6
+ export declare const createServer: (handler: Handler, port: number) => Promise<{
7
7
  port: number;
8
8
  close: () => Promise<void>;
9
9
  }>;
@@ -1,8 +1,12 @@
1
1
  import { WebSocket, WebSocketServer } from 'ws';
2
2
  import { ResponseError } from '@acala-network/chopsticks-core';
3
3
  import { z } from 'zod';
4
+ import http from 'node:http';
4
5
  import { defaultLogger, truncate } from './logger.js';
5
- const logger = defaultLogger.child({
6
+ const httpLogger = defaultLogger.child({
7
+ name: 'http'
8
+ });
9
+ const wsLogger = defaultLogger.child({
6
10
  name: 'ws'
7
11
  });
8
12
  const singleRequest = z.object({
@@ -23,34 +27,103 @@ const parseRequest = (request)=>{
23
27
  return undefined;
24
28
  }
25
29
  };
26
- const createWS = async (port)=>{
27
- const wss = new WebSocketServer({
28
- port,
29
- maxPayload: 1024 * 1024 * 100
30
- });
31
- const promise = new Promise((resolve)=>{
32
- wss.on('listening', ()=>{
33
- resolve([
34
- wss,
35
- wss.address().port
36
- ]);
37
- });
38
- wss.on('error', (_)=>{
39
- resolve([]);
30
+ const readBody = (request)=>new Promise((resolve)=>{
31
+ const bodyParts = [];
32
+ request.on('data', (chunk)=>{
33
+ bodyParts.push(chunk);
34
+ }).on('end', ()=>{
35
+ resolve(Buffer.concat(bodyParts).toString());
40
36
  });
41
37
  });
42
- return promise;
38
+ const respond = (res, data)=>{
39
+ res.writeHead(200, {
40
+ 'Access-Control-Allow-Origin': '*',
41
+ 'Access-Control-Allow-Methods': 'POST',
42
+ 'Access-Control-Allow-Headers': '*',
43
+ 'Content-Type': 'application/json'
44
+ });
45
+ if (data) {
46
+ res.write(data);
47
+ }
48
+ res.end();
43
49
  };
44
50
  export const createServer = async (handler, port)=>{
45
51
  let wss;
46
52
  let listenPort;
53
+ const emptySubscriptionManager = {
54
+ subscribe: ()=>{
55
+ throw new Error('Subscription is not supported');
56
+ },
57
+ unsubscribe: ()=>{
58
+ throw new Error('Subscription is not supported');
59
+ }
60
+ };
61
+ const server = http.createServer(async (req, res)=>{
62
+ if (req.method === 'OPTIONS') {
63
+ return respond(res);
64
+ }
65
+ try {
66
+ if (req.method !== 'POST') {
67
+ throw new Error('Only POST method is supported');
68
+ }
69
+ const body = await readBody(req);
70
+ const parsed = await requestSchema.safeParseAsync(parseRequest(body));
71
+ if (!parsed.success) {
72
+ httpLogger.error('Invalid request: %s', body);
73
+ throw new Error('Invalid request: ' + body);
74
+ }
75
+ httpLogger.trace({
76
+ req: parsed.data
77
+ }, 'Received request');
78
+ let response;
79
+ if (Array.isArray(parsed.data)) {
80
+ response = await Promise.all(parsed.data.map((req)=>{
81
+ const result = handler(req, emptySubscriptionManager);
82
+ return {
83
+ id: req.id,
84
+ jsonrpc: '2.0',
85
+ result
86
+ };
87
+ }));
88
+ } else {
89
+ const result = await handler(parsed.data, emptySubscriptionManager);
90
+ response = {
91
+ id: parsed.data.id,
92
+ jsonrpc: '2.0',
93
+ result
94
+ };
95
+ }
96
+ respond(res, JSON.stringify(response));
97
+ } catch (err) {
98
+ respond(res, JSON.stringify({
99
+ jsonrpc: '2.0',
100
+ id: 1,
101
+ error: {
102
+ message: err.message
103
+ }
104
+ }));
105
+ }
106
+ });
47
107
  for(let i = 0; i < 10; i++){
48
- const preferPort = (port ?? 0) > 0 ? (port ?? 0) + i : 0;
49
- logger.debug('Try starting on port %d', preferPort);
50
- const [maybeWss, maybeListenPort] = await createWS(preferPort);
51
- if (maybeWss && maybeListenPort) {
52
- wss = maybeWss;
53
- listenPort = maybeListenPort;
108
+ const preferPort = port ? port + i : undefined;
109
+ wsLogger.debug('Try starting on port %d', preferPort);
110
+ const success = await new Promise((resolve)=>{
111
+ server.once('error', (e)=>{
112
+ if (e.code === 'EADDRINUSE') {
113
+ server.close();
114
+ resolve(false);
115
+ }
116
+ });
117
+ server.listen(preferPort, ()=>{
118
+ wss = new WebSocketServer({
119
+ server,
120
+ maxPayload: 1024 * 1024 * 100
121
+ });
122
+ listenPort = server.address().port;
123
+ resolve(true);
124
+ });
125
+ });
126
+ if (success) {
54
127
  break;
55
128
  }
56
129
  }
@@ -58,7 +131,7 @@ export const createServer = async (handler, port)=>{
58
131
  throw new Error(`Failed to create WebsocketServer at port ${port}`);
59
132
  }
60
133
  wss.on('connection', (ws)=>{
61
- logger.debug('New connection');
134
+ wsLogger.debug('New connection');
62
135
  const send = (data)=>{
63
136
  if (ws.readyState === WebSocket.OPEN) {
64
137
  ws.send(JSON.stringify(data));
@@ -70,7 +143,7 @@ export const createServer = async (handler, port)=>{
70
143
  subscriptions[subid] = onCancel;
71
144
  return (data)=>{
72
145
  if (subscriptions[subid]) {
73
- logger.trace({
146
+ wsLogger.trace({
74
147
  method,
75
148
  subid,
76
149
  data: truncate(data)
@@ -94,13 +167,13 @@ export const createServer = async (handler, port)=>{
94
167
  }
95
168
  };
96
169
  const processRequest = async (req)=>{
97
- logger.trace({
170
+ wsLogger.trace({
98
171
  id: req.id,
99
172
  method: req.method
100
173
  }, 'Received message');
101
174
  try {
102
175
  const resp = await handler(req, subscriptionManager);
103
- logger.trace({
176
+ wsLogger.trace({
104
177
  id: req.id,
105
178
  method: req.method,
106
179
  result: truncate(resp)
@@ -111,7 +184,7 @@ export const createServer = async (handler, port)=>{
111
184
  result: resp ?? null
112
185
  };
113
186
  } catch (e) {
114
- logger.info('Error handling request: %o', e.stack);
187
+ wsLogger.info('Error handling request: %o', e.stack);
115
188
  return {
116
189
  id: req.id,
117
190
  jsonrpc: '2.0',
@@ -123,14 +196,14 @@ export const createServer = async (handler, port)=>{
123
196
  }
124
197
  };
125
198
  ws.on('close', ()=>{
126
- logger.debug('Connection closed');
199
+ wsLogger.debug('Connection closed');
127
200
  for (const [subid, onCancel] of Object.entries(subscriptions)){
128
201
  onCancel(subid);
129
202
  }
130
203
  ws.removeAllListeners();
131
204
  });
132
205
  ws.on('error', ()=>{
133
- logger.debug('Connection error');
206
+ wsLogger.debug('Connection error');
134
207
  for (const [subid, onCancel] of Object.entries(subscriptions)){
135
208
  onCancel(subid);
136
209
  }
@@ -139,7 +212,7 @@ export const createServer = async (handler, port)=>{
139
212
  ws.on('message', async (message)=>{
140
213
  const parsed = await requestSchema.safeParseAsync(parseRequest(message.toString()));
141
214
  if (!parsed.success) {
142
- logger.info('Invalid request: %s', message);
215
+ wsLogger.error('Invalid request: %s', message);
143
216
  send({
144
217
  id: null,
145
218
  jsonrpc: '2.0',
@@ -152,13 +225,13 @@ export const createServer = async (handler, port)=>{
152
225
  }
153
226
  const { data: req } = parsed;
154
227
  if (Array.isArray(req)) {
155
- logger.trace({
228
+ wsLogger.trace({
156
229
  req
157
230
  }, 'Received batch request');
158
231
  const resp = await Promise.all(req.map(processRequest));
159
232
  send(resp);
160
233
  } else {
161
- logger.trace({
234
+ wsLogger.trace({
162
235
  req
163
236
  }, 'Received single request');
164
237
  const resp = await processRequest(req);
@@ -168,15 +241,10 @@ export const createServer = async (handler, port)=>{
168
241
  });
169
242
  return {
170
243
  port: listenPort,
171
- close: ()=>new Promise((resolve, reject)=>{
172
- wss?.clients.forEach((socket)=>socket.close());
173
- wss?.close((err)=>{
174
- if (err) {
175
- reject(err);
176
- } else {
177
- resolve();
178
- }
179
- });
180
- })
244
+ close: async ()=>{
245
+ server.close();
246
+ server.closeAllConnections();
247
+ server.unref();
248
+ }
181
249
  };
182
250
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acala-network/chopsticks",
3
- "version": "0.9.9",
3
+ "version": "0.9.11-1",
4
4
  "author": "Acala Developers <hello@acala.network>",
5
5
  "license": "Apache-2.0",
6
6
  "bin": "./chopsticks.cjs",
@@ -13,15 +13,15 @@
13
13
  "docs:prep": "typedoc"
14
14
  },
15
15
  "dependencies": {
16
- "@acala-network/chopsticks-core": "0.9.9",
17
- "@acala-network/chopsticks-db": "0.9.9",
16
+ "@acala-network/chopsticks-core": "0.9.11-1",
17
+ "@acala-network/chopsticks-db": "0.9.11-1",
18
18
  "@pnpm/npm-conf": "^2.2.2",
19
19
  "@polkadot/api-augment": "^10.11.2",
20
20
  "@polkadot/types": "^10.11.2",
21
21
  "@polkadot/util": "^12.6.2",
22
22
  "@polkadot/util-crypto": "^12.6.2",
23
- "axios": "^1.6.5",
24
- "dotenv": "^16.4.0",
23
+ "axios": "^1.6.8",
24
+ "dotenv": "^16.4.5",
25
25
  "global-agent": "^3.0.0",
26
26
  "js-yaml": "^4.1.0",
27
27
  "jsondiffpatch": "^0.5.0",
@@ -32,15 +32,15 @@
32
32
  },
33
33
  "devDependencies": {
34
34
  "@swc/cli": "0.1.65",
35
- "@swc/core": "^1.3.105",
35
+ "@swc/core": "^1.4.8",
36
36
  "@types/global-agent": "^2.1.3",
37
37
  "@types/js-yaml": "^4.0.9",
38
- "@types/lodash": "^4.14.202",
38
+ "@types/lodash": "^4.17.0",
39
39
  "@types/node": "^20.11.5",
40
40
  "@types/ws": "^8.5.10",
41
41
  "@types/yargs": "^17.0.32",
42
42
  "typescript": "^5.3.3",
43
- "vitest": "^1.2.1"
43
+ "vitest": "^1.4.0"
44
44
  },
45
45
  "files": [
46
46
  "dist/esm/**",