@beblurt/blurt-nodes-checker 1.1.2 → 2.0.0

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 CHANGED
@@ -1,322 +1,111 @@
1
- # Blurt RPC nodes checker
2
-
3
- ESM Typscript [Blurt blockchain](https://gitlab.com/blurt/blurt) RPC nodes servers checker (latency, availability, methods).
4
-
5
- Checks the status of the RPC nodes servers of the Blurt blockchain at a specified interval and sends a report via a RxJS subscription. The result is stored in an array in memory and you can call it at any time.
6
-
7
- The library also allows you to identify the compatibility of an RPC node with [Nexus](https://gitlab.com/blurt/openblurt/nexus) (communities on the [Blurt blockchain](https://gitlab.com/blurt/blurt)) and to adapt the full test accordingly by including the Nexus methods.
8
-
9
- ## Getting Started
10
-
11
- ### Installation
12
-
13
- #### Using npm:
14
-
15
- ```bash
16
- $ npm install @beblurt/blurt-nodes-checker --save
17
- ```
18
-
19
- #### Using browser:
20
-
21
- ```html
22
- <script type="module" src="./dist/blurt-nodes-checker.min.js"></script>
23
- ```
24
-
25
- #### From the source:
26
-
27
- clone the repository
28
-
29
- ```bash
30
- $ git clone https://gitlab.com/beblurt/blurt-nodes-checker.git
31
- ```
32
-
33
- Build for NodeJS/Angular... in `"./lib"` directory
34
-
35
- ```bash
36
- $ npm run build
37
- ```
38
-
39
- Build for browser (minified) in `"./dist"` directory
40
-
41
- ```bash
42
- $ npm run build-browser
43
- ```
44
-
45
- ### Initialisation
46
-
47
- Initialise the Blurt nodes checker with **params**
48
-
49
- ```js
50
- /** Init the checker */
51
- const nodesChecker = new BlurtNodesChecker(["url1", "url2", ...])
52
- ```
53
-
54
- ### Params
55
- - `url`: array of node url to check
56
- - `options` (optional):
57
- - `debug` (boolean): if true show console info (default: false)
58
- - `full` (boolean): if false perform only a `get_config` with response time (default: false)
59
- - `nexus` (boolean): if true check if the rpc node is [Nexus](https://gitlab.com/blurt/openblurt/nexus) compatible (default: true)
60
- - `interval` (seconds): delay in seconds between each execution (default: 900 seconds)
61
- - `timeout` (seconds): timeout in seconds for node request (default: 3 seconds)
62
- - `reset` (number): number max of test before resetting the counters (default: no reset)
63
-
64
- ### Functions
65
-
66
- #### start()
67
-
68
- Start the checking process
69
-
70
- ```js
71
- /** Start the checker */
72
- nodesChecker.start()
73
- ```
74
-
75
- #### restart()
76
-
77
- restart the checking process with the same **params**
78
-
79
- ```js
80
- /** Restart the checker */
81
- nodesChecker.restart()
82
- ```
83
-
84
- #### stop()
85
-
86
- stop the checking process
87
-
88
- ```js
89
- /** Stop the checker */
90
- nodesChecker.stop()
91
- ```
92
-
93
- ### Message subscription
94
-
95
- #### message.subscribe()
96
-
97
- It use RxJS to send the result of a check
98
-
99
- ```js
100
- /** Subscribe results */
101
- nodesChecker.message.subscribe({
102
- next: async m => {
103
- ...
104
- },
105
- error: error => {
106
- ...
107
- }
108
- })
109
- ```
110
-
111
- #### message.unsubscribe()
112
-
113
- Unsubscribe manually from the Observable
114
-
115
- ```js
116
- /** Unsubscribe results */
117
- nodesChecker.message.unsubscribe()
118
- })
119
- ```
120
-
121
- ### Example usage
122
-
123
- Performing a full checking:
124
-
125
- ```js
126
- import { BlurtNodesChecker } from '@beblurt/blurt-nodes-checker'
127
-
128
- /** Blurt nodes url to check */
129
- const nodes = [
130
- "https://rpc.beblurt.com",
131
- "https://blurt-rpc.saboin.com",
132
- "https://rpc.blurt.world",
133
- "https://blurtrpc.actifit.io",
134
- "https://kentzz.blurt.world",
135
- "https://rpc.blurt.live",
136
- "https://blurtdev.techcoderx.com"
137
- ]
138
-
139
- /** Options */
140
- const options = {
141
- full: true,
142
- nexus: true,
143
- interval: 600, // 10 minutes
144
- reset: 144 // every 144 tests => 24 hours x 6 (10 minutes = 6 test per hours)
145
- }
146
- /** Init the checker */
147
- const nodesChecker = new BlurtNodesChecker(nodes, options)
148
- /** Start the checker */
149
- nodesChecker.start()
150
- /** Subscribe results */
151
- nodesChecker.message.subscribe({
152
- next: async m => {
153
- console.log('=====> NEW MESSAGE', m)
154
- console.log()
155
- },
156
- error: error => {
157
- console.log('=====> ERROR MESSAGE')
158
- console.log(error)
159
- console.log()
160
-
161
- /** Restart the checker */
162
- nodesChecker.restart()
163
- }
164
- })
165
- ```
166
-
167
- ### Light checking
168
-
169
- In this case, only a call to the rpc method `condenser_api.get_config` is made, if `nexus: true` in options there is a call to the rpc method `bridge.unread_notifications` too to check if it's a Nexus rcp node.
170
-
171
- #### Result
172
- ```ts
173
- [{
174
- "url": string
175
- "nb_ok": number
176
- "nb_error": number
177
- "nb_degraded": number
178
- "error"?: string
179
- "last_check": number
180
- "status": "unkown"|"online"|"degraded"|"error"
181
- "duration"?: number
182
- "average_time"?: number
183
- "version"?: string
184
- "deactivated"?: boolean
185
- "nexus": boolean
186
-
187
- "test_result": []
188
- }]
189
- ```
190
-
191
- #### Exemple of result for a light checking
192
- ```js
193
- [
194
- {
195
- url: "https://rpc.beblurt.com",
196
- nb_ok: 1,
197
- nb_error: 0,
198
- nb_degraded: 0,
199
- last_check: 1669607084463,
200
- status: "online",
201
- test_result: [],
202
- version: "0.8.2",
203
- duration: 598,
204
- nexus: true
205
- },
206
- ...
207
- ]
208
- ```
209
-
210
- ### Full checking
211
-
212
- In this case the methods below are checked:
213
-
214
- - `condenser_api.get_config`
215
- - `condenser_api.get_account_history`
216
- - `condenser_api.get_accounts`
217
- - `condenser_api.get_block`
218
- - `condenser_api.get_blog_entries`
219
- - `condenser_api.get_content`
220
- - `condenser_api.get_dynamic_global_properties`
221
- - `condenser_api.get_discussions_by_blog`
222
- - `condenser_api.lookup_accounts`
223
-
224
- If it is a Nexus node the following methods are also checked:
225
-
226
- - `bridge.account_notifications`
227
- - `bridge.get_account_posts`
228
- - `bridge.get_discussion`
229
- - `bridge.get_payout_stats`
230
- - `bridge.get_profile`
231
- - `bridge.get_ranked_posts`
232
- - `bridge.list_communities`
233
-
234
- #### Result
235
- ```ts
236
- [{
237
- "url": string
238
- "nb_ok": number
239
- "nb_error": number
240
- "nb_degraded": number
241
- "error"?: string
242
- "last_check": number
243
- "status": "unkown"|"online"|"degraded"|"error"
244
- "duration"?: number
245
- "average_time"?: number
246
- "version"?: string
247
- "deactivated"?: boolean
248
-
249
- "test_result": [{
250
- "name": string
251
- "description": string
252
- "method": string
253
- "success": boolean
254
- "duration": number
255
- "error"?: string
256
- "last_check": number
257
- }]
258
- }]
259
- ```
260
-
261
- #### Exemple of result for a full checking
262
- ```js
263
- [
264
- {
265
- url: "https://rpc.beblurt.com",
266
- nb_ok: 1,
267
- nb_error: 0,
268
- nb_degraded: 0,
269
- last_check: 1669607748639,
270
- status: "online",
271
- test_result: [
272
- {
273
- name: "Bridge | account_notifications ",
274
- description: "Account notifications",
275
- method: "bridge.account_notifications",
276
- success: true,
277
- duration: 314,
278
- last_check: 1669607748639
279
- },
280
- ...
281
- {
282
- name: "Condenser | Get Disccusion By Blog",
283
- description: "Retrieve a list of discussions by blog",
284
- method: "condenser_api.get_discussions_by_blog",
285
- success: true,
286
- duration: 1181,
287
- last_check: 1669607748639
288
- }
289
- ],
290
- version: "0.8.2",
291
- duration: 579,
292
- nexus: true,
293
- average_time: 1140,
294
- },
295
- ...
296
- ]
297
- ```
298
-
299
- ## Contributing
300
-
301
- Pull requests for new features, bug fixes, and suggestions are welcome!
302
-
303
- ## Author
304
-
305
- @beblurt (https://beblurt.com/@beblurt)
306
-
307
- ## License
308
-
309
- Copyright (C) 2022 IMT ASE Co., LTD
310
-
311
- This program is free software: you can redistribute it and/or modify
312
- it under the terms of the GNU General Public License as published by
313
- the Free Software Foundation, either version 3 of the License, or
314
- (at your option) any later version.
315
-
316
- This program is distributed in the hope that it will be useful,
317
- but WITHOUT ANY WARRANTY; without even the implied warranty of
318
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
319
- GNU General Public License for more details.
320
-
321
- You should have received a copy of the GNU General Public License
322
- along with this program. If not, see <http://www.gnu.org/licenses/>.
1
+ # Blurt Nodes Checker
2
+
3
+ [![NPM version](https://img.shields.io/npm/v/@beblurt/blurt-nodes-checker.svg?style=flat-square)](https://www.npmjs.com/package/@beblurt/blurt-nodes-checker)
4
+ [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg?style=flat-square)](https://www.gnu.org/licenses/gpl-3.0)
5
+
6
+ A sophisticated, **0-dependency**, and **Isomorphic** utility to monitor, score, and rank RPC nodes on the Blurt Blockchain. Designed for production performance on Node.js and Modern Frontend Frameworks (React, Angular, Vue, Vite).
7
+
8
+ ## Features
9
+
10
+ - **Dependency Zero**: Entirely powered by standard APIs (`fetch`, `AbortController`). Zero bloating.
11
+ - **Isomorphic Support**: Runs natively in Node.js >= 18 and all modern browsers. Fully Tree-Shakable.
12
+ - **Micro-Subject Architecture**: Safely drop `rxjs` and Node `EventEmitter` without breaking the `.subscribe()` api flow.
13
+ - **Two-Phase Consensus Detection**: Calculates Median Head Block across the cluster and validates `block_ids` backward in time to guarantee **extremely robust fork detection with minimized false positives**.
14
+ - **Dynamic Scoring Matrix**: Ranks nodes (0-100 score) using historic latency averages, network fault degradations, success reliability, and stale-block penalties.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @beblurt/blurt-nodes-checker
20
+ ```
21
+
22
+ ## Getting Started
23
+
24
+ ```javascript
25
+ import { BlurtNodesChecker, createDefaultTests } from "@beblurt/blurt-nodes-checker";
26
+
27
+ const rpcList = [
28
+ 'https://rpc.blurt.blog',
29
+ 'https://blurt-rpc.saboin.com',
30
+ 'https://rpc.beblurt.com',
31
+ 'https://blurtrpc.dagobert.uk',
32
+ 'https://rpc.drakernoise.com'
33
+ ];
34
+
35
+ // 1. Initialize Checker
36
+ const checker = new BlurtNodesChecker(rpcList, {
37
+ interval: 15, // Check every 15 seconds
38
+ timeout: 4000, // Wait max 4 seconds before aborting calls
39
+ maxRetries: 2, // Exponential backoff network retries
40
+ retryDelay: 500, // Time between retries (ms)
41
+ staleThreshold: 50, // Node is "stale" if lagging 50 blocks behind consensus median
42
+ tests: createDefaultTests("beblurt") // Inject dynamic queries
43
+ });
44
+
45
+ // 2. Subscribe to matrix updates
46
+ checker.message.subscribe((nodes) => {
47
+ console.log("Cluster Top Node:", nodes[0].url, "Score:", nodes[0].score);
48
+
49
+ nodes.forEach(node => {
50
+ switch(node.status) {
51
+ case "online":
52
+ console.log(`✅ ${node.url} - Perfectly healthy (${node.score}/100)`);
53
+ break;
54
+ case "stale":
55
+ console.log(`⚠️ ${node.url} - Syncing slowly (${node.lag} blocks behind).`);
56
+ break;
57
+ case "forked":
58
+ console.log(`🚨 ${node.url} - Network Forked / Mismatched Block Identity!`);
59
+ break;
60
+ case "degraded":
61
+ console.log(`🧰 ${node.url} - Missing Critical Plugins!`);
62
+ break;
63
+ case "error":
64
+ console.log(`❌ ${node.url} - Unreachable!`);
65
+ break;
66
+ }
67
+ });
68
+ });
69
+
70
+ // 3. Begin monitoring
71
+ checker.start();
72
+ ```
73
+
74
+ ## Interactive Browser Dashboard
75
+
76
+ To view the absolute power of this tool without any Node.js backend dependencies, an incredibly detailed Glassmorphic dashboard is bundled!
77
+
78
+ Navigate to `examples/browser/index.html` within this repo (and serve it via any basic HTTP tool like `npx serve .`) to experience a live, flickering-free analytical dashboard dynamically coloring lag limits and modal validations directly over the Web.
79
+
80
+ ## The 0-100 Scoring Math
81
+
82
+ Our clustering matrix is scored on a normalized 0-100 spectrum allowing standard load balancers to automatically select the absolute healthiest node in real-time.
83
+
84
+ | Category | Description | Base Impact |
85
+ | -------- | ----------- | ----------- |
86
+ | **Health** | Basic Ok/Error response ratio | **40 points**
87
+ | **Tests** | Weight-scaled test completions | **30 points**
88
+ | **Latency**| Averaged responsiveness | **30 points**
89
+ | **Lag** | Mild penalty for lagging blocks | *- (0.5 * blocks lagged)* |
90
+ | **Degraded**| Node fails a `critical: true` test | *- 30 points* |
91
+ | **Stale** | Node has lag beyond `staleThreshold` | *- 50 points* |
92
+ | **Forked** | Node is confirmed on a false timeline | **Score Plummets to 0** |
93
+
94
+ ## Injecting Custom Checks
95
+
96
+ Instead of standard queries, pass custom JSON-RPC instructions straight to the constructor! Nodes will evaluate tests and reward points based on matching validations and `weights`.
97
+
98
+ ```javascript
99
+ const checker = new BlurtNodesChecker(myRpcList, {
100
+ tests: [
101
+ {
102
+ name: "Get Global Properties",
103
+ method: "condenser_api.get_dynamic_global_properties",
104
+ params: [],
105
+ weight: 10,
106
+ critical: true, // If this fails, the node status changes to DEGRADED
107
+ validator: (result) => result && result.head_block_number !== undefined
108
+ }
109
+ ]
110
+ })
111
+ ```
@@ -0,0 +1,21 @@
1
+ import { Subject } from "./subject.js";
2
+ import { OPTIONS, RPC_NODE, FULL_TEST } from "./types.js";
3
+ export { createDefaultTests } from "./test.js";
4
+ export * from "./types.js";
5
+ export declare class BlurtNodesChecker {
6
+ nodes: RPC_NODE[];
7
+ message: Subject<RPC_NODE[]>;
8
+ private timer;
9
+ debug: boolean;
10
+ interval: number;
11
+ timeout: number;
12
+ maxRetries: number;
13
+ retryDelay: number;
14
+ staleThreshold: number;
15
+ tests: FULL_TEST[];
16
+ constructor(nodes: string[], options?: OPTIONS);
17
+ start(): Promise<void>;
18
+ stop(): void;
19
+ restart(): void;
20
+ private check;
21
+ }