hive-stream 2.0.6 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.env.example +2 -2
  3. package/.travis.yml +11 -11
  4. package/AGENTS.md +35 -0
  5. package/CHANGELOG.md +166 -0
  6. package/CLAUDE.md +75 -0
  7. package/DOCUMENTATION.md +380 -0
  8. package/LICENSE +21 -21
  9. package/README.md +429 -238
  10. package/dist/actions.d.ts +41 -10
  11. package/dist/actions.js +126 -23
  12. package/dist/actions.js.map +1 -1
  13. package/dist/adapters/base.adapter.d.ts +43 -25
  14. package/dist/adapters/base.adapter.js +79 -49
  15. package/dist/adapters/base.adapter.js.map +1 -1
  16. package/dist/adapters/mongodb.adapter.d.ts +44 -37
  17. package/dist/adapters/mongodb.adapter.js +363 -158
  18. package/dist/adapters/mongodb.adapter.js.map +1 -1
  19. package/dist/adapters/postgresql.adapter.d.ts +66 -0
  20. package/dist/adapters/postgresql.adapter.js +598 -0
  21. package/dist/adapters/postgresql.adapter.js.map +1 -0
  22. package/dist/adapters/sqlite.adapter.d.ts +57 -41
  23. package/dist/adapters/sqlite.adapter.js +561 -397
  24. package/dist/adapters/sqlite.adapter.js.map +1 -1
  25. package/dist/api.d.ts +6 -6
  26. package/dist/api.js +181 -55
  27. package/dist/api.js.map +1 -1
  28. package/dist/config.d.ts +19 -16
  29. package/dist/config.js +21 -18
  30. package/dist/config.js.map +1 -1
  31. package/dist/contracts/coinflip.contract.d.ts +9 -14
  32. package/dist/contracts/coinflip.contract.js +232 -94
  33. package/dist/contracts/coinflip.contract.js.map +1 -1
  34. package/dist/contracts/contract.d.ts +3 -0
  35. package/dist/contracts/contract.js +26 -0
  36. package/dist/contracts/contract.js.map +1 -0
  37. package/dist/contracts/dice.contract.d.ts +10 -29
  38. package/dist/contracts/dice.contract.js +217 -155
  39. package/dist/contracts/dice.contract.js.map +1 -1
  40. package/dist/contracts/exchange.contract.d.ts +11 -0
  41. package/dist/contracts/exchange.contract.js +492 -0
  42. package/dist/contracts/exchange.contract.js.map +1 -0
  43. package/dist/contracts/lotto.contract.d.ts +16 -20
  44. package/dist/contracts/lotto.contract.js +238 -246
  45. package/dist/contracts/lotto.contract.js.map +1 -1
  46. package/dist/contracts/nft.contract.d.ts +28 -0
  47. package/dist/contracts/nft.contract.js +598 -0
  48. package/dist/contracts/nft.contract.js.map +1 -0
  49. package/dist/contracts/poll.contract.d.ts +4 -0
  50. package/dist/contracts/poll.contract.js +105 -0
  51. package/dist/contracts/poll.contract.js.map +1 -0
  52. package/dist/contracts/rps.contract.d.ts +9 -0
  53. package/dist/contracts/rps.contract.js +217 -0
  54. package/dist/contracts/rps.contract.js.map +1 -0
  55. package/dist/contracts/tipjar.contract.d.ts +4 -0
  56. package/dist/contracts/tipjar.contract.js +60 -0
  57. package/dist/contracts/tipjar.contract.js.map +1 -0
  58. package/dist/contracts/token.contract.d.ts +4 -0
  59. package/dist/contracts/token.contract.js +311 -0
  60. package/dist/contracts/token.contract.js.map +1 -0
  61. package/dist/exchanges/bittrex.d.ts +6 -6
  62. package/dist/exchanges/bittrex.js +34 -34
  63. package/dist/exchanges/coingecko.d.ts +11 -0
  64. package/dist/exchanges/coingecko.js +57 -0
  65. package/dist/exchanges/coingecko.js.map +1 -0
  66. package/dist/exchanges/exchange.d.ts +16 -9
  67. package/dist/exchanges/exchange.js +80 -26
  68. package/dist/exchanges/exchange.js.map +1 -1
  69. package/dist/hive-rates.d.ts +34 -9
  70. package/dist/hive-rates.js +208 -75
  71. package/dist/hive-rates.js.map +1 -1
  72. package/dist/index.d.ts +19 -11
  73. package/dist/index.js +47 -32
  74. package/dist/index.js.map +1 -1
  75. package/dist/streamer.d.ts +233 -93
  76. package/dist/streamer.js +1063 -545
  77. package/dist/streamer.js.map +1 -1
  78. package/dist/test.d.ts +1 -1
  79. package/dist/test.js +24 -25
  80. package/dist/test.js.map +1 -1
  81. package/dist/types/hive-stream.d.ts +106 -6
  82. package/dist/types/hive-stream.js +2 -2
  83. package/dist/types/rates.d.ts +47 -0
  84. package/dist/types/rates.js +29 -0
  85. package/dist/types/rates.js.map +1 -0
  86. package/dist/utils.d.ts +334 -27
  87. package/dist/utils.js +960 -261
  88. package/dist/utils.js.map +1 -1
  89. package/ecosystem.config.js +17 -17
  90. package/examples/contracts/README.md +8 -0
  91. package/examples/contracts/exchange.ts +38 -0
  92. package/examples/contracts/poll.ts +21 -0
  93. package/examples/contracts/rps.ts +19 -0
  94. package/examples/contracts/tipjar.ts +19 -0
  95. package/jest.config.js +8 -8
  96. package/package.json +54 -48
  97. package/test-contract-block.md +18 -18
  98. package/tests/actions.spec.ts +252 -0
  99. package/tests/adapters/actions-persistence.spec.ts +144 -0
  100. package/tests/adapters/postgresql.adapter.spec.ts +127 -0
  101. package/tests/adapters/sqlite.adapter.spec.ts +180 -42
  102. package/tests/contracts/coinflip.contract.spec.ts +94 -132
  103. package/tests/contracts/dice.contract.spec.ts +87 -160
  104. package/tests/contracts/entrants.json +728 -728
  105. package/tests/contracts/exchange.contract.spec.ts +84 -0
  106. package/tests/contracts/lotto.contract.spec.ts +59 -324
  107. package/tests/contracts/nft.contract.spec.ts +948 -0
  108. package/tests/contracts/token.contract.spec.ts +90 -0
  109. package/tests/exchanges/coingecko.exchange.spec.ts +169 -0
  110. package/tests/exchanges/exchange.base.spec.ts +246 -0
  111. package/tests/helpers/mock-adapter.ts +214 -0
  112. package/tests/helpers/mock-fetch.ts +165 -0
  113. package/tests/hive-chain-features.spec.ts +238 -0
  114. package/tests/hive-rates.spec.ts +443 -0
  115. package/tests/integration/hive-rates.integration.spec.ts +35 -0
  116. package/tests/setup.ts +29 -18
  117. package/tests/streamer-actions.spec.ts +274 -0
  118. package/tests/streamer.spec.ts +342 -152
  119. package/tests/types/rates.spec.ts +216 -0
  120. package/tests/utils.spec.ts +113 -95
  121. package/tsconfig.build.json +3 -22
  122. package/tslint.json +20 -20
  123. package/wallaby.js +26 -26
@@ -1,398 +1,562 @@
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.SqliteAdapter = void 0;
7
- const base_adapter_1 = require("./base.adapter");
8
- const sqlite3_1 = require("sqlite3");
9
- const path_1 = __importDefault(require("path"));
10
- class SqliteAdapter extends base_adapter_1.AdapterBase {
11
- db = new sqlite3_1.Database(path_1.default.resolve(__dirname, 'hive-stream.db'));
12
- blockNumber;
13
- lastBlockNumber;
14
- blockId;
15
- prevBlockId;
16
- transactionId;
17
- getDb() {
18
- return this.db;
19
- }
20
- async create() {
21
- return new Promise((resolve) => {
22
- this.db.serialize(() => {
23
- const params = `CREATE TABLE IF NOT EXISTS params ( id INTEGER PRIMARY KEY, lastBlockNumber NUMERIC, actions TEXT )`;
24
- const transfers = `CREATE TABLE IF NOT EXISTS transfers ( id TEXT NOT NULL UNIQUE, blockId TEXT, blockNumber INTEGER, sender TEXT, amount TEXT, contractName TEXT, contractAction TEXT, contractPayload TEXT)`;
25
- const customJson = `CREATE TABLE IF NOT EXISTS customJson ( id TEXT NOT NULL UNIQUE, blockId TEXT, blockNumber INTEGER, sender TEXT, isSignedWithActiveKey INTEGER, contractName TEXT, contractAction TEXT, contractPayload TEXT)`;
26
- const events = `CREATE TABLE IF NOT EXISTS events ( id INTEGER PRIMARY KEY, date TEXT, contract TEXT, action TEXT, payload TEXT, data TEXT )`;
27
- this.db
28
- .run(params)
29
- .run(transfers)
30
- .run(customJson)
31
- .run(events, () => {
32
- resolve(true);
33
- });
34
- });
35
- });
36
- }
37
- async loadActions() {
38
- const state = await this.loadState();
39
- if (state) {
40
- return (state?.actions) ? state.actions : [];
41
- }
42
- return [];
43
- }
44
- async loadState() {
45
- return new Promise((resolve, reject) => {
46
- this.db.all('SELECT actions, lastBlockNumber FROM params LIMIT 1', (err, rows) => {
47
- if (!err) {
48
- if (rows.length) {
49
- const row = rows[0];
50
- row.actions = JSON.parse(row.actions) ?? [];
51
- resolve(row);
52
- }
53
- else {
54
- resolve(null);
55
- }
56
- }
57
- else {
58
- reject(err);
59
- }
60
- });
61
- });
62
- }
63
- async saveState(data) {
64
- return new Promise((resolve, reject) => {
65
- const sql = `REPLACE INTO params (id, actions, lastBlockNumber) VALUES(1, '${JSON.stringify(data.actions)}', '${data.lastBlockNumber}')`;
66
- this.db.run(sql, [], (err, result) => {
67
- if (!err) {
68
- resolve(true);
69
- }
70
- else {
71
- reject(err);
72
- }
73
- });
74
- });
75
- }
76
- async processOperation(op, blockNumber, blockId, prevBlockId, trxId, blockTime) {
77
- this.blockNumber = blockNumber;
78
- this.blockId = blockId;
79
- this.prevBlockId = prevBlockId;
80
- this.transactionId = trxId;
81
- }
82
- async processTransfer(operation, payload, metadata) {
83
- return new Promise((resolve, reject) => {
84
- const sql = `INSERT INTO transfers (id, blockId, blockNumber, sender, amount, contractName, contractAction, contractPayload)
85
- VALUES ('${this.transactionId}', '${this.blockId}', ${this.blockNumber}, '${metadata.sender}', '${metadata.amount}', '${payload.name}', '${payload.action}', '${JSON.stringify(payload.payload)}')`;
86
- this.db.run(sql, [], (err, result) => {
87
- if (!err) {
88
- resolve(true);
89
- }
90
- else {
91
- reject(err);
92
- }
93
- });
94
- });
95
- }
96
- async processCustomJson(operation, payload, metadata) {
97
- return new Promise((resolve, reject) => {
98
- const sql = `INSERT INTO customJson (id, blockId, blockNumber, sender, isSignedWithActiveKey, contractName, contractAction, contractPayload)
99
- VALUES ('${this.transactionId}', '${this.blockId}', ${this.blockNumber},'${metadata.sender}', ${metadata.isSignedWithActiveKey}, '${payload.name}', '${payload.action}', '${JSON.stringify(payload.payload)}')`;
100
- this.db.run(sql, [], (err, result) => {
101
- if (!err) {
102
- resolve(true);
103
- }
104
- else {
105
- reject(err);
106
- }
107
- });
108
- });
109
- }
110
- async addEvent(date, contract, action, payload, data) {
111
- return new Promise((resolve, reject) => {
112
- const sql = `INSERT INTO events (date, contract, action, payload, data)
113
- VALUES ('${date}', '${contract}', '${action}', '${JSON.stringify(payload)}', '${JSON.stringify(data)}')`;
114
- this.db.run(sql, [], (err, result) => {
115
- if (!err) {
116
- resolve(true);
117
- }
118
- else {
119
- reject(err);
120
- }
121
- });
122
- });
123
- }
124
- async getTransfers() {
125
- return new Promise((resolve, reject) => {
126
- this.db.all('SELECT id, blockId, blockNumber, sender, amount, contractName, contractAction, contractPayload FROM transfers', (err, rows) => {
127
- if (!err) {
128
- if (rows.length) {
129
- resolve(rows.reduce((arr, row) => {
130
- row.contractPayload = JSON.parse(row.contractPayload) ?? {};
131
- arr.push(row);
132
- return arr;
133
- }, []));
134
- }
135
- else {
136
- resolve(null);
137
- }
138
- }
139
- else {
140
- reject(err);
141
- }
142
- });
143
- });
144
- }
145
- async getEvents() {
146
- return new Promise((resolve, reject) => {
147
- this.db.all('SELECT id, date, contract, action, payload, data FROM events', (err, rows) => {
148
- if (!err) {
149
- if (rows.length) {
150
- resolve(rows.reduce((arr, row) => {
151
- row.payload = JSON.parse(row.payload) ?? {};
152
- row.data = JSON.parse(row.data) ?? {};
153
- arr.push(row);
154
- return arr;
155
- }, []));
156
- }
157
- else {
158
- resolve(null);
159
- }
160
- }
161
- else {
162
- reject(err);
163
- }
164
- });
165
- });
166
- }
167
- async getTransfersByContract(contract) {
168
- return new Promise((resolve, reject) => {
169
- this.db.all(`SELECT id, blockId, blockNumber, sender, amount, contractName, contractAction, contractPayload FROM transfers WHERE contractName = '${contract}'`, (err, rows) => {
170
- if (!err) {
171
- if (rows.length) {
172
- resolve(rows.reduce((arr, row) => {
173
- row.contractPayload = JSON.parse(row.contractPayload) ?? {};
174
- arr.push(row);
175
- return arr;
176
- }, []));
177
- }
178
- else {
179
- resolve(null);
180
- }
181
- }
182
- else {
183
- reject(err);
184
- }
185
- });
186
- });
187
- }
188
- async getTransfersByAccount(account) {
189
- return new Promise((resolve, reject) => {
190
- this.db.all(`SELECT id, blockId, blockNumber, sender, amount, contractName, contractAction, contractPayload FROM transfers WHERE sender = '${account}'`, (err, rows) => {
191
- if (!err) {
192
- if (rows.length) {
193
- resolve(rows.reduce((arr, row) => {
194
- row.contractPayload = JSON.parse(row.contractPayload) ?? {};
195
- arr.push(row);
196
- return arr;
197
- }, []));
198
- }
199
- else {
200
- resolve(null);
201
- }
202
- }
203
- else {
204
- reject(err);
205
- }
206
- });
207
- });
208
- }
209
- async getTransfersByBlockid(blockId) {
210
- return new Promise((resolve, reject) => {
211
- this.db.all(`SELECT id, blockId, blockNumber, sender, amount, contractName, contractAction, contractPayload FROM transfers WHERE blockId = ${blockId}`, (err, rows) => {
212
- if (!err) {
213
- if (rows.length) {
214
- resolve(rows.reduce((arr, row) => {
215
- row.contractPayload = JSON.parse(row.contractPayload) ?? {};
216
- arr.push(row);
217
- return arr;
218
- }, []));
219
- }
220
- else {
221
- resolve(null);
222
- }
223
- }
224
- else {
225
- reject(err);
226
- }
227
- });
228
- });
229
- }
230
- async getJson() {
231
- return new Promise((resolve, reject) => {
232
- this.db.all('SELECT id, blockId, blockNumber, sender, isSignedWithActiveKey, contractName, contractAction, contractPayload FROM customJson', (err, rows) => {
233
- if (!err) {
234
- if (rows.length) {
235
- resolve(rows.reduce((arr, row) => {
236
- row.contractPayload = JSON.parse(row.contractPayload) ?? {};
237
- arr.push(row);
238
- return arr;
239
- }, []));
240
- }
241
- else {
242
- resolve(null);
243
- }
244
- }
245
- else {
246
- reject(err);
247
- }
248
- });
249
- });
250
- }
251
- async getJsonByContract(contract) {
252
- return new Promise((resolve, reject) => {
253
- this.db.all(`SELECT id, blockId, blockNumber, sender, isSignedWithActiveKey, contractName, contractAction, contractPayload FROM customJson WHERE contractName = '${contract}'`, (err, rows) => {
254
- if (!err) {
255
- if (rows.length) {
256
- resolve(rows.reduce((arr, row) => {
257
- row.contractPayload = JSON.parse(row.contractPayload) ?? {};
258
- arr.push(row);
259
- return arr;
260
- }, []));
261
- }
262
- else {
263
- resolve(null);
264
- }
265
- }
266
- else {
267
- reject(err);
268
- }
269
- });
270
- });
271
- }
272
- async getJsonByAccount(account) {
273
- return new Promise((resolve, reject) => {
274
- this.db.all(`SELECT id, blockId, blockNumber, sender, isSignedWithActiveKey, contractName, contractAction, contractPayload FROM customJson WHERE sender = '${account}'`, (err, rows) => {
275
- if (!err) {
276
- if (rows.length) {
277
- resolve(rows.reduce((arr, row) => {
278
- row.contractPayload = JSON.parse(row.contractPayload) ?? {};
279
- arr.push(row);
280
- return arr;
281
- }, []));
282
- }
283
- else {
284
- resolve(null);
285
- }
286
- }
287
- else {
288
- reject(err);
289
- }
290
- });
291
- });
292
- }
293
- async getJsonByBlockid(blockId) {
294
- return new Promise((resolve, reject) => {
295
- this.db.all(`SELECT id, blockId, blockNumber, sender, isSignedWithActiveKey, contractName, contractAction, contractPayload FROM customJson WHERE blockId = ${blockId}`, (err, rows) => {
296
- if (!err) {
297
- if (rows.length) {
298
- resolve(rows.reduce((arr, row) => {
299
- row.contractPayload = JSON.parse(row.contractPayload) ?? {};
300
- arr.push(row);
301
- return arr;
302
- }, []));
303
- }
304
- else {
305
- resolve(null);
306
- }
307
- }
308
- else {
309
- reject(err);
310
- }
311
- });
312
- });
313
- }
314
- async destroy() {
315
- return new Promise((resolve, reject) => {
316
- this.db.close((err) => {
317
- if (!err) {
318
- resolve(true);
319
- }
320
- else {
321
- reject(err);
322
- }
323
- });
324
- });
325
- }
326
- async find(table, query) {
327
- return new Promise((resolve, reject) => {
328
- query = Object.keys(query).reduce((arr, key) => {
329
- arr.push(`${key} = ${query[key]}`);
330
- return arr;
331
- }, []).join(' AND ');
332
- this.db.all(`SELECT * FROM ${table} WHERE ${query}`, (err, rows) => {
333
- if (!err) {
334
- if (rows.length) {
335
- resolve(rows);
336
- }
337
- else {
338
- resolve(null);
339
- }
340
- }
341
- else {
342
- reject(err);
343
- }
344
- });
345
- });
346
- }
347
- async findOne(table, query) {
348
- return new Promise((resolve, reject) => {
349
- query = Object.keys(query).reduce((arr, key) => {
350
- arr.push(`${key} = ${query[key]}`);
351
- return arr;
352
- }, []).join(' AND ');
353
- this.db.get(`SELECT * FROM ${table} WHERE ${query}`, (err, row) => {
354
- if (!err) {
355
- if (row) {
356
- resolve(row);
357
- }
358
- else {
359
- resolve(null);
360
- }
361
- }
362
- else {
363
- reject(err);
364
- }
365
- });
366
- });
367
- }
368
- async insert(table, data) {
369
- return new Promise((resolve, reject) => {
370
- this.db.run(`INSERT INTO ${table} VALUES (${data})`, (err) => {
371
- if (!err) {
372
- resolve(true);
373
- }
374
- else {
375
- reject(err);
376
- }
377
- });
378
- });
379
- }
380
- async replace(table, queryObject, data) {
381
- return new Promise((resolve, reject) => {
382
- queryObject = Object.keys(queryObject).reduce((arr, key) => {
383
- arr.push(`${key} = ${queryObject[key]}`);
384
- return arr;
385
- }, []).join(' AND ');
386
- this.db.run(`REPLACE INTO ${table} ${queryObject} VALUES (${data})`, (err) => {
387
- if (!err) {
388
- resolve(data);
389
- }
390
- else {
391
- reject(err);
392
- }
393
- });
394
- });
395
- }
396
- }
397
- exports.SqliteAdapter = SqliteAdapter;
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.SqliteAdapter = void 0;
7
+ const actions_1 = require("./../actions");
8
+ const base_adapter_1 = require("./base.adapter");
9
+ const knex_1 = require("knex");
10
+ const path_1 = __importDefault(require("path"));
11
+ class SqliteAdapter extends base_adapter_1.AdapterBase {
12
+ dbPath;
13
+ constructor(dbPath) {
14
+ super();
15
+ this.dbPath = dbPath || path_1.default.resolve(__dirname, 'hive-stream.db');
16
+ this.db = (0, knex_1.knex)({
17
+ client: 'better-sqlite3',
18
+ connection: {
19
+ filename: this.dbPath
20
+ },
21
+ useNullAsDefault: true,
22
+ pool: {
23
+ afterCreate: (conn, cb) => {
24
+ conn.pragma('journal_mode = WAL');
25
+ cb();
26
+ }
27
+ }
28
+ });
29
+ }
30
+ blockNumber;
31
+ lastBlockNumber;
32
+ blockId;
33
+ prevBlockId;
34
+ transactionId;
35
+ getDb() {
36
+ return this.db;
37
+ }
38
+ async create() {
39
+ try {
40
+ await this.db.schema.createTableIfNotExists('params', table => {
41
+ table.integer('id').primary();
42
+ table.integer('lastBlockNumber');
43
+ table.text('actions');
44
+ });
45
+ await this.db.schema.createTableIfNotExists('transfers', table => {
46
+ table.text('id').primary();
47
+ table.text('blockId');
48
+ table.integer('blockNumber');
49
+ table.text('sender');
50
+ table.text('amount');
51
+ table.text('contractName');
52
+ table.text('contractAction');
53
+ table.text('contractPayload');
54
+ });
55
+ await this.db.schema.createTableIfNotExists('customJson', table => {
56
+ table.text('id').primary();
57
+ table.text('blockId');
58
+ table.integer('blockNumber');
59
+ table.text('sender');
60
+ table.integer('isSignedWithActiveKey');
61
+ table.text('contractName');
62
+ table.text('contractAction');
63
+ table.text('contractPayload');
64
+ });
65
+ await this.db.schema.createTableIfNotExists('events', table => {
66
+ table.increments('id').primary();
67
+ table.text('date');
68
+ table.text('contract');
69
+ table.text('action');
70
+ table.text('payload');
71
+ table.text('data');
72
+ });
73
+ return true;
74
+ }
75
+ catch (error) {
76
+ console.error('[SqliteAdapter] Error creating tables:', error);
77
+ throw error;
78
+ }
79
+ }
80
+ async loadActions() {
81
+ const state = await this.loadState();
82
+ if (state && state.actions) {
83
+ try {
84
+ return state.actions.map((actionData) => {
85
+ try {
86
+ return actions_1.TimeAction.fromJSON(actionData);
87
+ }
88
+ catch (error) {
89
+ console.warn(`[SqliteAdapter] Failed to restore action ${actionData?.id || 'unknown'}:`, error);
90
+ return null;
91
+ }
92
+ }).filter(Boolean);
93
+ }
94
+ catch (error) {
95
+ console.error('[SqliteAdapter] Error loading actions:', error);
96
+ return [];
97
+ }
98
+ }
99
+ return [];
100
+ }
101
+ async loadState() {
102
+ try {
103
+ const row = await this.db('params')
104
+ .select('actions', 'lastBlockNumber')
105
+ .first();
106
+ if (row) {
107
+ try {
108
+ row.actions = row.actions ? JSON.parse(row.actions) : [];
109
+ }
110
+ catch (parseError) {
111
+ console.warn('[SqliteAdapter] Failed to parse actions from database, using empty array:', parseError);
112
+ row.actions = [];
113
+ }
114
+ return row;
115
+ }
116
+ return null;
117
+ }
118
+ catch (error) {
119
+ console.error('[SqliteAdapter] Error loading state:', error);
120
+ throw error;
121
+ }
122
+ }
123
+ async saveState(data) {
124
+ try {
125
+ let actionsJson;
126
+ try {
127
+ actionsJson = JSON.stringify(data.actions || []);
128
+ }
129
+ catch (error) {
130
+ console.error('[SqliteAdapter] Failed to serialize actions:', error);
131
+ actionsJson = '[]';
132
+ }
133
+ await this.db('params')
134
+ .insert({
135
+ id: 1,
136
+ actions: actionsJson,
137
+ lastBlockNumber: data.lastBlockNumber
138
+ })
139
+ .onConflict('id')
140
+ .merge();
141
+ return true;
142
+ }
143
+ catch (error) {
144
+ console.error('[SqliteAdapter] Error saving state:', error);
145
+ throw error;
146
+ }
147
+ }
148
+ async processOperation(op, blockNumber, blockId, prevBlockId, trxId, blockTime) {
149
+ this.blockNumber = blockNumber;
150
+ this.blockId = blockId;
151
+ this.prevBlockId = prevBlockId;
152
+ this.transactionId = trxId;
153
+ }
154
+ async processTransfer(operation, payload, metadata) {
155
+ try {
156
+ await this.db('transfers').insert({
157
+ id: metadata.transactionId || this.transactionId,
158
+ blockId: metadata.blockId || this.blockId,
159
+ blockNumber: metadata.blockNumber || this.blockNumber,
160
+ sender: metadata.sender,
161
+ amount: metadata.amount,
162
+ contractName: payload.contract,
163
+ contractAction: payload.action,
164
+ contractPayload: JSON.stringify(payload.payload)
165
+ });
166
+ return true;
167
+ }
168
+ catch (error) {
169
+ console.error('[SqliteAdapter] Error processing transfer:', error);
170
+ throw error;
171
+ }
172
+ }
173
+ async processCustomJson(operation, payload, metadata) {
174
+ try {
175
+ await this.db('customJson').insert({
176
+ id: metadata.transactionId || this.transactionId,
177
+ blockId: metadata.blockId || this.blockId,
178
+ blockNumber: metadata.blockNumber || this.blockNumber,
179
+ sender: metadata.sender,
180
+ isSignedWithActiveKey: metadata.isSignedWithActiveKey ? 1 : 0,
181
+ contractName: payload.contract,
182
+ contractAction: payload.action,
183
+ contractPayload: JSON.stringify(payload.payload)
184
+ });
185
+ return true;
186
+ }
187
+ catch (error) {
188
+ console.error('[SqliteAdapter] Error processing custom JSON:', error);
189
+ throw error;
190
+ }
191
+ }
192
+ async addEvent(date, contract, action, payload, data) {
193
+ try {
194
+ await this.db('events').insert({
195
+ date,
196
+ contract,
197
+ action,
198
+ payload: JSON.stringify(payload),
199
+ data: JSON.stringify(data)
200
+ });
201
+ return true;
202
+ }
203
+ catch (error) {
204
+ console.error('[SqliteAdapter] Error adding event:', error);
205
+ throw error;
206
+ }
207
+ }
208
+ async getTransfers() {
209
+ try {
210
+ const rows = await this.db('transfers')
211
+ .select('id', 'blockId', 'blockNumber', 'sender', 'amount', 'contractName', 'contractAction', 'contractPayload');
212
+ if (rows.length) {
213
+ return rows.map(row => ({
214
+ ...row,
215
+ contractPayload: JSON.parse(row.contractPayload) ?? {}
216
+ }));
217
+ }
218
+ return null;
219
+ }
220
+ catch (error) {
221
+ console.error('[SqliteAdapter] Error getting transfers:', error);
222
+ throw error;
223
+ }
224
+ }
225
+ async getEvents() {
226
+ try {
227
+ const rows = await this.db('events')
228
+ .select('id', 'date', 'contract', 'action', 'payload', 'data');
229
+ if (rows.length) {
230
+ return rows.map(row => ({
231
+ ...row,
232
+ payload: JSON.parse(row.payload) ?? {},
233
+ data: JSON.parse(row.data) ?? {}
234
+ }));
235
+ }
236
+ return null;
237
+ }
238
+ catch (error) {
239
+ console.error('[SqliteAdapter] Error getting events:', error);
240
+ throw error;
241
+ }
242
+ }
243
+ async getEventsByContract(contract) {
244
+ try {
245
+ const rows = await this.db('events')
246
+ .select('id', 'date', 'contract', 'action', 'payload', 'data')
247
+ .where('contract', contract);
248
+ if (rows.length) {
249
+ return rows.map(row => ({
250
+ ...row,
251
+ payload: JSON.parse(row.payload) ?? {},
252
+ data: JSON.parse(row.data) ?? {}
253
+ }));
254
+ }
255
+ return null;
256
+ }
257
+ catch (error) {
258
+ console.error('[SqliteAdapter] Error getting events by contract:', error);
259
+ throw error;
260
+ }
261
+ }
262
+ async getEventsByAccount(account) {
263
+ try {
264
+ const rows = await this.db('events')
265
+ .select('id', 'date', 'contract', 'action', 'payload', 'data')
266
+ .where('data', 'like', `%"${account}"%`);
267
+ if (rows.length) {
268
+ return rows.map(row => ({
269
+ ...row,
270
+ payload: JSON.parse(row.payload) ?? {},
271
+ data: JSON.parse(row.data) ?? {}
272
+ }));
273
+ }
274
+ return null;
275
+ }
276
+ catch (error) {
277
+ console.error('[SqliteAdapter] Error getting events by account:', error);
278
+ throw error;
279
+ }
280
+ }
281
+ async getTransfersByContract(contract) {
282
+ try {
283
+ const rows = await this.db('transfers')
284
+ .select('id', 'blockId', 'blockNumber', 'sender', 'amount', 'contractName', 'contractAction', 'contractPayload')
285
+ .where('contractName', contract);
286
+ if (rows.length) {
287
+ return rows.map(row => ({
288
+ ...row,
289
+ contractPayload: JSON.parse(row.contractPayload) ?? {}
290
+ }));
291
+ }
292
+ return null;
293
+ }
294
+ catch (error) {
295
+ console.error('[SqliteAdapter] Error getting transfers by contract:', error);
296
+ throw error;
297
+ }
298
+ }
299
+ async getTransfersByAccount(account) {
300
+ try {
301
+ const rows = await this.db('transfers')
302
+ .select('id', 'blockId', 'blockNumber', 'sender', 'amount', 'contractName', 'contractAction', 'contractPayload')
303
+ .where('sender', account);
304
+ if (rows.length) {
305
+ return rows.map(row => ({
306
+ ...row,
307
+ contractPayload: JSON.parse(row.contractPayload) ?? {}
308
+ }));
309
+ }
310
+ return null;
311
+ }
312
+ catch (error) {
313
+ console.error('[SqliteAdapter] Error getting transfers by account:', error);
314
+ throw error;
315
+ }
316
+ }
317
+ async getTransfersByBlockid(blockId) {
318
+ try {
319
+ const rows = await this.db('transfers')
320
+ .select('id', 'blockId', 'blockNumber', 'sender', 'amount', 'contractName', 'contractAction', 'contractPayload')
321
+ .where('blockId', blockId);
322
+ if (rows.length) {
323
+ return rows.map(row => ({
324
+ ...row,
325
+ contractPayload: JSON.parse(row.contractPayload) ?? {}
326
+ }));
327
+ }
328
+ return null;
329
+ }
330
+ catch (error) {
331
+ console.error('[SqliteAdapter] Error getting transfers by blockId:', error);
332
+ throw error;
333
+ }
334
+ }
335
+ async getJson() {
336
+ try {
337
+ const rows = await this.db('customJson')
338
+ .select('id', 'blockId', 'blockNumber', 'sender', 'isSignedWithActiveKey', 'contractName', 'contractAction', 'contractPayload');
339
+ if (rows.length) {
340
+ return rows.map(row => ({
341
+ ...row,
342
+ contractPayload: JSON.parse(row.contractPayload) ?? {}
343
+ }));
344
+ }
345
+ return null;
346
+ }
347
+ catch (error) {
348
+ console.error('[SqliteAdapter] Error getting JSON:', error);
349
+ throw error;
350
+ }
351
+ }
352
+ async getJsonByContract(contract) {
353
+ try {
354
+ const rows = await this.db('customJson')
355
+ .select('id', 'blockId', 'blockNumber', 'sender', 'isSignedWithActiveKey', 'contractName', 'contractAction', 'contractPayload')
356
+ .where('contractName', contract);
357
+ if (rows.length) {
358
+ return rows.map(row => ({
359
+ ...row,
360
+ contractPayload: JSON.parse(row.contractPayload) ?? {}
361
+ }));
362
+ }
363
+ return null;
364
+ }
365
+ catch (error) {
366
+ console.error('[SqliteAdapter] Error getting JSON by contract:', error);
367
+ throw error;
368
+ }
369
+ }
370
+ async getJsonByAccount(account) {
371
+ try {
372
+ const rows = await this.db('customJson')
373
+ .select('id', 'blockId', 'blockNumber', 'sender', 'isSignedWithActiveKey', 'contractName', 'contractAction', 'contractPayload')
374
+ .where('sender', account);
375
+ if (rows.length) {
376
+ return rows.map(row => ({
377
+ ...row,
378
+ contractPayload: JSON.parse(row.contractPayload) ?? {}
379
+ }));
380
+ }
381
+ return null;
382
+ }
383
+ catch (error) {
384
+ console.error('[SqliteAdapter] Error getting JSON by account:', error);
385
+ throw error;
386
+ }
387
+ }
388
+ async getJsonByBlockid(blockId) {
389
+ try {
390
+ const rows = await this.db('customJson')
391
+ .select('id', 'blockId', 'blockNumber', 'sender', 'isSignedWithActiveKey', 'contractName', 'contractAction', 'contractPayload')
392
+ .where('blockId', blockId);
393
+ if (rows.length) {
394
+ return rows.map(row => ({
395
+ ...row,
396
+ contractPayload: JSON.parse(row.contractPayload) ?? {}
397
+ }));
398
+ }
399
+ return null;
400
+ }
401
+ catch (error) {
402
+ console.error('[SqliteAdapter] Error getting JSON by blockId:', error);
403
+ throw error;
404
+ }
405
+ }
406
+ async getExchangeBalances(account) {
407
+ try {
408
+ const query = this.db('exchange_balances')
409
+ .select('account', 'asset', 'available', 'locked');
410
+ if (account) {
411
+ query.where('account', account);
412
+ }
413
+ const rows = await query;
414
+ return rows.length ? rows : null;
415
+ }
416
+ catch (error) {
417
+ console.error('[SqliteAdapter] Error getting exchange balances:', error);
418
+ throw error;
419
+ }
420
+ }
421
+ async getExchangeOrders(filters = {}) {
422
+ try {
423
+ const query = this.db('exchange_orders')
424
+ .select('id', 'account', 'side', 'base_asset', 'quote_asset', 'price', 'amount', 'remaining', 'status', 'created_at');
425
+ if (filters.account) {
426
+ query.where('account', filters.account);
427
+ }
428
+ if (filters.base) {
429
+ query.where('base_asset', filters.base);
430
+ }
431
+ if (filters.quote) {
432
+ query.where('quote_asset', filters.quote);
433
+ }
434
+ if (filters.status) {
435
+ query.where('status', filters.status);
436
+ }
437
+ const rows = await query;
438
+ return rows.length ? rows : null;
439
+ }
440
+ catch (error) {
441
+ console.error('[SqliteAdapter] Error getting exchange orders:', error);
442
+ throw error;
443
+ }
444
+ }
445
+ async getExchangeTrades(filters = {}) {
446
+ try {
447
+ const query = this.db('exchange_trades')
448
+ .select('id', 'buy_order_id', 'sell_order_id', 'price', 'amount', 'base_asset', 'quote_asset', 'buyer', 'seller', 'created_at');
449
+ if (filters.account) {
450
+ query.where(builder => {
451
+ builder.where('buyer', filters.account).orWhere('seller', filters.account);
452
+ });
453
+ }
454
+ if (filters.base) {
455
+ query.where('base_asset', filters.base);
456
+ }
457
+ if (filters.quote) {
458
+ query.where('quote_asset', filters.quote);
459
+ }
460
+ const rows = await query;
461
+ return rows.length ? rows : null;
462
+ }
463
+ catch (error) {
464
+ console.error('[SqliteAdapter] Error getting exchange trades:', error);
465
+ throw error;
466
+ }
467
+ }
468
+ async getExchangeOrderBookSnapshots(filters = {}) {
469
+ try {
470
+ const query = this.db('exchange_orderbook_snapshots')
471
+ .select('id', 'base_asset', 'quote_asset', 'bids', 'asks', 'created_at')
472
+ .orderBy('created_at', 'desc');
473
+ if (filters.base) {
474
+ query.where('base_asset', filters.base);
475
+ }
476
+ if (filters.quote) {
477
+ query.where('quote_asset', filters.quote);
478
+ }
479
+ if (filters.limit) {
480
+ query.limit(filters.limit);
481
+ }
482
+ const rows = await query;
483
+ if (rows.length) {
484
+ return rows.map(row => ({
485
+ ...row,
486
+ bids: JSON.parse(row.bids) ?? [],
487
+ asks: JSON.parse(row.asks) ?? []
488
+ }));
489
+ }
490
+ return null;
491
+ }
492
+ catch (error) {
493
+ console.error('[SqliteAdapter] Error getting exchange order book snapshots:', error);
494
+ throw error;
495
+ }
496
+ }
497
+ async destroy() {
498
+ try {
499
+ await this.db.destroy();
500
+ return true;
501
+ }
502
+ catch (error) {
503
+ console.error('[SqliteAdapter] Error destroying database connection:', error);
504
+ throw error;
505
+ }
506
+ }
507
+ async find(table, query) {
508
+ try {
509
+ const rows = await this.db(table).where(query);
510
+ return rows.length ? rows : null;
511
+ }
512
+ catch (error) {
513
+ console.error(`[SqliteAdapter] Error finding in table ${table}:`, error);
514
+ throw error;
515
+ }
516
+ }
517
+ async findOne(table, query) {
518
+ try {
519
+ const row = await this.db(table).where(query).first();
520
+ return row || null;
521
+ }
522
+ catch (error) {
523
+ console.error(`[SqliteAdapter] Error finding one in table ${table}:`, error);
524
+ throw error;
525
+ }
526
+ }
527
+ async insert(table, data) {
528
+ try {
529
+ await this.db(table).insert(data);
530
+ return true;
531
+ }
532
+ catch (error) {
533
+ console.error(`[SqliteAdapter] Error inserting into table ${table}:`, error);
534
+ throw error;
535
+ }
536
+ }
537
+ async replace(table, queryObject, data) {
538
+ try {
539
+ await this.db(table)
540
+ .insert(data)
541
+ .onConflict(Object.keys(queryObject))
542
+ .merge();
543
+ return data;
544
+ }
545
+ catch (error) {
546
+ console.error(`[SqliteAdapter] Error replacing in table ${table}:`, error);
547
+ throw error;
548
+ }
549
+ }
550
+ async query(sql, params) {
551
+ try {
552
+ const result = await this.db.raw(sql, params);
553
+ return result || [];
554
+ }
555
+ catch (error) {
556
+ console.error('[SqliteAdapter] Error executing raw query:', error);
557
+ throw error;
558
+ }
559
+ }
560
+ }
561
+ exports.SqliteAdapter = SqliteAdapter;
398
562
  //# sourceMappingURL=sqlite.adapter.js.map