hive-stream 2.0.3 → 2.0.6
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/.env.example +3 -2
- package/.travis.yml +11 -11
- package/LICENSE +21 -21
- package/README.md +238 -236
- package/dist/actions.d.ts +10 -9
- package/dist/actions.js +23 -15
- package/dist/actions.js.map +1 -1
- package/dist/adapters/base.adapter.d.ts +25 -21
- package/dist/adapters/base.adapter.js +49 -63
- package/dist/adapters/base.adapter.js.map +1 -1
- package/dist/adapters/mongodb.adapter.d.ts +37 -29
- package/dist/adapters/mongodb.adapter.js +158 -113
- package/dist/adapters/mongodb.adapter.js.map +1 -1
- package/dist/adapters/sqlite.adapter.d.ts +41 -23
- package/dist/adapters/sqlite.adapter.js +397 -121
- package/dist/adapters/sqlite.adapter.js.map +1 -1
- package/dist/api.d.ts +6 -0
- package/dist/api.js +56 -0
- package/dist/api.js.map +1 -0
- package/dist/config.d.ts +16 -14
- package/dist/config.js +18 -15
- package/dist/config.js.map +1 -1
- package/dist/contracts/coinflip.contract.d.ts +14 -0
- package/dist/contracts/coinflip.contract.js +95 -0
- package/dist/contracts/coinflip.contract.js.map +1 -0
- package/dist/contracts/dice.contract.d.ts +29 -29
- package/dist/contracts/dice.contract.js +155 -157
- package/dist/contracts/dice.contract.js.map +1 -1
- package/dist/contracts/lotto.contract.d.ts +20 -16
- package/dist/contracts/lotto.contract.js +246 -107
- package/dist/contracts/lotto.contract.js.map +1 -1
- package/dist/exchanges/bittrex.d.ts +6 -0
- package/dist/exchanges/bittrex.js +35 -0
- package/dist/exchanges/bittrex.js.map +1 -0
- package/dist/exchanges/exchange.d.ts +9 -0
- package/dist/exchanges/exchange.js +27 -0
- package/dist/exchanges/exchange.js.map +1 -0
- package/dist/hive-rates.d.ts +9 -0
- package/dist/hive-rates.js +76 -0
- package/dist/hive-rates.js.map +1 -0
- package/dist/index.d.ts +11 -10
- package/dist/index.js +32 -15
- package/dist/index.js.map +1 -1
- package/dist/streamer.d.ts +93 -70
- package/dist/streamer.js +545 -439
- package/dist/streamer.js.map +1 -1
- package/dist/test.d.ts +1 -1
- package/dist/test.js +25 -27
- package/dist/test.js.map +1 -1
- package/dist/types/hive-stream.d.ts +6 -6
- package/dist/types/hive-stream.js +2 -2
- package/dist/utils.d.ts +27 -14
- package/dist/utils.js +261 -85
- package/dist/utils.js.map +1 -1
- package/ecosystem.config.js +17 -17
- package/jest.config.js +8 -13
- package/package.json +48 -44
- package/test-contract-block.md +18 -18
- package/tests/adapters/sqlite.adapter.spec.ts +43 -0
- package/tests/contracts/coinflip.contract.spec.ts +132 -0
- package/tests/contracts/dice.contract.spec.ts +159 -156
- package/tests/contracts/entrants.json +728 -728
- package/tests/contracts/lotto.contract.spec.ts +323 -372
- package/tests/setup.ts +18 -20
- package/tests/streamer.spec.ts +151 -151
- package/tests/utils.spec.ts +94 -99
- package/tsconfig.build.json +22 -20
- package/tslint.json +20 -20
- package/wallaby.js +26 -0
- package/.env +0 -1
- package/dist/adapters/file.adapter.d.ts +0 -8
- package/dist/adapters/file.adapter.js +0 -70
- package/dist/adapters/file.adapter.js.map +0 -1
- package/dist/test/setup.d.ts +0 -0
- package/dist/test/setup.js +0 -9
- package/dist/test/setup.js.map +0 -1
- package/dist/test/streamer.spec.d.ts +0 -1
- package/dist/test/streamer.spec.js +0 -145
- package/dist/test/streamer.spec.js.map +0 -1
- package/dist/test/utils.spec.d.ts +0 -1
- package/dist/test/utils.spec.js +0 -11
- package/dist/test/utils.spec.js.map +0 -1
- package/dist/tests/contracts/dice.contract.spec.d.ts +0 -1
- package/dist/tests/contracts/dice.contract.spec.js +0 -130
- package/dist/tests/contracts/dice.contract.spec.js.map +0 -1
- package/dist/tests/contracts/entrants.json +0 -729
- package/dist/tests/contracts/lotto.contract.spec.d.ts +0 -1
- package/dist/tests/contracts/lotto.contract.spec.js +0 -300
- package/dist/tests/contracts/lotto.contract.spec.js.map +0 -1
- package/dist/tests/setup.d.ts +0 -1
- package/dist/tests/setup.js +0 -19
- package/dist/tests/setup.js.map +0 -1
- package/dist/tests/streamer.spec.d.ts +0 -1
- package/dist/tests/streamer.spec.js +0 -123
- package/dist/tests/streamer.spec.js.map +0 -1
- package/dist/tests/utils.spec.d.ts +0 -1
- package/dist/tests/utils.spec.js +0 -87
- package/dist/tests/utils.spec.js.map +0 -1
- package/hive-stream.json +0 -1
package/dist/streamer.js
CHANGED
|
@@ -1,440 +1,546 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
this.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
this.
|
|
104
|
-
return this;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
*
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
if (this.
|
|
206
|
-
this.
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
this.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if (
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
//
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
if (
|
|
327
|
-
contract.contract
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
}
|
|
439
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Streamer = void 0;
|
|
7
|
+
const api_1 = require("./api");
|
|
8
|
+
const sqlite_adapter_1 = require("./adapters/sqlite.adapter");
|
|
9
|
+
const utils_1 = require("@hiveio/dhive/lib/utils");
|
|
10
|
+
const actions_1 = require("./actions");
|
|
11
|
+
const dhive_1 = require("@hiveio/dhive");
|
|
12
|
+
const utils_2 = require("./utils");
|
|
13
|
+
const config_1 = require("./config");
|
|
14
|
+
const moment_1 = __importDefault(require("moment"));
|
|
15
|
+
const sscjs_1 = __importDefault(require("sscjs"));
|
|
16
|
+
class Streamer {
|
|
17
|
+
customJsonSubscriptions = [];
|
|
18
|
+
customJsonIdSubscriptions = [];
|
|
19
|
+
customJsonHiveEngineSubscriptions = [];
|
|
20
|
+
commentSubscriptions = [];
|
|
21
|
+
postSubscriptions = [];
|
|
22
|
+
transferSubscriptions = [];
|
|
23
|
+
attempts = 0;
|
|
24
|
+
config = config_1.Config;
|
|
25
|
+
client;
|
|
26
|
+
hive;
|
|
27
|
+
username;
|
|
28
|
+
postingKey;
|
|
29
|
+
activeKey;
|
|
30
|
+
blockNumberTimeout = null;
|
|
31
|
+
latestBlockTimer = null;
|
|
32
|
+
lastBlockNumber = 0;
|
|
33
|
+
blockId;
|
|
34
|
+
previousBlockId;
|
|
35
|
+
transactionId;
|
|
36
|
+
blockTime;
|
|
37
|
+
latestBlockchainTime;
|
|
38
|
+
disableAllProcessing = false;
|
|
39
|
+
contracts = [];
|
|
40
|
+
adapter;
|
|
41
|
+
actions = [];
|
|
42
|
+
utils = utils_2.Utils;
|
|
43
|
+
constructor(userConfig = {}) {
|
|
44
|
+
this.config = Object.assign(config_1.Config, userConfig);
|
|
45
|
+
this.lastBlockNumber = this.config.LAST_BLOCK_NUMBER;
|
|
46
|
+
this.username = this.config.USERNAME;
|
|
47
|
+
this.postingKey = this.config.POSTING_KEY;
|
|
48
|
+
this.activeKey = this.config.ACTIVE_KEY;
|
|
49
|
+
this.hive = new sscjs_1.default(this.config.HIVE_ENGINE_API);
|
|
50
|
+
this.client = new dhive_1.Client(this.config.API_NODES);
|
|
51
|
+
this.registerAdapter(new sqlite_adapter_1.SqliteAdapter());
|
|
52
|
+
if (process?.env?.NODE_ENV !== 'test') {
|
|
53
|
+
new api_1.Api(this);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
registerAdapter(adapter) {
|
|
57
|
+
this.adapter = adapter;
|
|
58
|
+
if (this?.adapter?.create) {
|
|
59
|
+
this.adapter.create();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
getAdapter() {
|
|
63
|
+
return this.adapter;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Register a new action
|
|
67
|
+
*
|
|
68
|
+
*/
|
|
69
|
+
async registerAction(action) {
|
|
70
|
+
const loadedActions = await this.adapter.loadActions();
|
|
71
|
+
for (const a of loadedActions) {
|
|
72
|
+
const exists = this.actions.find(i => i.id === a.id);
|
|
73
|
+
if (!exists) {
|
|
74
|
+
this.actions.push(new actions_1.TimeAction(a.timeValue, a.id, a.contractName, a.contractMethod, a.date));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const exists = this.actions.find(a => a.id === action.id);
|
|
78
|
+
if (!exists) {
|
|
79
|
+
this.actions.push(action);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resets a specific action time value
|
|
84
|
+
*
|
|
85
|
+
* @param id
|
|
86
|
+
*
|
|
87
|
+
*/
|
|
88
|
+
resetAction(id) {
|
|
89
|
+
const action = this.actions.find(i => i.id === id);
|
|
90
|
+
if (action) {
|
|
91
|
+
action.reset();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
registerContract(name, contract) {
|
|
95
|
+
// Store an instance of the streamer
|
|
96
|
+
contract['_instance'] = this;
|
|
97
|
+
// Call the contract create lifecycle method if it exists
|
|
98
|
+
if (contract && typeof contract['create'] !== 'undefined') {
|
|
99
|
+
contract.create();
|
|
100
|
+
}
|
|
101
|
+
const storedReference = { name, contract };
|
|
102
|
+
// Push the contract reference to be called later on
|
|
103
|
+
this.contracts.push(storedReference);
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
unregisterContract(name) {
|
|
107
|
+
// Find the registered contract by it's ID
|
|
108
|
+
const contractIndex = this.contracts.findIndex(c => c.name === name);
|
|
109
|
+
if (contractIndex >= 0) {
|
|
110
|
+
// Get the contract itself
|
|
111
|
+
const contract = this.contracts.find(c => c.name === name);
|
|
112
|
+
// Call the contract destroy lifecycle method if it exists
|
|
113
|
+
if (contract && typeof contract.contract['destroy'] !== 'undefined') {
|
|
114
|
+
contract.contract.destroy();
|
|
115
|
+
}
|
|
116
|
+
// Remove the contract
|
|
117
|
+
this.contracts.splice(contractIndex, 1);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* setConfig
|
|
122
|
+
*
|
|
123
|
+
* Allows specific configuration settings to be overridden
|
|
124
|
+
*
|
|
125
|
+
* @param config
|
|
126
|
+
*/
|
|
127
|
+
setConfig(config) {
|
|
128
|
+
Object.assign(this.config, config);
|
|
129
|
+
// Set keys and username incase they have changed
|
|
130
|
+
this.username = this.config.USERNAME;
|
|
131
|
+
this.postingKey = this.config.POSTING_KEY;
|
|
132
|
+
this.activeKey = this.config.ACTIVE_KEY;
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Start
|
|
137
|
+
*
|
|
138
|
+
* Starts the streamer bot to get blocks from the Hive API
|
|
139
|
+
*
|
|
140
|
+
*/
|
|
141
|
+
async start() {
|
|
142
|
+
if (this.config.DEBUG_MODE) {
|
|
143
|
+
console.log('Starting to stream the Hive blockchain');
|
|
144
|
+
}
|
|
145
|
+
this.disableAllProcessing = false;
|
|
146
|
+
const state = await this.adapter.loadState();
|
|
147
|
+
if (this.config.DEBUG_MODE) {
|
|
148
|
+
console.log(`Restoring state from file`);
|
|
149
|
+
}
|
|
150
|
+
if (!this.config.LAST_BLOCK_NUMBER && state?.lastBlockNumber) {
|
|
151
|
+
if (state.lastBlockNumber) {
|
|
152
|
+
this.lastBlockNumber = state.lastBlockNumber;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Kicks off the blockchain streaming and operation parsing
|
|
156
|
+
this.getBlock();
|
|
157
|
+
this.latestBlockTimer = setInterval(() => { this.getLatestBlock(); }, this.config.BLOCK_CHECK_INTERVAL);
|
|
158
|
+
return this;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Stop
|
|
162
|
+
*
|
|
163
|
+
* Stops the streamer from running
|
|
164
|
+
*/
|
|
165
|
+
async stop() {
|
|
166
|
+
this.disableAllProcessing = true;
|
|
167
|
+
if (this.blockNumberTimeout) {
|
|
168
|
+
clearTimeout(this.blockNumberTimeout);
|
|
169
|
+
}
|
|
170
|
+
if (this.latestBlockTimer) {
|
|
171
|
+
clearInterval(this.latestBlockTimer);
|
|
172
|
+
}
|
|
173
|
+
if (this?.adapter?.destroy) {
|
|
174
|
+
this.adapter.destroy();
|
|
175
|
+
}
|
|
176
|
+
await (0, utils_1.sleep)(800);
|
|
177
|
+
}
|
|
178
|
+
async getLatestBlock() {
|
|
179
|
+
const props = await this.client.database.getDynamicGlobalProperties();
|
|
180
|
+
if (props) {
|
|
181
|
+
this.latestBlockchainTime = new Date(`${props.time}Z`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async getBlock() {
|
|
185
|
+
try {
|
|
186
|
+
// Load global properties from the Hive API
|
|
187
|
+
const props = await this.client.database.getDynamicGlobalProperties();
|
|
188
|
+
// We have no props, so try loading them again.
|
|
189
|
+
if (!props && !this.disableAllProcessing) {
|
|
190
|
+
this.blockNumberTimeout = setTimeout(() => {
|
|
191
|
+
this.getBlock();
|
|
192
|
+
}, this.config.BLOCK_CHECK_INTERVAL);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
// If the block number we've got is zero
|
|
196
|
+
// set it to the last irreversible block number
|
|
197
|
+
if (this.lastBlockNumber === 0) {
|
|
198
|
+
this.lastBlockNumber = props.head_block_number - 1;
|
|
199
|
+
}
|
|
200
|
+
if (this.config.DEBUG_MODE) {
|
|
201
|
+
console.log(`Head block number: `, props.head_block_number);
|
|
202
|
+
console.log(`Last block number: `, this.lastBlockNumber);
|
|
203
|
+
}
|
|
204
|
+
const BLOCKS_BEHIND = parseInt(this.config.BLOCKS_BEHIND_WARNING, 10);
|
|
205
|
+
if (!this.disableAllProcessing) {
|
|
206
|
+
await this.loadBlock(this.lastBlockNumber + 1);
|
|
207
|
+
}
|
|
208
|
+
// We are more than 25 blocks behind, uh oh, we gotta catch up
|
|
209
|
+
if (props.head_block_number >= (this.lastBlockNumber + BLOCKS_BEHIND) && this.config.DEBUG_MODE) {
|
|
210
|
+
console.log(`We are more than ${BLOCKS_BEHIND} blocks behind ${props.head_block_number}, ${(this.lastBlockNumber + BLOCKS_BEHIND)}`);
|
|
211
|
+
if (!this.disableAllProcessing) {
|
|
212
|
+
this.getBlock();
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Storing timeout allows us to clear it, as this just calls itself
|
|
217
|
+
if (!this.disableAllProcessing) {
|
|
218
|
+
this.blockNumberTimeout = setTimeout(() => { this.getBlock(); }, this.config.BLOCK_CHECK_INTERVAL);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
const message = e.message.toLowerCase();
|
|
223
|
+
console.error(message);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Takes the block from Hive and allows us to work with it
|
|
227
|
+
async loadBlock(blockNumber) {
|
|
228
|
+
// Load the block itself from the Hive API
|
|
229
|
+
const block = await this.client.database.getBlock(blockNumber);
|
|
230
|
+
// The block doesn't exist, wait and try again
|
|
231
|
+
if (!block) {
|
|
232
|
+
await utils_2.Utils.sleep(this.config.BLOCK_CHECK_INTERVAL);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
// Get the block date and time
|
|
236
|
+
const blockTime = new Date(`${block.timestamp}Z`);
|
|
237
|
+
if (this.lastBlockNumber !== blockNumber) {
|
|
238
|
+
this.processActions();
|
|
239
|
+
}
|
|
240
|
+
this.blockId = block.block_id;
|
|
241
|
+
this.previousBlockId = block.previous;
|
|
242
|
+
this.transactionId = block.transaction_ids[1];
|
|
243
|
+
this.blockTime = blockTime;
|
|
244
|
+
if (this.adapter?.processBlock) {
|
|
245
|
+
this.adapter.processBlock(block);
|
|
246
|
+
}
|
|
247
|
+
// Loop over all transactions in the block
|
|
248
|
+
for (const [i, transaction] of Object.entries(block.transactions)) {
|
|
249
|
+
// Loop over operations in the block
|
|
250
|
+
for (const [opIndex, op] of Object.entries(transaction.operations)) {
|
|
251
|
+
// For every operation, process it
|
|
252
|
+
await this.processOperation(op, blockNumber, block.block_id, block.previous, block.transaction_ids[i], blockTime);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
this.lastBlockNumber = blockNumber;
|
|
256
|
+
this.saveStateToDisk();
|
|
257
|
+
}
|
|
258
|
+
processOperation(op, blockNumber, blockId, prevBlockId, trxId, blockTime) {
|
|
259
|
+
if (this.adapter?.processOperation) {
|
|
260
|
+
this.adapter.processOperation(op, blockNumber, blockId, prevBlockId, trxId, blockTime);
|
|
261
|
+
}
|
|
262
|
+
// Operation is a "comment" which could either be a post or comment
|
|
263
|
+
if (op[0] === 'comment') {
|
|
264
|
+
// This is a post
|
|
265
|
+
if (op[1].parent_author === '') {
|
|
266
|
+
this.postSubscriptions.forEach(sub => {
|
|
267
|
+
sub.callback(op[1], blockNumber, blockId, prevBlockId, trxId, blockTime);
|
|
268
|
+
});
|
|
269
|
+
// This is a comment
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
this.commentSubscriptions.forEach(sub => {
|
|
273
|
+
sub.callback(op[1], blockNumber, blockId, prevBlockId, trxId, blockTime);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// This is a transfer
|
|
278
|
+
if (op[0] === 'transfer') {
|
|
279
|
+
const sender = op[1]?.from;
|
|
280
|
+
const amount = op[1]?.amount;
|
|
281
|
+
const json = utils_2.Utils.jsonParse(op[1].memo);
|
|
282
|
+
if (json?.[this.config.PAYLOAD_IDENTIFIER] && json?.[this.config.PAYLOAD_IDENTIFIER]?.id === this.config.JSON_ID) {
|
|
283
|
+
// Pull out details of contract
|
|
284
|
+
const { name, action, payload } = json[this.config.PAYLOAD_IDENTIFIER];
|
|
285
|
+
// Do we have a contract that matches the name in the payload?
|
|
286
|
+
const contract = this.contracts.find(c => c.name === name);
|
|
287
|
+
if (contract) {
|
|
288
|
+
if (this?.adapter?.processTransfer) {
|
|
289
|
+
this.adapter.processTransfer(op[1], { name, action, payload }, { sender, amount });
|
|
290
|
+
}
|
|
291
|
+
if (contract?.contract?.updateBlockInfo) {
|
|
292
|
+
contract.contract.updateBlockInfo(blockNumber, blockId, prevBlockId, trxId);
|
|
293
|
+
}
|
|
294
|
+
if (contract?.contract[action]) {
|
|
295
|
+
contract.contract[action](payload, { sender, amount });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
this.transferSubscriptions.forEach(sub => {
|
|
300
|
+
if (sub.account === op[1].to) {
|
|
301
|
+
sub.callback(op[1], blockNumber, blockId, prevBlockId, trxId, blockTime);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
// This is a custom JSON operation
|
|
306
|
+
if (op[0] === 'custom_json') {
|
|
307
|
+
let isSignedWithActiveKey = false;
|
|
308
|
+
let sender;
|
|
309
|
+
const id = op[1]?.id;
|
|
310
|
+
if (op[1]?.required_auths?.length > 0) {
|
|
311
|
+
sender = op[1].required_auths[0];
|
|
312
|
+
isSignedWithActiveKey = true;
|
|
313
|
+
}
|
|
314
|
+
else if (op[1]?.required_posting_auths?.length > 0) {
|
|
315
|
+
sender = op[1].required_posting_auths[0];
|
|
316
|
+
isSignedWithActiveKey = false;
|
|
317
|
+
}
|
|
318
|
+
const json = utils_2.Utils.jsonParse(op[1].json);
|
|
319
|
+
if (json && json?.[this.config.PAYLOAD_IDENTIFIER] && id === this.config.JSON_ID) {
|
|
320
|
+
// Pull out details of contract
|
|
321
|
+
const { name, action, payload } = json[this.config.PAYLOAD_IDENTIFIER];
|
|
322
|
+
// Do we have a contract that matches the name in the payload?
|
|
323
|
+
const contract = this.contracts.find(c => c.name === name);
|
|
324
|
+
if (contract) {
|
|
325
|
+
this.adapter.processCustomJson(op[1], { name, action, payload }, { sender, isSignedWithActiveKey });
|
|
326
|
+
if (contract?.contract?.updateBlockInfo) {
|
|
327
|
+
contract.contract.updateBlockInfo(blockNumber, blockId, prevBlockId, trxId);
|
|
328
|
+
}
|
|
329
|
+
if (contract?.contract[action]) {
|
|
330
|
+
contract.contract[action](payload, { sender, isSignedWithActiveKey }, id);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
this.customJsonSubscriptions.forEach(sub => {
|
|
335
|
+
sub.callback(op[1], { sender, isSignedWithActiveKey }, blockNumber, blockId, prevBlockId, trxId, blockTime);
|
|
336
|
+
});
|
|
337
|
+
this.customJsonIdSubscriptions.forEach(sub => {
|
|
338
|
+
const byId = this.customJsonIdSubscriptions.find(s => s.id === op[1].id);
|
|
339
|
+
if (byId) {
|
|
340
|
+
sub.callback(op[1], { sender, isSignedWithActiveKey }, blockNumber, blockId, prevBlockId, trxId, blockTime);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
utils_2.Utils.asyncForEach(this.customJsonHiveEngineSubscriptions, async (sub) => {
|
|
344
|
+
let isSignedWithActiveKey = null;
|
|
345
|
+
let sender;
|
|
346
|
+
if (op[1].required_auths.length > 0) {
|
|
347
|
+
sender = op[1].required_auths[0];
|
|
348
|
+
isSignedWithActiveKey = true;
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
sender = op[1].required_posting_auths[0];
|
|
352
|
+
isSignedWithActiveKey = false;
|
|
353
|
+
}
|
|
354
|
+
const id = op[1].id;
|
|
355
|
+
const json = utils_2.Utils.jsonParse(op[1].json);
|
|
356
|
+
// Hive Engine JSON operation
|
|
357
|
+
if (id === this.config.HIVE_ENGINE_ID) {
|
|
358
|
+
const { contractName, contractAction, contractPayload } = json;
|
|
359
|
+
try {
|
|
360
|
+
// Attempt to get the transaction from Hive Engine itself
|
|
361
|
+
const txInfo = await this.hive.getTransactionInfo(trxId);
|
|
362
|
+
const logs = txInfo && txInfo.logs ? utils_2.Utils.jsonParse(txInfo.logs) : null;
|
|
363
|
+
// Do we have a valid transaction and are there no errors? It's a real transaction
|
|
364
|
+
if (txInfo && logs && typeof logs.errors === 'undefined') {
|
|
365
|
+
sub.callback(contractName, contractAction, contractPayload, sender, op[1], blockNumber, blockId, prevBlockId, trxId, blockTime);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
catch (e) {
|
|
369
|
+
console.error(e);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
processActions() {
|
|
377
|
+
const blockDate = moment_1.default.utc(this.latestBlockchainTime);
|
|
378
|
+
for (const action of this.actions) {
|
|
379
|
+
const date = moment_1.default.utc(action.date);
|
|
380
|
+
const frequency = action.timeValue;
|
|
381
|
+
const contract = this.contracts.find(c => c.name === action.contractName);
|
|
382
|
+
// Contract doesn't exist or action doesn't exist, carry on
|
|
383
|
+
if (!contract || !contract?.contract?.[action.contractMethod]) {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
let difference = 0;
|
|
387
|
+
switch (frequency) {
|
|
388
|
+
case '3s':
|
|
389
|
+
case 'block':
|
|
390
|
+
difference = date.diff(blockDate, 's');
|
|
391
|
+
// 3 seconds or more has passed
|
|
392
|
+
if (difference >= 3) {
|
|
393
|
+
contract.contract[action.contractMethod](action.payload);
|
|
394
|
+
action.reset();
|
|
395
|
+
}
|
|
396
|
+
break;
|
|
397
|
+
case '10s':
|
|
398
|
+
difference = blockDate.diff(date, 's');
|
|
399
|
+
// 10 seconds or more has passed
|
|
400
|
+
if (difference >= 10) {
|
|
401
|
+
contract.contract[action.contractMethod](action.payload);
|
|
402
|
+
action.reset();
|
|
403
|
+
}
|
|
404
|
+
break;
|
|
405
|
+
case '30s':
|
|
406
|
+
difference = blockDate.diff(date, 's');
|
|
407
|
+
// 30 seconds or more has passed
|
|
408
|
+
if (difference >= 30) {
|
|
409
|
+
contract.contract[action.contractMethod](action.payload);
|
|
410
|
+
action.reset();
|
|
411
|
+
}
|
|
412
|
+
break;
|
|
413
|
+
case '1m':
|
|
414
|
+
case 'minute':
|
|
415
|
+
difference = blockDate.diff(date, 'm');
|
|
416
|
+
// One minute has passed
|
|
417
|
+
if (difference >= 1) {
|
|
418
|
+
contract.contract[action.contractMethod](action.payload);
|
|
419
|
+
action.reset();
|
|
420
|
+
}
|
|
421
|
+
break;
|
|
422
|
+
case '15m':
|
|
423
|
+
case 'quarter':
|
|
424
|
+
difference = blockDate.diff(date, 'm');
|
|
425
|
+
// 15 minutes has passed
|
|
426
|
+
if (difference >= 15) {
|
|
427
|
+
contract.contract[action.contractMethod](action.payload);
|
|
428
|
+
action.reset();
|
|
429
|
+
}
|
|
430
|
+
break;
|
|
431
|
+
case '30m':
|
|
432
|
+
case 'halfhour':
|
|
433
|
+
difference = blockDate.diff(date, 'm');
|
|
434
|
+
// 30 minutes has passed
|
|
435
|
+
if (difference >= 30) {
|
|
436
|
+
contract.contract[action.contractMethod](action.payload);
|
|
437
|
+
action.reset();
|
|
438
|
+
}
|
|
439
|
+
break;
|
|
440
|
+
case 'hourly':
|
|
441
|
+
case '1h':
|
|
442
|
+
difference = blockDate.diff(date, 'h');
|
|
443
|
+
// One our or more has passed
|
|
444
|
+
if (difference >= 1) {
|
|
445
|
+
contract.contract[action.contractMethod](action.payload);
|
|
446
|
+
action.reset();
|
|
447
|
+
}
|
|
448
|
+
break;
|
|
449
|
+
case '12h':
|
|
450
|
+
case 'halfday':
|
|
451
|
+
difference = blockDate.diff(date, 'h');
|
|
452
|
+
// Twelve hours or more has passed
|
|
453
|
+
if (difference >= 12) {
|
|
454
|
+
contract.contract[action.contractMethod](action.payload);
|
|
455
|
+
action.reset();
|
|
456
|
+
}
|
|
457
|
+
break;
|
|
458
|
+
case '24h':
|
|
459
|
+
case 'day':
|
|
460
|
+
difference = blockDate.diff(date, 'd');
|
|
461
|
+
// One day (24 hours) has passed
|
|
462
|
+
if (difference >= 1) {
|
|
463
|
+
contract.contract[action.contractMethod](action.payload);
|
|
464
|
+
action.reset();
|
|
465
|
+
}
|
|
466
|
+
break;
|
|
467
|
+
case 'week':
|
|
468
|
+
difference = blockDate.diff(date, 'w');
|
|
469
|
+
// One week has passed
|
|
470
|
+
if (difference >= 1) {
|
|
471
|
+
contract.contract[action.contractMethod](action.payload);
|
|
472
|
+
action.reset();
|
|
473
|
+
}
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
async saveStateToDisk() {
|
|
479
|
+
if (this.adapter?.saveState) {
|
|
480
|
+
this.adapter.saveState({ lastBlockNumber: this.lastBlockNumber, actions: this.actions });
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
saveToHiveApi(from, data) {
|
|
484
|
+
return utils_2.Utils.transferHiveTokens(this.client, this.config, from, 'hiveapi', '0.001', 'HIVE', data);
|
|
485
|
+
}
|
|
486
|
+
getAccountTransfers(account, from = -1, limit = 100) {
|
|
487
|
+
return utils_2.Utils.getAccountTransfers(this.client, account, from, limit);
|
|
488
|
+
}
|
|
489
|
+
transferHiveTokens(from, to, amount, symbol, memo = '') {
|
|
490
|
+
return utils_2.Utils.transferHiveTokens(this.client, this.config, from, to, amount, symbol, memo);
|
|
491
|
+
}
|
|
492
|
+
transferHiveTokensMultiple(from, accounts = [], amount = '0', symbol, memo = '') {
|
|
493
|
+
return utils_2.Utils.transferHiveTokensMultiple(this.client, this.config, from, accounts, amount, symbol, memo);
|
|
494
|
+
}
|
|
495
|
+
transferHiveEngineTokens(from, to, symbol, quantity, memo = '') {
|
|
496
|
+
return utils_2.Utils.transferHiveEngineTokens(this.client, this.config, from, to, symbol, quantity, memo);
|
|
497
|
+
}
|
|
498
|
+
transferHiveEngineTokensMultiple(from, accounts = [], symbol, memo = '', amount = '0') {
|
|
499
|
+
return utils_2.Utils.transferHiveEngineTokensMultiple(this.client, this.config, from, accounts, symbol, memo, amount);
|
|
500
|
+
}
|
|
501
|
+
issueHiveEngineTokens(from, to, symbol, quantity, memo = '') {
|
|
502
|
+
return utils_2.Utils.issueHiveEngineTokens(this.client, this.config, from, to, symbol, quantity, memo);
|
|
503
|
+
}
|
|
504
|
+
issueHiveEngineTokensMultiple(from, accounts = [], symbol, memo = '', amount = '0') {
|
|
505
|
+
return utils_2.Utils.issueHiveEngineTokensMultiple(this.client, this.config, from, accounts, symbol, memo, amount);
|
|
506
|
+
}
|
|
507
|
+
upvote(votePercentage = '100.0', username, permlink) {
|
|
508
|
+
return utils_2.Utils.upvote(this.client, this.config, this.username, votePercentage, username, permlink);
|
|
509
|
+
}
|
|
510
|
+
downvote(votePercentage = '100.0', username, permlink) {
|
|
511
|
+
return utils_2.Utils.downvote(this.client, this.config, this.username, votePercentage, username, permlink);
|
|
512
|
+
}
|
|
513
|
+
getTransaction(blockNumber, transactionId) {
|
|
514
|
+
return utils_2.Utils.getTransaction(this.client, blockNumber, transactionId);
|
|
515
|
+
}
|
|
516
|
+
verifyTransfer(transaction, from, to, amount) {
|
|
517
|
+
return utils_2.Utils.verifyTransfer(transaction, from, to, amount);
|
|
518
|
+
}
|
|
519
|
+
onComment(callback) {
|
|
520
|
+
this.commentSubscriptions.push({
|
|
521
|
+
callback
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
onPost(callback) {
|
|
525
|
+
this.postSubscriptions.push({
|
|
526
|
+
callback
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
onTransfer(account, callback) {
|
|
530
|
+
this.transferSubscriptions.push({
|
|
531
|
+
account,
|
|
532
|
+
callback
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
onCustomJson(callback) {
|
|
536
|
+
this.customJsonSubscriptions.push({ callback });
|
|
537
|
+
}
|
|
538
|
+
onCustomJsonId(callback, id) {
|
|
539
|
+
this.customJsonIdSubscriptions.push({ callback, id });
|
|
540
|
+
}
|
|
541
|
+
onHiveEngine(callback) {
|
|
542
|
+
this.customJsonHiveEngineSubscriptions.push({ callback });
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
exports.Streamer = Streamer;
|
|
440
546
|
//# sourceMappingURL=streamer.js.map
|