@@ -2,25 +2,68 @@ import { sendMessage } from "@coreUtils/utils";
2
2
import {
3
3
BackgroundMessage ,
4
4
BlockPopupMessage ,
5
+ FeeNotificationBorder ,
5
6
Fees ,
6
7
FeesPopupMessage ,
7
- PlayBlockNotificationSoundOffscreenMessage
8
+ PlayNotificationSoundOffscreenMessage
8
9
} from "@models/types" ;
10
+ import logo from "@static/images/logo.png" ;
9
11
12
+ import { releaseNotes } from "./utils/releaseNotes" ;
10
13
import { getSocketUrl } from "./utils/utils" ;
11
14
12
15
const OFFSCREEN_DOCUMENT_NAME = "offScreen.html" ;
13
16
const OFFSCREEN_DOCUMENT_PATH = `../${ OFFSCREEN_DOCUMENT_NAME } ` ;
14
17
15
- let creating : Promise < void > | null ;
16
- let socket : WebSocket | null ;
18
+ let isBlockNotificationEnabled : boolean | null = null ;
19
+ let isMainnet : boolean | null = null ;
20
+ let creating : Promise < void > | null = null ;
21
+ let socket : WebSocket | null = null ;
17
22
let intervalId : NodeJS . Timer | null ;
18
- let fees : Fees | null ;
19
- let lastBlockTime : number | null ;
20
- let lastBlockHeight : number | null ;
23
+ let fees : Fees | null = null ;
24
+ let lastBlockTime : number | null = null ;
25
+ let lastBlockHeight : number | null = null ;
21
26
let blockNotificationVolume : number = 100 ;
22
27
let blockNotificationSound : string | null = null ;
23
28
29
+ let isFeeNotificationEnabled : boolean | null = null ;
30
+ let feeNotificationBorder : FeeNotificationBorder | null = null ;
31
+ let feeNotificationVolume : number = 100 ;
32
+ let feeNotificationSound : string | null = null ;
33
+
34
+ chrome . runtime . onInstalled . addListener ( ( details ) => {
35
+ try {
36
+ const currentVersion = chrome . runtime . getManifest ( ) . version ;
37
+ if ( details . reason === "update" && currentVersion !== details . previousVersion ) {
38
+ console . debug ( `Updated version: ${ currentVersion } . Send notification` ) ;
39
+
40
+ const currentVersionReleaseNotes = releaseNotes [ currentVersion ] ;
41
+
42
+ if ( currentVersionReleaseNotes ) {
43
+ chrome . notifications . create (
44
+ `relese-notes-${ currentVersion } ` ,
45
+ {
46
+ type : "basic" ,
47
+ iconUrl : logo ,
48
+ title : currentVersionReleaseNotes . title ,
49
+ message : currentVersionReleaseNotes . message ,
50
+ buttons : [ { title : "Release Notes" } ]
51
+ } ,
52
+ ( ) => { }
53
+ ) ;
54
+
55
+ chrome . notifications . onClicked . addListener ( ( ) => {
56
+ chrome . tabs . create ( { url : currentVersionReleaseNotes . link } ) ;
57
+ } ) ;
58
+ } else {
59
+ console . debug ( `Release notes for version "${ currentVersion } " not found` ) ;
60
+ }
61
+ }
62
+ } catch ( error ) {
63
+ console . warn ( `Error sending update notification: ${ ( error as Error ) . message } ` ) ;
64
+ }
65
+ } ) ;
66
+
24
67
async function checkOffscreenDocumentExist ( ) : Promise < boolean > {
25
68
// Check all windows controlled by the service worker to see if one
26
69
// of them is the offscreen document with the given path
@@ -51,23 +94,36 @@ async function setupOffscreenDocument() {
51
94
}
52
95
}
53
96
97
+ function initialSettings ( ) : void {
98
+ chrome . storage . local
99
+ . get ( [
100
+ "blockNotificationVolume" ,
101
+ "blockNotificationSound" ,
102
+ "feeNotificationBorder" ,
103
+ "feeNotificationVolume" ,
104
+ "feeNotificationSound"
105
+ ] )
106
+ . then ( ( result ) => {
107
+ blockNotificationVolume = result . blockNotificationVolume ?? 100 ;
108
+ blockNotificationSound = result . blockNotificationSound ;
109
+ feeNotificationBorder = result . feeNotificationBorder ;
110
+ feeNotificationVolume = result . feeNotificationVolume ?? 100 ;
111
+ feeNotificationSound = result . feeNotificationSound ;
112
+ } ) ;
113
+ }
114
+
54
115
function onOpenSocketHandler ( ) : void {
55
116
console . debug ( "Socket is open" ) ;
56
117
console . debug ( "Send data to server" ) ;
57
118
socket ?. send ( JSON . stringify ( { action : "init" } ) ) ;
58
119
socket ?. send ( JSON . stringify ( { action : "want" , data : [ "blocks" , "stats" ] } ) ) ;
59
-
60
- chrome . storage . local . get ( [ "blockNotificationVolume" , "blockNotificationSound" ] ) . then ( ( result ) => {
61
- blockNotificationVolume = result . blockNotificationVolume ?? 100 ;
62
- blockNotificationSound = result . blockNotificationSound ;
63
- } ) ;
64
120
}
65
121
66
122
function onCloseSocketWithReconnectHandler ( event : CloseEvent , websocketUrl : string ) : void {
67
123
console . debug ( `Socket is closed. Reason: ${ event . reason } ` ) ;
68
124
69
- chrome . storage . local . get ( [ "isTrackingEnabled " ] ) . then ( ( result ) => {
70
- if ( result . isTrackingEnabled && event . code !== 1000 ) {
125
+ chrome . storage . local . get ( [ "isBlockNotificationEnabled" , "isFeeNotificationEnabled "] ) . then ( ( result ) => {
126
+ if ( ( result . isTrackingEnabled || result . isFeeNotificationEnabled ) && event . code !== 1000 ) {
71
127
console . debug ( "Reconnect will be attempted in 1 second." ) ;
72
128
73
129
if ( intervalId ) {
@@ -99,14 +155,16 @@ function onCloseSocketWithReconnectHandler(event: CloseEvent, websocketUrl: stri
99
155
function onBlockMessageHandler ( eventData : any ) : void {
100
156
if ( "block" in eventData ) {
101
157
console . info ( "New block" ) ;
102
- setupOffscreenDocument ( ) . then ( ( ) => {
103
- console . debug ( "Send block notification method to offscreen" ) ;
104
- sendMessage < PlayBlockNotificationSoundOffscreenMessage > ( {
105
- data : { volume : blockNotificationVolume , sound : blockNotificationSound } ,
106
- target : "offscreen" ,
107
- type : "playBlockNotificationSound"
158
+ if ( isBlockNotificationEnabled ) {
159
+ setupOffscreenDocument ( ) . then ( ( ) => {
160
+ console . debug ( "Send block notification to offscreen" ) ;
161
+ sendMessage < PlayNotificationSoundOffscreenMessage > ( {
162
+ data : { volume : blockNotificationVolume , sound : blockNotificationSound } ,
163
+ target : "offscreen" ,
164
+ type : "playBlockNotificationSound"
165
+ } ) ;
108
166
} ) ;
109
- } ) ;
167
+ }
110
168
111
169
lastBlockTime = eventData . block . timestamp * 1000 ;
112
170
lastBlockHeight = eventData . block . height ;
@@ -124,11 +182,44 @@ function onBlockMessageHandler(eventData: any): void {
124
182
}
125
183
}
126
184
185
+ function checkFeeBorder ( oldFees : Fees | null , newFees : Fees | null ) : void {
186
+ if (
187
+ isFeeNotificationEnabled &&
188
+ feeNotificationBorder !== null &&
189
+ feeNotificationBorder . feeBorder &&
190
+ newFees !== null &&
191
+ oldFees !== null
192
+ ) {
193
+ const fromLowToHighCondition =
194
+ oldFees [ feeNotificationBorder . feeLevel ] < newFees [ feeNotificationBorder . feeLevel ] &&
195
+ newFees [ feeNotificationBorder . feeLevel ] >= feeNotificationBorder . feeBorder &&
196
+ oldFees [ feeNotificationBorder . feeLevel ] < feeNotificationBorder . feeBorder ;
197
+ const fromHighToLowCondition =
198
+ oldFees [ feeNotificationBorder . feeLevel ] > newFees [ feeNotificationBorder . feeLevel ] &&
199
+ newFees [ feeNotificationBorder . feeLevel ] <= feeNotificationBorder . feeBorder &&
200
+ oldFees [ feeNotificationBorder . feeLevel ] > feeNotificationBorder . feeBorder ;
201
+
202
+ if ( fromLowToHighCondition || fromHighToLowCondition ) {
203
+ setupOffscreenDocument ( ) . then ( ( ) => {
204
+ console . debug ( "Send fee notification to offscreen" ) ;
205
+ sendMessage < PlayNotificationSoundOffscreenMessage > ( {
206
+ data : { volume : feeNotificationVolume , sound : feeNotificationSound } ,
207
+ target : "offscreen" ,
208
+ type : "playFeeNotificationSound"
209
+ } ) ;
210
+ } ) ;
211
+ }
212
+ }
213
+ }
214
+
127
215
function onFeesMessageHandler ( eventData : any ) : void {
128
216
if ( "fees" in eventData ) {
129
217
console . debug ( "Fee updated" ) ;
218
+ const lastFees = structuredClone ( fees ) ;
219
+
130
220
fees = eventData . fees ;
131
221
sendMessage < FeesPopupMessage > ( { target : "popup" , data : { fees } , type : "fees" } ) ;
222
+ checkFeeBorder ( lastFees , fees ) ;
132
223
133
224
console . info ( `Current fees: slow: ${ fees ?. hourFee } , medium: ${ fees ?. halfHourFee } , fast: ${ fees ?. fastestFee } ` ) ;
134
225
}
@@ -191,55 +282,75 @@ function mempoolSpaceBlockNotification(websocketUrl: string) {
191
282
intervalId = setInterval ( healthcheck , 1000 ) ;
192
283
}
193
284
194
- function enableBlocksTracking ( isMainnet : boolean ) : void {
195
- console . log ( "Enabling blocks tracking" ) ;
196
- mempoolSpaceBlockNotification ( getSocketUrl ( isMainnet ) ) ;
285
+ function enableWebSocket ( _isMainnet : boolean ) : void {
286
+ if ( ( isBlockNotificationEnabled || isFeeNotificationEnabled ) && ! socket ) {
287
+ console . log ( "Enabling web socket" ) ;
288
+ initialSettings ( ) ;
289
+ mempoolSpaceBlockNotification ( getSocketUrl ( _isMainnet ) ) ;
290
+ }
197
291
}
198
292
199
- function disableBlocksTracking ( ) : void {
200
- console . log ( "Disabling blocks tracking" ) ;
201
- checkOffscreenDocumentExist ( ) . then ( ( isOffscreenDocumentExist : boolean ) => {
202
- if ( isOffscreenDocumentExist ) {
203
- chrome . offscreen . closeDocument ( ) ;
204
- }
205
- } ) ;
206
- socket ?. close ( 1000 , "Disabling blocks tracking" ) ;
293
+ function disableWebSocket ( ) : void {
294
+ if ( ! isBlockNotificationEnabled && ! isFeeNotificationEnabled ) {
295
+ console . log ( "Disabling web socket" ) ;
296
+ checkOffscreenDocumentExist ( ) . then ( ( isOffscreenDocumentExist : boolean ) => {
297
+ if ( isOffscreenDocumentExist ) {
298
+ chrome . offscreen . closeDocument ( ) ;
299
+ }
300
+ } ) ;
301
+ socket ?. close ( 1000 , "Disabling blocks tracking" ) ;
207
302
208
- fees = null ;
209
- lastBlockTime = null ;
210
- lastBlockHeight = null ;
303
+ fees = null ;
304
+ lastBlockTime = null ;
305
+ lastBlockHeight = null ;
211
306
212
- sendMessage < BlockPopupMessage > ( {
213
- target : "popup" ,
214
- data : { blockInfo : { lastBlockTime, lastBlockHeight } } ,
215
- type : "blockInfo"
216
- } ) ;
217
- sendMessage < FeesPopupMessage > ( { target : "popup" , data : { fees } , type : "fees" } ) ;
307
+ sendMessage < BlockPopupMessage > ( {
308
+ target : "popup" ,
309
+ data : { blockInfo : { lastBlockTime, lastBlockHeight } } ,
310
+ type : "blockInfo"
311
+ } ) ;
312
+ sendMessage < FeesPopupMessage > ( { target : "popup" , data : { fees } , type : "fees" } ) ;
313
+ }
218
314
}
219
315
220
- chrome . storage . local . get ( [ "isTrackingEnabled" , "isMainnet" ] ) . then ( ( result ) => {
221
- const isTrackingEnabled = result . isTrackingEnabled || false ;
222
- const isMainnet = result . isMainnet || true ;
316
+ chrome . storage . local . get ( [ "isBlockNotificationEnabled" , "isMainnet" , "isFeeNotificationEnabled" ] ) . then ( ( result ) => {
317
+ isBlockNotificationEnabled = result . isBlockNotificationEnabled ?? false ;
318
+ isFeeNotificationEnabled = result . isFeeNotificationEnabled ?? false ;
319
+ isMainnet = result . isMainnet ?? true ;
223
320
224
- if ( isTrackingEnabled && ! socket ) {
225
- enableBlocksTracking ( isMainnet ) ;
321
+ enableWebSocket ( ! ! isMainnet ) ;
322
+ } ) ;
323
+
324
+ chrome . runtime . onMessage . addListener ( ( message : BackgroundMessage ) => {
325
+ if ( message . target === "background" && message . type === "changeBlockNotificationEnabled" ) {
326
+ isBlockNotificationEnabled = message . data . enabled ;
327
+ if ( isBlockNotificationEnabled ) {
328
+ enableWebSocket ( ! ! isMainnet ) ;
329
+ } else {
330
+ disableWebSocket ( ) ;
331
+ }
226
332
}
227
333
} ) ;
228
334
229
335
chrome . runtime . onMessage . addListener ( ( message : BackgroundMessage ) => {
230
- if ( message . target === "background" && message . type === "changeEnabled" ) {
231
- if ( message . data . enabled ) {
232
- enableBlocksTracking ( message . data . isMainnet ) ;
336
+ if ( message . target === "background" && message . type === "changeFeeNotificationEnabled" ) {
337
+ isFeeNotificationEnabled = message . data . enabled ;
338
+ if ( isFeeNotificationEnabled ) {
339
+ enableWebSocket ( ! ! isMainnet ) ;
233
340
} else {
234
- disableBlocksTracking ( ) ;
341
+ disableWebSocket ( ) ;
235
342
}
236
343
}
237
344
} ) ;
238
345
239
346
chrome . runtime . onMessage . addListener ( ( message : BackgroundMessage ) => {
240
- if ( message . target === "background" && message . type === "changeBlockchain" && message . data . enabled && socket ) {
241
- console . log ( `Changing blockchain to ${ message . data . isMainnet ? "mainnet" : "testnet" } ` ) ;
242
- socket . close ( 3001 , getSocketUrl ( message . data . isMainnet ) ) ;
347
+ if ( message . target === "background" && message . type === "changeBlockchain" ) {
348
+ isMainnet = message . data . isMainnet ;
349
+
350
+ if ( ( isBlockNotificationEnabled || isFeeNotificationEnabled ) && socket ) {
351
+ console . log ( `Changing blockchain to ${ message . data . isMainnet ? "mainnet" : "testnet" } ` ) ;
352
+ socket . close ( 3001 , getSocketUrl ( message . data . isMainnet ) ) ;
353
+ }
243
354
}
244
355
} ) ;
245
356
@@ -278,3 +389,27 @@ chrome.runtime.onMessage.addListener((message: BackgroundMessage) => {
278
389
blockNotificationSound = message . data . sound ;
279
390
}
280
391
} ) ;
392
+
393
+ chrome . runtime . onMessage . addListener ( ( message : BackgroundMessage ) => {
394
+ if ( message . target === "background" && message . type === "changeFeeNotificationSoundVolume" ) {
395
+ console . debug ( "Change fee notification sound volume" ) ;
396
+
397
+ feeNotificationVolume = message . data . volume ;
398
+ }
399
+ } ) ;
400
+
401
+ chrome . runtime . onMessage . addListener ( ( message : BackgroundMessage ) => {
402
+ if ( message . target === "background" && message . type === "changeFeeNotificationSound" ) {
403
+ console . debug ( "Change fee notification sound" ) ;
404
+
405
+ feeNotificationSound = message . data . sound ;
406
+ }
407
+ } ) ;
408
+
409
+ chrome . runtime . onMessage . addListener ( ( message : BackgroundMessage ) => {
410
+ if ( message . target === "background" && message . type === "changeFeeNotificationBorder" ) {
411
+ console . debug ( "Change fee notification border" ) ;
412
+
413
+ feeNotificationBorder = message . data . feeBorder ;
414
+ }
415
+ } ) ;
0 commit comments