From 6a1c89d02e74806d78a3aa201468ec90306eed30 Mon Sep 17 00:00:00 2001 From: gyroflaw <83718263+gyroflaw@users.noreply.github.com> Date: Tue, 23 Jan 2024 02:03:17 -0500 Subject: [PATCH 1/9] fix: removed invalid event handler(timeout) and updated parser --- src/services/EventStream.ts | 169 ++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 63 deletions(-) diff --git a/src/services/EventStream.ts b/src/services/EventStream.ts index 639b7d2f8..371d402c4 100644 --- a/src/services/EventStream.ts +++ b/src/services/EventStream.ts @@ -1,13 +1,19 @@ -import http from 'http'; -import https from 'https'; -import { Result, Ok, Err } from 'ts-results'; +import * as http from 'http'; +import * as https from 'https'; + +import { Err, Ok, Result } from 'ts-results'; + +export interface Event { + id: string; + body: T; +} export interface DeploySubscription { deployHash: string; eventHandlerFn: EventHandlerFn; } -enum StreamErrors { +export enum StreamErrors { NotAnEvent, EarlyEndOfStream, MissingDataHeader, @@ -32,13 +38,14 @@ export class DeployWatcher { } start() { - this.es.subscribe(EventName.DeployProcessed, result => { - const deployHash = result.body.DeployProcessed.deploy_hash; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.es.subscribe(EventName.DeployProcessed, (event: any) => { + const deployHash = event.body.DeployProcessed.deploy_hash; const pendingDeploy = this.watchList.find( d => d.deployHash === deployHash ); if (pendingDeploy) { - pendingDeploy.eventHandlerFn(result); + pendingDeploy.eventHandlerFn(event); this.unsubscribe(deployHash); } }); @@ -50,7 +57,7 @@ export class DeployWatcher { } } -type EventHandlerFn = (result: any) => void; +type EventHandlerFn = (event: E) => void; export enum EventName { BlockAdded = 'BlockAdded', @@ -66,9 +73,9 @@ interface EventSubscription { } export interface EventParseResult { - id: string | null; + events: Event[]; + remainder: string | null; err: StreamErrors | null; - body: any | null; } export class EventStream { @@ -100,17 +107,21 @@ export class EventStream { return Ok(true); } - private runEventsLoop(result: EventParseResult) { + private runEventsLoop(event: Event) { this.subscribedTo.forEach((sub: EventSubscription) => { - if (result.body && result.body.hasOwnProperty(sub.eventName)) { - sub.eventHandlerFn(result); + // eslint-disable-next-line no-prototype-builtins + if (event.body && event.body.hasOwnProperty(sub.eventName)) { + sub.eventHandlerFn(event); } }); } - public start(eventId = 0) { + public start(eventId?: number) { const separator = this.eventStreamUrl.indexOf('?') > -1 ? '&' : '?'; - const requestUrl = `${this.eventStreamUrl}${separator}start_from=${eventId}`; + let requestUrl = `${this.eventStreamUrl}${separator}`; + if (eventId !== undefined) { + requestUrl = requestUrl.concat(`start_from=${eventId}`); + } const request = requestUrl.startsWith('https://') ? https.get : http.get; @@ -118,26 +129,8 @@ export class EventStream { this.stream = body; body.on('data', (buf: Uint8Array) => { - const result = parseEvent(Buffer.from(buf).toString()); - if (result && !result.err) { - this.runEventsLoop(result); - } - if (result.err === StreamErrors.EarlyEndOfStream) { - this.pendingDeployString = result.body; - } - if (result.err === StreamErrors.MissingDataHeaderAndId) { - this.pendingDeployString += result.body; - } - if (result.err === StreamErrors.MissingDataHeader) { - this.pendingDeployString += result.body; - this.pendingDeployString += `\nid:${result.id}`; - - const newResult = parseEvent(this.pendingDeployString); - if (newResult.err === null) { - this.pendingDeployString = ''; - } - this.runEventsLoop(newResult); - } + const eventString = Buffer.from(buf).toString(); + this.parse(eventString); }); body.once('readable', () => { console.info('Connected successfully to event stream endpoint.'); @@ -145,58 +138,108 @@ export class EventStream { body.on('error', (error: Error) => { throw error; }); - body.on('timeout', () => { - throw Error('EventStream: Timeout error'); - }); - body.on('close', () => { - throw Error('EventStream: Connection closed'); - }); }); } + public parse(eventString: string) { + const result = parseEvent(eventString); + + if (result.events.length > 0) { + result.events.map(this.runEventsLoop.bind(this)); + } + if (result.err === StreamErrors.EarlyEndOfStream && result.remainder) { + this.pendingDeployString = result.remainder; + } + if (result.err === StreamErrors.MissingDataHeaderAndId) { + this.pendingDeployString += result.remainder; + } + if (result.err === StreamErrors.MissingDataHeader) { + this.pendingDeployString += result.remainder; + + const newResult = parseEvent(this.pendingDeployString); + if (newResult.err === null) { + this.pendingDeployString = ''; + } + result.events.map(this.runEventsLoop.bind(this)); + } + return result; + } + public stop(): void { if (this.stream) this.stream.pause(); } } -export const parseEvent = (eventString: string): any => { +export const parseEvent = (eventString: string): EventParseResult => { if (eventString.startsWith('data')) { - const splitted = eventString.split('\n'); - const id = - splitted[1] && splitted[1].startsWith('id:') - ? splitted[1].substr(3) - : null; - try { - const body = JSON.parse(splitted[0].substr(5)); - if (id) { - // Note: This is case where there is proper object with JSON body and id in one chunk. - return { id, body, err: null }; - } else { - // Note: This is case where there is proper object with JSON body but without ID. - return { id, body, err: StreamErrors.MissingId }; + const splitted = eventString.split('\n').filter(str => str !== ''); + + if (splitted.length === 2) { + const id = + splitted[1] && splitted[1].startsWith('id:') + ? splitted[1].substr(3) + : null; + try { + const body = JSON.parse(splitted[0].substr(5)); + if (id) { + // Note: This is case where there is proper object with JSON body and id in one chunk. + return { events: [{ id, body }], remainder: null, err: null }; + } else { + // Note: This is case where there is proper object with JSON body but without ID. + return { events: [], remainder: body, err: StreamErrors.MissingId }; + } + } catch { + // Note: This is case where there is invalid JSON because of early end of stream. + return { + events: [], + remainder: eventString, + err: StreamErrors.EarlyEndOfStream + }; } - } catch { - // Note: This is case where there is invalid JSON because of early end of stream. - const body = splitted[0]; - return { id, body, err: StreamErrors.EarlyEndOfStream }; + } else if (splitted.length === 4) { + const event0 = parseEvent(splitted[0].concat('\n', splitted[1])); + const event1 = parseEvent(splitted[2].concat('\n', splitted[3])); + + return { + events: [...event0.events, ...event1.events], + remainder: event1.remainder, + err: event1.err + }; + } else { + if (!eventString.startsWith('data:{"ApiVersion"')) { + console.warn(`Unexpected event string: ${eventString}`); + } + return { + events: [], + remainder: eventString, + err: StreamErrors.NotAnEvent + }; } } else { // Note: This is in case where there data chunk which isn't the first one. const splitted = eventString.split('\n'); - const body = splitted[0]; + const id = splitted[1] && splitted[1].startsWith('id:') ? splitted[1].substr(3) : null; if (splitted[0] === ':' && splitted[1] === '' && splitted[2] === '') { - return { id: null, body: null, err: StreamErrors.NotAnEvent }; + return { events: [], remainder: null, err: StreamErrors.NotAnEvent }; } if (id) { - return { id, body, err: StreamErrors.MissingDataHeader }; + return { + events: [], + remainder: eventString, + err: StreamErrors.MissingDataHeader + }; } else { - return { id: null, body, err: StreamErrors.MissingDataHeaderAndId }; + return { + events: [], + remainder: eventString, + err: StreamErrors.MissingDataHeaderAndId + }; } } }; From c85d45248ce7d6bc3f4980114137252261733ea1 Mon Sep 17 00:00:00 2001 From: gyroflaw <83718263+gyroflaw@users.noreply.github.com> Date: Tue, 23 Jan 2024 07:48:43 -0500 Subject: [PATCH 2/9] Revert "fix: removed invalid event handler(timeout) and updated parser" This reverts commit 6a1c89d02e74806d78a3aa201468ec90306eed30. --- src/services/EventStream.ts | 169 ++++++++++++++---------------------- 1 file changed, 63 insertions(+), 106 deletions(-) diff --git a/src/services/EventStream.ts b/src/services/EventStream.ts index 371d402c4..639b7d2f8 100644 --- a/src/services/EventStream.ts +++ b/src/services/EventStream.ts @@ -1,19 +1,13 @@ -import * as http from 'http'; -import * as https from 'https'; - -import { Err, Ok, Result } from 'ts-results'; - -export interface Event { - id: string; - body: T; -} +import http from 'http'; +import https from 'https'; +import { Result, Ok, Err } from 'ts-results'; export interface DeploySubscription { deployHash: string; eventHandlerFn: EventHandlerFn; } -export enum StreamErrors { +enum StreamErrors { NotAnEvent, EarlyEndOfStream, MissingDataHeader, @@ -38,14 +32,13 @@ export class DeployWatcher { } start() { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - this.es.subscribe(EventName.DeployProcessed, (event: any) => { - const deployHash = event.body.DeployProcessed.deploy_hash; + this.es.subscribe(EventName.DeployProcessed, result => { + const deployHash = result.body.DeployProcessed.deploy_hash; const pendingDeploy = this.watchList.find( d => d.deployHash === deployHash ); if (pendingDeploy) { - pendingDeploy.eventHandlerFn(event); + pendingDeploy.eventHandlerFn(result); this.unsubscribe(deployHash); } }); @@ -57,7 +50,7 @@ export class DeployWatcher { } } -type EventHandlerFn = (event: E) => void; +type EventHandlerFn = (result: any) => void; export enum EventName { BlockAdded = 'BlockAdded', @@ -73,9 +66,9 @@ interface EventSubscription { } export interface EventParseResult { - events: Event[]; - remainder: string | null; + id: string | null; err: StreamErrors | null; + body: any | null; } export class EventStream { @@ -107,21 +100,17 @@ export class EventStream { return Ok(true); } - private runEventsLoop(event: Event) { + private runEventsLoop(result: EventParseResult) { this.subscribedTo.forEach((sub: EventSubscription) => { - // eslint-disable-next-line no-prototype-builtins - if (event.body && event.body.hasOwnProperty(sub.eventName)) { - sub.eventHandlerFn(event); + if (result.body && result.body.hasOwnProperty(sub.eventName)) { + sub.eventHandlerFn(result); } }); } - public start(eventId?: number) { + public start(eventId = 0) { const separator = this.eventStreamUrl.indexOf('?') > -1 ? '&' : '?'; - let requestUrl = `${this.eventStreamUrl}${separator}`; - if (eventId !== undefined) { - requestUrl = requestUrl.concat(`start_from=${eventId}`); - } + const requestUrl = `${this.eventStreamUrl}${separator}start_from=${eventId}`; const request = requestUrl.startsWith('https://') ? https.get : http.get; @@ -129,8 +118,26 @@ export class EventStream { this.stream = body; body.on('data', (buf: Uint8Array) => { - const eventString = Buffer.from(buf).toString(); - this.parse(eventString); + const result = parseEvent(Buffer.from(buf).toString()); + if (result && !result.err) { + this.runEventsLoop(result); + } + if (result.err === StreamErrors.EarlyEndOfStream) { + this.pendingDeployString = result.body; + } + if (result.err === StreamErrors.MissingDataHeaderAndId) { + this.pendingDeployString += result.body; + } + if (result.err === StreamErrors.MissingDataHeader) { + this.pendingDeployString += result.body; + this.pendingDeployString += `\nid:${result.id}`; + + const newResult = parseEvent(this.pendingDeployString); + if (newResult.err === null) { + this.pendingDeployString = ''; + } + this.runEventsLoop(newResult); + } }); body.once('readable', () => { console.info('Connected successfully to event stream endpoint.'); @@ -138,108 +145,58 @@ export class EventStream { body.on('error', (error: Error) => { throw error; }); + body.on('timeout', () => { + throw Error('EventStream: Timeout error'); + }); + body.on('close', () => { + throw Error('EventStream: Connection closed'); + }); }); } - public parse(eventString: string) { - const result = parseEvent(eventString); - - if (result.events.length > 0) { - result.events.map(this.runEventsLoop.bind(this)); - } - if (result.err === StreamErrors.EarlyEndOfStream && result.remainder) { - this.pendingDeployString = result.remainder; - } - if (result.err === StreamErrors.MissingDataHeaderAndId) { - this.pendingDeployString += result.remainder; - } - if (result.err === StreamErrors.MissingDataHeader) { - this.pendingDeployString += result.remainder; - - const newResult = parseEvent(this.pendingDeployString); - if (newResult.err === null) { - this.pendingDeployString = ''; - } - result.events.map(this.runEventsLoop.bind(this)); - } - return result; - } - public stop(): void { if (this.stream) this.stream.pause(); } } -export const parseEvent = (eventString: string): EventParseResult => { +export const parseEvent = (eventString: string): any => { if (eventString.startsWith('data')) { - const splitted = eventString.split('\n').filter(str => str !== ''); - - if (splitted.length === 2) { - const id = - splitted[1] && splitted[1].startsWith('id:') - ? splitted[1].substr(3) - : null; - try { - const body = JSON.parse(splitted[0].substr(5)); - if (id) { - // Note: This is case where there is proper object with JSON body and id in one chunk. - return { events: [{ id, body }], remainder: null, err: null }; - } else { - // Note: This is case where there is proper object with JSON body but without ID. - return { events: [], remainder: body, err: StreamErrors.MissingId }; - } - } catch { - // Note: This is case where there is invalid JSON because of early end of stream. - return { - events: [], - remainder: eventString, - err: StreamErrors.EarlyEndOfStream - }; - } - } else if (splitted.length === 4) { - const event0 = parseEvent(splitted[0].concat('\n', splitted[1])); - const event1 = parseEvent(splitted[2].concat('\n', splitted[3])); - - return { - events: [...event0.events, ...event1.events], - remainder: event1.remainder, - err: event1.err - }; - } else { - if (!eventString.startsWith('data:{"ApiVersion"')) { - console.warn(`Unexpected event string: ${eventString}`); + const splitted = eventString.split('\n'); + const id = + splitted[1] && splitted[1].startsWith('id:') + ? splitted[1].substr(3) + : null; + try { + const body = JSON.parse(splitted[0].substr(5)); + if (id) { + // Note: This is case where there is proper object with JSON body and id in one chunk. + return { id, body, err: null }; + } else { + // Note: This is case where there is proper object with JSON body but without ID. + return { id, body, err: StreamErrors.MissingId }; } - return { - events: [], - remainder: eventString, - err: StreamErrors.NotAnEvent - }; + } catch { + // Note: This is case where there is invalid JSON because of early end of stream. + const body = splitted[0]; + return { id, body, err: StreamErrors.EarlyEndOfStream }; } } else { // Note: This is in case where there data chunk which isn't the first one. const splitted = eventString.split('\n'); - + const body = splitted[0]; const id = splitted[1] && splitted[1].startsWith('id:') ? splitted[1].substr(3) : null; if (splitted[0] === ':' && splitted[1] === '' && splitted[2] === '') { - return { events: [], remainder: null, err: StreamErrors.NotAnEvent }; + return { id: null, body: null, err: StreamErrors.NotAnEvent }; } if (id) { - return { - events: [], - remainder: eventString, - err: StreamErrors.MissingDataHeader - }; + return { id, body, err: StreamErrors.MissingDataHeader }; } else { - return { - events: [], - remainder: eventString, - err: StreamErrors.MissingDataHeaderAndId - }; + return { id: null, body, err: StreamErrors.MissingDataHeaderAndId }; } } }; From 85f9943353b72d6a22b1b72c4565c7bbc11da261 Mon Sep 17 00:00:00 2001 From: gyroflaw <83718263+gyroflaw@users.noreply.github.com> Date: Tue, 23 Jan 2024 07:49:17 -0500 Subject: [PATCH 3/9] remove invalid event listener (timeout) --- src/services/EventStream.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/services/EventStream.ts b/src/services/EventStream.ts index 639b7d2f8..deb698e6b 100644 --- a/src/services/EventStream.ts +++ b/src/services/EventStream.ts @@ -145,12 +145,6 @@ export class EventStream { body.on('error', (error: Error) => { throw error; }); - body.on('timeout', () => { - throw Error('EventStream: Timeout error'); - }); - body.on('close', () => { - throw Error('EventStream: Connection closed'); - }); }); } From 8a58ba4d5332733112b09aa2aa78e81fcfc8b601 Mon Sep 17 00:00:00 2001 From: gyroflaw <83718263+gyroflaw@users.noreply.github.com> Date: Tue, 23 Jan 2024 22:01:39 -0500 Subject: [PATCH 4/9] update: start event stream from the latest when id isn't provided --- src/services/EventStream.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/services/EventStream.ts b/src/services/EventStream.ts index deb698e6b..2f5dced7b 100644 --- a/src/services/EventStream.ts +++ b/src/services/EventStream.ts @@ -108,10 +108,12 @@ export class EventStream { }); } - public start(eventId = 0) { + public start(eventId?: number) { const separator = this.eventStreamUrl.indexOf('?') > -1 ? '&' : '?'; - const requestUrl = `${this.eventStreamUrl}${separator}start_from=${eventId}`; - + let requestUrl = `${this.eventStreamUrl}${separator}`; + if (eventId !== undefined) { + requestUrl = requestUrl.concat(`start_from=${eventId}`); + } const request = requestUrl.startsWith('https://') ? https.get : http.get; request(requestUrl, body => { From 42bb0c47082dfa15596b74da18dbabe216668f33 Mon Sep 17 00:00:00 2001 From: gyroflaw <83718263+gyroflaw@users.noreply.github.com> Date: Wed, 24 Jan 2024 04:32:14 -0500 Subject: [PATCH 5/9] feat: use eventsource in eventstream --- package-lock.json | 250 ++++++++++++++++++++++++------------ package.json | 2 + src/services/EventStream.ts | 119 +++++------------ 3 files changed, 199 insertions(+), 172 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3db2165ed..662c4a5bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,11 +20,12 @@ "@scure/bip32": "^1.1.5", "@scure/bip39": "^1.2.0", "@types/ws": "^8.2.2", + "eventsource": "^2.0.2", "glob": "^7.1.6", "humanize-duration": "^3.24.0", "key-encoder": "^2.0.3", "lodash": "^4.17.21", - "node-fetch": "^2.6.11", + "node-fetch": "2.6.13", "reflect-metadata": "^0.1.13", "ts-results": "npm:@casperlabs/ts-results@^3.3.4", "typedjson": "^1.6.0-rc2" @@ -33,6 +34,7 @@ "@jsdevtools/coverage-istanbul-loader": "^3.0.5", "@types/chai": "^4.1.7", "@types/chai-as-promised": "^7.1.5", + "@types/eventsource": "^1.1.15", "@types/humanize-duration": "^3.18.1", "@types/lodash": "^4.14.191", "@types/mocha": "^5.2.7", @@ -101,17 +103,80 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz", @@ -161,12 +226,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz", - "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -219,22 +284,22 @@ "dev": true }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -296,9 +361,9 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz", - "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { "@babel/types": "^7.22.5" @@ -308,18 +373,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" @@ -349,13 +414,13 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -425,9 +490,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", - "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -437,34 +502,34 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz", - "integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -481,13 +546,13 @@ } }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1354,6 +1419,12 @@ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", "dev": true }, + "node_modules/@types/eventsource": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@types/eventsource/-/eventsource-1.1.15.tgz", + "integrity": "sha512-XQmGcbnxUNa06HR3VBVkc9+A2Vpi9ZyLJcdS5dwaQQ/4ZMWFO+5c90FnMUpbtMZwB/FChoYHwuVg8TvkECacTA==", + "dev": true + }, "node_modules/@types/humanize-duration": { "version": "3.18.1", "resolved": "https://registry.npmjs.org/@types/humanize-duration/-/humanize-duration-3.18.1.tgz", @@ -2177,12 +2248,12 @@ } }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -2523,26 +2594,29 @@ "dev": true }, "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", + "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", "dev": true, "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", + "elliptic": "^6.5.4", "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "parse-asn1": "^5.1.6", + "readable-stream": "^3.6.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 4" } }, "node_modules/browserify-sign/node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", "dev": true }, "node_modules/browserify-zlib": { @@ -4318,6 +4392,14 @@ "node": ">=0.8.x" } }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -4564,9 +4646,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "dev": true, "funding": [ { @@ -4716,9 +4798,9 @@ } }, "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, "engines": { "node": "*" @@ -7128,9 +7210,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -8028,9 +8110,9 @@ } }, "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { "inherits": "^2.0.3", diff --git a/package.json b/package.json index f6f81a5c3..54b72bbf7 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "@jsdevtools/coverage-istanbul-loader": "^3.0.5", "@types/chai": "^4.1.7", "@types/chai-as-promised": "^7.1.5", + "@types/eventsource": "^1.1.15", "@types/humanize-duration": "^3.18.1", "@types/lodash": "^4.14.191", "@types/mocha": "^5.2.7", @@ -119,6 +120,7 @@ "@scure/bip32": "^1.1.5", "@scure/bip39": "^1.2.0", "@types/ws": "^8.2.2", + "eventsource": "^2.0.2", "glob": "^7.1.6", "humanize-duration": "^3.24.0", "key-encoder": "^2.0.3", diff --git a/src/services/EventStream.ts b/src/services/EventStream.ts index 2f5dced7b..df97da8cc 100644 --- a/src/services/EventStream.ts +++ b/src/services/EventStream.ts @@ -1,5 +1,4 @@ -import http from 'http'; -import https from 'https'; +import EventSource from 'eventsource'; import { Result, Ok, Err } from 'ts-results'; export interface DeploySubscription { @@ -7,6 +6,9 @@ export interface DeploySubscription { eventHandlerFn: EventHandlerFn; } +/** + * @deprecated + */ enum StreamErrors { NotAnEvent, EarlyEndOfStream, @@ -53,11 +55,16 @@ export class DeployWatcher { type EventHandlerFn = (result: any) => void; export enum EventName { + /** Can be fetched in `/events/main` path */ BlockAdded = 'BlockAdded', + /** Can be fetched in `/events/main` path */ + DeployProcessed = 'DeployProcessed', + /** Can be fetched in `/events/deploys` path */ + DeployAccepted = 'DeployAccepted', BlockFinalized = 'BlockFinalized', + /** Can be fetched in `/events/sigs` path */ FinalitySignature = 'FinalitySignature', - Fault = 'Fault', - DeployProcessed = 'DeployProcessed' + Fault = 'Fault' } interface EventSubscription { @@ -65,17 +72,16 @@ interface EventSubscription { eventHandlerFn: EventHandlerFn; } -export interface EventParseResult { - id: string | null; - err: StreamErrors | null; - body: any | null; +export interface EventParseResult { + id: string; + /** @deprecated */ + err?: StreamErrors | null; + body: E; } export class EventStream { subscribedTo: EventSubscription[] = []; - pendingDeploysParts: EventParseResult[] = []; - pendingDeployString = ''; - stream?: NodeJS.ReadableStream; + eventSource: EventSource; constructor(public eventStreamUrl: string) {} @@ -114,85 +120,22 @@ export class EventStream { if (eventId !== undefined) { requestUrl = requestUrl.concat(`start_from=${eventId}`); } - const request = requestUrl.startsWith('https://') ? https.get : http.get; - - request(requestUrl, body => { - this.stream = body; - - body.on('data', (buf: Uint8Array) => { - const result = parseEvent(Buffer.from(buf).toString()); - if (result && !result.err) { - this.runEventsLoop(result); - } - if (result.err === StreamErrors.EarlyEndOfStream) { - this.pendingDeployString = result.body; - } - if (result.err === StreamErrors.MissingDataHeaderAndId) { - this.pendingDeployString += result.body; - } - if (result.err === StreamErrors.MissingDataHeader) { - this.pendingDeployString += result.body; - this.pendingDeployString += `\nid:${result.id}`; - - const newResult = parseEvent(this.pendingDeployString); - if (newResult.err === null) { - this.pendingDeployString = ''; - } - this.runEventsLoop(newResult); - } - }); - body.once('readable', () => { - console.info('Connected successfully to event stream endpoint.'); - }); - body.on('error', (error: Error) => { - throw error; - }); - }); + this.eventSource = new EventSource(requestUrl); + + this.eventSource.onmessage = e => { + const event = { + body: JSON.parse(e.data), + id: e.lastEventId + }; + this.runEventsLoop(event); + }; + + this.eventSource.onerror = err => { + throw err; + }; } public stop(): void { - if (this.stream) this.stream.pause(); + if (this.eventSource) this.eventSource.close(); } } - -export const parseEvent = (eventString: string): any => { - if (eventString.startsWith('data')) { - const splitted = eventString.split('\n'); - const id = - splitted[1] && splitted[1].startsWith('id:') - ? splitted[1].substr(3) - : null; - try { - const body = JSON.parse(splitted[0].substr(5)); - if (id) { - // Note: This is case where there is proper object with JSON body and id in one chunk. - return { id, body, err: null }; - } else { - // Note: This is case where there is proper object with JSON body but without ID. - return { id, body, err: StreamErrors.MissingId }; - } - } catch { - // Note: This is case where there is invalid JSON because of early end of stream. - const body = splitted[0]; - return { id, body, err: StreamErrors.EarlyEndOfStream }; - } - } else { - // Note: This is in case where there data chunk which isn't the first one. - const splitted = eventString.split('\n'); - const body = splitted[0]; - const id = - splitted[1] && splitted[1].startsWith('id:') - ? splitted[1].substr(3) - : null; - - if (splitted[0] === ':' && splitted[1] === '' && splitted[2] === '') { - return { id: null, body: null, err: StreamErrors.NotAnEvent }; - } - - if (id) { - return { id, body, err: StreamErrors.MissingDataHeader }; - } else { - return { id: null, body, err: StreamErrors.MissingDataHeaderAndId }; - } - } -}; From 7739d226acba5376302be67db3037d552c266e71 Mon Sep 17 00:00:00 2001 From: Jan Hoffmann Date: Thu, 1 Feb 2024 17:13:14 +0100 Subject: [PATCH 6/9] docs: version bump and CHANGELOG.md addition --- CHANGELOG.md | 8 +++++++- package.json | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4179e168..8e46afbc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,11 +13,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Removed --> +## [2.15.4] - 2024-02-01 + +### Fixed + +- Fixed implementation of `EventStream`. Previous one had problems when there was two events emmited in the same time. + ## [2.15.3] - 2023-10-16 ### Fixed -- replace legacy `sendAsync` with `request` ([#373](https://github.com/casper-ecosystem/casper-js-sdk/pull/373)) +- Replace legacy `sendAsync` with `request` ([#373](https://github.com/casper-ecosystem/casper-js-sdk/pull/373)) [2.15.3]: https://github.com/casper-ecosystem/casper-js-sdk/compare/2.15.2...2.15.3 diff --git a/package.json b/package.json index 54b72bbf7..77c89a826 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "casper-js-sdk", - "version": "2.15.3", + "version": "2.15.4", "license": "Apache 2.0", "description": "SDK to interact with the Casper blockchain", "homepage": "https://github.com/casper-ecosystem/casper-js-sdk#README.md", From 99186c442564d6e83bbe1f65265452b319483a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20W=C3=B3dkiewicz?= Date: Mon, 5 Feb 2024 11:22:40 +0100 Subject: [PATCH 7/9] fix: rename lib.js to lib.web.js This fixes TypeScript support for NodeNext/Node16/Bundler moduleResolution. The issue was that the ./dist/lib.js had a higher precedence than ./dist/lib/index.d.ts when TypeScript tried to resolve "./lib" imports/exports. Instead of renaming the whole lib/ folder I decided to add a infix to the lib.js artifact. But to solve the issue you could've renamed the directory instead. --- .github/workflows/publish-casper-client-sdk.yml | 2 +- package.json | 2 +- webpack.config.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-casper-client-sdk.yml b/.github/workflows/publish-casper-client-sdk.yml index b6d991488..ba0f7d342 100644 --- a/.github/workflows/publish-casper-client-sdk.yml +++ b/.github/workflows/publish-casper-client-sdk.yml @@ -32,7 +32,7 @@ jobs: - name: Get latest release version number id: get_version uses: battila7/get-version-action@d97fbc34ceb64d1f5d95f4dfd6dce33521ccccf5 #v2.3.0 - - run: cp dist/lib.js casper-js-sdk.v${{ steps.get_version.outputs.version }}.js + - run: cp dist/lib.web.js casper-js-sdk.v${{ steps.get_version.outputs.version }}.js - uses: meeDamian/github-release@7ae19492500104f636b3fee4d8103af0fed36c8e #v2.0.3 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/package.json b/package.json index f6f81a5c3..3e444847a 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "url": "https://github.com/casper-ecosystem/casper-js-sdk.git" }, "main": "dist/lib.node.js", - "browser": "dist/lib.js", + "browser": "dist/lib.web.js", "types": "dist/index.d.ts", "scripts": { "prepare": "husky-run install", diff --git a/webpack.config.js b/webpack.config.js index 9c8846c78..590bf4065 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -70,7 +70,7 @@ const clientConfig = { ], output: { path: path.resolve(__dirname, 'dist'), - filename: 'lib.js', + filename: 'lib.web.js', libraryTarget: 'umd' } }; From cfa3c44fd7d07a6ed990e338338d456a899b602b Mon Sep 17 00:00:00 2001 From: Jan Hoffmann Date: Thu, 8 Feb 2024 16:25:53 +0100 Subject: [PATCH 8/9] fix: newTransferWithOptionalTransferId use PublicKey --- CHANGELOG.md | 3 ++- src/lib/DeployUtil.ts | 5 +---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e46afbc3..029b09763 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,10 +13,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Removed --> -## [2.15.4] - 2024-02-01 +## [2.15.4] - 2024-02-08 ### Fixed +- `newTransferWithOptionalTransferId` now uses `PublicKey` as a target instead of `AccountHash`. - Fixed implementation of `EventStream`. Previous one had problems when there was two events emmited in the same time. ## [2.15.3] - 2023-10-16 diff --git a/src/lib/DeployUtil.ts b/src/lib/DeployUtil.ts index bed06ee4f..51743a1f5 100644 --- a/src/lib/DeployUtil.ts +++ b/src/lib/DeployUtil.ts @@ -984,10 +984,7 @@ export class ExecutableDeployItem implements ToBytes { if (target instanceof CLURef) { runtimeArgs.insert('target', target); } else if (target instanceof CLPublicKey) { - runtimeArgs.insert( - 'target', - CLValueBuilder.byteArray(target.toAccountHash()) - ); + runtimeArgs.insert('target', target); } else { throw new Error('Please specify target'); } From c848b337002cfbdf62e5a0481489085620f2df8b Mon Sep 17 00:00:00 2001 From: Jan Hoffmann Date: Mon, 12 Feb 2024 18:17:10 +0100 Subject: [PATCH 9/9] docs: Updated changelog --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 029b09763..027d4e39d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,12 +13,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Removed --> -## [2.15.4] - 2024-02-08 +## [2.15.4] - 2024-02-12 ### Fixed -- `newTransferWithOptionalTransferId` now uses `PublicKey` as a target instead of `AccountHash`. -- Fixed implementation of `EventStream`. Previous one had problems when there was two events emmited in the same time. +- [`newTransferWithOptionalTransferId` now uses `PublicKey` as a target instead of `AccountHash`.](https://github.com/casper-ecosystem/casper-js-sdk/issues/385) +- [Fixed implementation of `EventStream`. Previous one had problems when there was two events emmited at the same time](https://github.com/casper-ecosystem/casper-js-sdk/issues/379) +- [Fixed imports problem in modern TS environment](https://github.com/casper-ecosystem/casper-js-sdk/issues/386) ## [2.15.3] - 2023-10-16