@coopenomics/parser 2025.10.16 → 2025.11.7

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/dist/index.cjs CHANGED
@@ -32,50 +32,20 @@ const redisPort = getEnvVar("REDIS_PORT");
32
32
  const redisHost = getEnvVar("REDIS_HOST");
33
33
  const redisPassword = getEnvVar("REDIS_PASSWORD");
34
34
  const redisStreamLimit = Number(getEnvVar("REDIS_STREAM_LIMIT"));
35
- const subsribedTables = [
36
- // документы
37
- { code: "draft", table: "drafts" },
38
- { code: "draft", table: "translations" },
39
- // meet
40
- { code: "meet", table: "meets" },
41
- { code: "meet", table: "questions" },
42
- // совет
43
- { code: "soviet", table: "decisions" },
44
- { code: "soviet", table: "boards" },
45
- { code: "soviet", table: "participants" },
46
- // registrator.joincoop
47
- { code: "soviet", table: "joincoops" },
48
- // регистратор
49
- { code: "registrator", table: "accounts" },
50
- { code: "registrator", table: "coops" }
51
- ];
52
- const subsribedActions = [
53
- { code: "eosio.token", action: "transfer", notify: true },
54
- { code: "registrator", action: "confirmreg", notify: true },
55
- { code: "soviet", action: "votefor" },
56
- { code: "soviet", action: "voteagainst" },
57
- { code: "soviet", action: "newsubmitted" },
58
- { code: "soviet", action: "newresolved" },
59
- { code: "soviet", action: "newdecision" },
60
- { code: "soviet", action: "newpackage" },
61
- { code: "soviet", action: "newact" },
62
- { code: "soviet", action: "newlink" },
63
- { code: "soviet", action: "newagreement" },
64
- { code: "soviet", action: "newdeclined" },
65
- // // registrator.joincoop
66
- { code: "soviet", action: "joincoop" },
67
- { code: "soviet", action: "joincoopdec" },
68
- { code: "soviet", action: "updateboard", notify: true },
69
- { code: "soviet", action: "createboard", notify: true },
70
- { code: "meet", action: "newgdecision", notify: true },
71
- { code: "wallet", action: "createwthd", notify: true },
72
- { code: "ledger", action: "debet", notify: true },
73
- { code: "ledger", action: "credit", notify: true },
74
- { code: "ledger", action: "block", notify: true },
75
- { code: "ledger", action: "unblock", notify: true },
76
- { code: "ledger", action: "writeoff", notify: true },
77
- { code: "ledger", action: "writeoffcnsl", notify: true }
35
+ const subscribedContracts = [
36
+ "draft",
37
+ "meet",
38
+ "soviet",
39
+ "registrator",
40
+ "eosio.token",
41
+ "capital",
42
+ "wallet",
43
+ "ledger"
78
44
  ];
45
+ const subsribedActions = subscribedContracts.map((contract) => ({
46
+ code: contract,
47
+ action: "*"
48
+ }));
79
49
 
80
50
  var __defProp = Object.defineProperty;
81
51
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -200,6 +170,16 @@ async function publishEvent(type, event) {
200
170
  await redis.xadd(streamName, "*", "event", message);
201
171
  await redis.xtrim(streamName, "MAXLEN", "~", redisStreamLimit);
202
172
  }
173
+ async function publishDelta(type, delta) {
174
+ const message = JSON.stringify({ type, delta });
175
+ await redis.xadd(streamName, "*", "delta", message);
176
+ await redis.xtrim(streamName, "MAXLEN", "~", redisStreamLimit);
177
+ }
178
+ async function publishFork(type, block_num) {
179
+ const message = JSON.stringify({ type, block_num });
180
+ await redis.xadd(streamName, "*", "fork", message);
181
+ await redis.xtrim(streamName, "MAXLEN", "~", redisStreamLimit);
182
+ }
203
183
 
204
184
  class AnyAnyActionParser {
205
185
  async process(db, action) {
@@ -224,11 +204,9 @@ async function ActionsParser(db, reader) {
224
204
  console.log(`
225
205
  ACTION - account: ${action.account}, name: ${action.name}, authorization: ${JSON.stringify(action.authorization)}, data: ${JSON.stringify(action.data)}`);
226
206
  const parser = ActionParserFactory.create(action.account, action.name);
227
- const source = subsribedActions.find((el) => el.action === action.name && el.code === action.account);
228
207
  if (parser) {
229
208
  await parser.process(db, action);
230
- if (source?.notify)
231
- await publishEvent("action", action);
209
+ await publishEvent("action", action);
232
210
  }
233
211
  });
234
212
  console.log("\u041F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u043D\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0430\u043A\u0442\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u0430");
@@ -269,17 +247,41 @@ async function DeltasParser(db, reader) {
269
247
  rows$.subscribe(async (delta) => {
270
248
  console.log(`
271
249
  DELTA - code: ${delta.code}, scope: ${delta.scope}, table: ${delta.table}, primary_key: ${delta.primary_key}, data: ${JSON.stringify(delta.value)}`);
272
- const source = subsribedTables.find((el) => el.code === delta.code && el.table === delta.table);
273
250
  const parser = DeltaParserFactory.create(delta.code, delta.scope, delta.table);
274
251
  if (parser) {
275
252
  await parser.process(db, delta);
276
- if (source?.notify)
277
- await publishEvent("delta", delta);
253
+ await publishDelta("delta", delta);
278
254
  }
279
255
  });
280
256
  console.log("\u041F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u043D\u0430 \u0434\u0435\u043B\u044C\u0442\u044B \u0430\u043A\u0442\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u0430");
281
257
  }
282
258
 
259
+ class AnyForkParser {
260
+ async process(db, block_num) {
261
+ console.log(`FORK detected at block: ${block_num}`);
262
+ }
263
+ }
264
+
265
+ class ForkParserFactory {
266
+ static create() {
267
+ return new AnyForkParser();
268
+ }
269
+ }
270
+
271
+ async function ForksParser(db, reader) {
272
+ const { forks$ } = reader;
273
+ forks$.subscribe(async (block_num) => {
274
+ console.log(`
275
+ FORK detected at block: ${block_num}`);
276
+ const parser = ForkParserFactory.create();
277
+ if (parser) {
278
+ await parser.process(db, block_num);
279
+ await publishFork("fork", block_num);
280
+ }
281
+ });
282
+ console.log("\u041F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u043D\u0430 \u0444\u043E\u0440\u043A\u0438 \u0430\u043A\u0442\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u0430");
283
+ }
284
+
283
285
  const getInfo = () => fetch__default(`${eosioApi}/v1/chain/get_info`).then((res) => res.json());
284
286
  function fetchAbi(account_name) {
285
287
  return fetch__default(`${eosioApi}/v1/chain/get_abi`, {
@@ -289,17 +291,23 @@ function fetchAbi(account_name) {
289
291
  })
290
292
  }).then(async (res) => {
291
293
  const response = await res.json();
294
+ if (!response.abi) {
295
+ console.warn(`ABI \u0434\u043B\u044F \u043A\u043E\u043D\u0442\u0440\u0430\u043A\u0442\u0430 ${account_name} \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D (\u043A\u043E\u043D\u0442\u0440\u0430\u043A\u0442 \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D \u0432 \u0431\u043B\u043E\u043A\u0447\u0435\u0439\u043D\u0435)`);
296
+ }
292
297
  return {
293
298
  account_name,
294
299
  abi: response.abi
295
300
  };
296
301
  });
297
302
  }
303
+ function extractTablesFromAbi(abi) {
304
+ if (!abi || !abi.tables)
305
+ return [];
306
+ return abi.tables.map((table) => table.name);
307
+ }
298
308
 
299
- const table_rows_whitelist = () => subsribedTables;
300
309
  const actions_whitelist = () => subsribedActions;
301
- console.log(subsribedTables);
302
- console.log(subsribedActions);
310
+ console.log("Actions whitelist (auto-generated from subscribedContracts):", subsribedActions);
303
311
  async function loadReader(db) {
304
312
  let currentBlock = await db.getCurrentBlock();
305
313
  const info = await getInfo();
@@ -315,13 +323,27 @@ async function loadReader(db) {
315
323
  console.log("\u0412\u044B\u0441\u043E\u0442\u0430 \u0446\u0435\u043F\u043E\u0447\u043A\u0438: ", info.head_block_num);
316
324
  console.log("\u041E\u0447\u0438\u0449\u0430\u0435\u043C \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0438 \u0434\u0435\u043B\u044C\u0442\u044B \u043F\u043E\u0441\u043B\u0435 \u0431\u043B\u043E\u043A\u0430: ", currentBlock);
317
325
  await db.purgeAfterBlock(currentBlock);
318
- const unique_contract_names = [...new Set(table_rows_whitelist().map((row) => row.code)), ...new Set(actions_whitelist().map((row) => row.code))];
326
+ const unique_contract_names = [.../* @__PURE__ */ new Set([...subscribedContracts, ...actions_whitelist().map((row) => row.code)])];
319
327
  const abisArr = await Promise.all(unique_contract_names.map((account_name) => fetchAbi(account_name)));
320
328
  const contract_abis = () => {
321
329
  const numap = /* @__PURE__ */ new Map();
322
330
  abisArr.forEach(({ account_name, abi }) => numap.set(account_name, abi));
323
331
  return numap;
324
332
  };
333
+ const table_rows_whitelist = () => {
334
+ const tables = [];
335
+ abisArr.forEach(({ account_name, abi }) => {
336
+ if (subscribedContracts.includes(account_name)) {
337
+ const tableNames = extractTablesFromAbi(abi);
338
+ tableNames.forEach((tableName) => {
339
+ tables.push({ code: account_name, table: tableName });
340
+ });
341
+ }
342
+ });
343
+ return tables;
344
+ };
345
+ const tablesWhitelist = table_rows_whitelist();
346
+ console.log("Tables whitelist (auto-generated from ABI):", tablesWhitelist);
325
347
  const delta_whitelist = () => [
326
348
  "account_metadata",
327
349
  "contract_table",
@@ -362,6 +384,7 @@ class Parser {
362
384
  BlockParser(db, reader);
363
385
  ActionsParser(db, reader);
364
386
  DeltasParser(db, reader);
387
+ ForksParser(db, reader);
365
388
  } catch (e) {
366
389
  console.error("\u041E\u0448\u0438\u0431\u043A\u0430: ", e);
367
390
  this.start();
package/dist/index.mjs CHANGED
@@ -23,50 +23,20 @@ const redisPort = getEnvVar("REDIS_PORT");
23
23
  const redisHost = getEnvVar("REDIS_HOST");
24
24
  const redisPassword = getEnvVar("REDIS_PASSWORD");
25
25
  const redisStreamLimit = Number(getEnvVar("REDIS_STREAM_LIMIT"));
26
- const subsribedTables = [
27
- // документы
28
- { code: "draft", table: "drafts" },
29
- { code: "draft", table: "translations" },
30
- // meet
31
- { code: "meet", table: "meets" },
32
- { code: "meet", table: "questions" },
33
- // совет
34
- { code: "soviet", table: "decisions" },
35
- { code: "soviet", table: "boards" },
36
- { code: "soviet", table: "participants" },
37
- // registrator.joincoop
38
- { code: "soviet", table: "joincoops" },
39
- // регистратор
40
- { code: "registrator", table: "accounts" },
41
- { code: "registrator", table: "coops" }
42
- ];
43
- const subsribedActions = [
44
- { code: "eosio.token", action: "transfer", notify: true },
45
- { code: "registrator", action: "confirmreg", notify: true },
46
- { code: "soviet", action: "votefor" },
47
- { code: "soviet", action: "voteagainst" },
48
- { code: "soviet", action: "newsubmitted" },
49
- { code: "soviet", action: "newresolved" },
50
- { code: "soviet", action: "newdecision" },
51
- { code: "soviet", action: "newpackage" },
52
- { code: "soviet", action: "newact" },
53
- { code: "soviet", action: "newlink" },
54
- { code: "soviet", action: "newagreement" },
55
- { code: "soviet", action: "newdeclined" },
56
- // // registrator.joincoop
57
- { code: "soviet", action: "joincoop" },
58
- { code: "soviet", action: "joincoopdec" },
59
- { code: "soviet", action: "updateboard", notify: true },
60
- { code: "soviet", action: "createboard", notify: true },
61
- { code: "meet", action: "newgdecision", notify: true },
62
- { code: "wallet", action: "createwthd", notify: true },
63
- { code: "ledger", action: "debet", notify: true },
64
- { code: "ledger", action: "credit", notify: true },
65
- { code: "ledger", action: "block", notify: true },
66
- { code: "ledger", action: "unblock", notify: true },
67
- { code: "ledger", action: "writeoff", notify: true },
68
- { code: "ledger", action: "writeoffcnsl", notify: true }
26
+ const subscribedContracts = [
27
+ "draft",
28
+ "meet",
29
+ "soviet",
30
+ "registrator",
31
+ "eosio.token",
32
+ "capital",
33
+ "wallet",
34
+ "ledger"
69
35
  ];
36
+ const subsribedActions = subscribedContracts.map((contract) => ({
37
+ code: contract,
38
+ action: "*"
39
+ }));
70
40
 
71
41
  var __defProp = Object.defineProperty;
72
42
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -191,6 +161,16 @@ async function publishEvent(type, event) {
191
161
  await redis.xadd(streamName, "*", "event", message);
192
162
  await redis.xtrim(streamName, "MAXLEN", "~", redisStreamLimit);
193
163
  }
164
+ async function publishDelta(type, delta) {
165
+ const message = JSON.stringify({ type, delta });
166
+ await redis.xadd(streamName, "*", "delta", message);
167
+ await redis.xtrim(streamName, "MAXLEN", "~", redisStreamLimit);
168
+ }
169
+ async function publishFork(type, block_num) {
170
+ const message = JSON.stringify({ type, block_num });
171
+ await redis.xadd(streamName, "*", "fork", message);
172
+ await redis.xtrim(streamName, "MAXLEN", "~", redisStreamLimit);
173
+ }
194
174
 
195
175
  class AnyAnyActionParser {
196
176
  async process(db, action) {
@@ -215,11 +195,9 @@ async function ActionsParser(db, reader) {
215
195
  console.log(`
216
196
  ACTION - account: ${action.account}, name: ${action.name}, authorization: ${JSON.stringify(action.authorization)}, data: ${JSON.stringify(action.data)}`);
217
197
  const parser = ActionParserFactory.create(action.account, action.name);
218
- const source = subsribedActions.find((el) => el.action === action.name && el.code === action.account);
219
198
  if (parser) {
220
199
  await parser.process(db, action);
221
- if (source?.notify)
222
- await publishEvent("action", action);
200
+ await publishEvent("action", action);
223
201
  }
224
202
  });
225
203
  console.log("\u041F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u043D\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0430\u043A\u0442\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u0430");
@@ -260,17 +238,41 @@ async function DeltasParser(db, reader) {
260
238
  rows$.subscribe(async (delta) => {
261
239
  console.log(`
262
240
  DELTA - code: ${delta.code}, scope: ${delta.scope}, table: ${delta.table}, primary_key: ${delta.primary_key}, data: ${JSON.stringify(delta.value)}`);
263
- const source = subsribedTables.find((el) => el.code === delta.code && el.table === delta.table);
264
241
  const parser = DeltaParserFactory.create(delta.code, delta.scope, delta.table);
265
242
  if (parser) {
266
243
  await parser.process(db, delta);
267
- if (source?.notify)
268
- await publishEvent("delta", delta);
244
+ await publishDelta("delta", delta);
269
245
  }
270
246
  });
271
247
  console.log("\u041F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u043D\u0430 \u0434\u0435\u043B\u044C\u0442\u044B \u0430\u043A\u0442\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u0430");
272
248
  }
273
249
 
250
+ class AnyForkParser {
251
+ async process(db, block_num) {
252
+ console.log(`FORK detected at block: ${block_num}`);
253
+ }
254
+ }
255
+
256
+ class ForkParserFactory {
257
+ static create() {
258
+ return new AnyForkParser();
259
+ }
260
+ }
261
+
262
+ async function ForksParser(db, reader) {
263
+ const { forks$ } = reader;
264
+ forks$.subscribe(async (block_num) => {
265
+ console.log(`
266
+ FORK detected at block: ${block_num}`);
267
+ const parser = ForkParserFactory.create();
268
+ if (parser) {
269
+ await parser.process(db, block_num);
270
+ await publishFork("fork", block_num);
271
+ }
272
+ });
273
+ console.log("\u041F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u043D\u0430 \u0444\u043E\u0440\u043A\u0438 \u0430\u043A\u0442\u0438\u0432\u0438\u0440\u043E\u0432\u0430\u043D\u0430");
274
+ }
275
+
274
276
  const getInfo = () => fetch(`${eosioApi}/v1/chain/get_info`).then((res) => res.json());
275
277
  function fetchAbi(account_name) {
276
278
  return fetch(`${eosioApi}/v1/chain/get_abi`, {
@@ -280,17 +282,23 @@ function fetchAbi(account_name) {
280
282
  })
281
283
  }).then(async (res) => {
282
284
  const response = await res.json();
285
+ if (!response.abi) {
286
+ console.warn(`ABI \u0434\u043B\u044F \u043A\u043E\u043D\u0442\u0440\u0430\u043A\u0442\u0430 ${account_name} \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D (\u043A\u043E\u043D\u0442\u0440\u0430\u043A\u0442 \u043D\u0435 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D \u0432 \u0431\u043B\u043E\u043A\u0447\u0435\u0439\u043D\u0435)`);
287
+ }
283
288
  return {
284
289
  account_name,
285
290
  abi: response.abi
286
291
  };
287
292
  });
288
293
  }
294
+ function extractTablesFromAbi(abi) {
295
+ if (!abi || !abi.tables)
296
+ return [];
297
+ return abi.tables.map((table) => table.name);
298
+ }
289
299
 
290
- const table_rows_whitelist = () => subsribedTables;
291
300
  const actions_whitelist = () => subsribedActions;
292
- console.log(subsribedTables);
293
- console.log(subsribedActions);
301
+ console.log("Actions whitelist (auto-generated from subscribedContracts):", subsribedActions);
294
302
  async function loadReader(db) {
295
303
  let currentBlock = await db.getCurrentBlock();
296
304
  const info = await getInfo();
@@ -306,13 +314,27 @@ async function loadReader(db) {
306
314
  console.log("\u0412\u044B\u0441\u043E\u0442\u0430 \u0446\u0435\u043F\u043E\u0447\u043A\u0438: ", info.head_block_num);
307
315
  console.log("\u041E\u0447\u0438\u0449\u0430\u0435\u043C \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0438 \u0434\u0435\u043B\u044C\u0442\u044B \u043F\u043E\u0441\u043B\u0435 \u0431\u043B\u043E\u043A\u0430: ", currentBlock);
308
316
  await db.purgeAfterBlock(currentBlock);
309
- const unique_contract_names = [...new Set(table_rows_whitelist().map((row) => row.code)), ...new Set(actions_whitelist().map((row) => row.code))];
317
+ const unique_contract_names = [.../* @__PURE__ */ new Set([...subscribedContracts, ...actions_whitelist().map((row) => row.code)])];
310
318
  const abisArr = await Promise.all(unique_contract_names.map((account_name) => fetchAbi(account_name)));
311
319
  const contract_abis = () => {
312
320
  const numap = /* @__PURE__ */ new Map();
313
321
  abisArr.forEach(({ account_name, abi }) => numap.set(account_name, abi));
314
322
  return numap;
315
323
  };
324
+ const table_rows_whitelist = () => {
325
+ const tables = [];
326
+ abisArr.forEach(({ account_name, abi }) => {
327
+ if (subscribedContracts.includes(account_name)) {
328
+ const tableNames = extractTablesFromAbi(abi);
329
+ tableNames.forEach((tableName) => {
330
+ tables.push({ code: account_name, table: tableName });
331
+ });
332
+ }
333
+ });
334
+ return tables;
335
+ };
336
+ const tablesWhitelist = table_rows_whitelist();
337
+ console.log("Tables whitelist (auto-generated from ABI):", tablesWhitelist);
316
338
  const delta_whitelist = () => [
317
339
  "account_metadata",
318
340
  "contract_table",
@@ -353,6 +375,7 @@ class Parser {
353
375
  BlockParser(db, reader);
354
376
  ActionsParser(db, reader);
355
377
  DeltasParser(db, reader);
378
+ ForksParser(db, reader);
356
379
  } catch (e) {
357
380
  console.error("\u041E\u0448\u0438\u0431\u043A\u0430: ", e);
358
381
  this.start();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@coopenomics/parser",
3
3
  "type": "module",
4
- "version": "2025.10.16",
4
+ "version": "2025.11.7",
5
5
  "private": false,
6
6
  "packageManager": "pnpm@9.0.6",
7
7
  "description": "",
@@ -85,5 +85,5 @@
85
85
  "vite": "^5.2.10",
86
86
  "vitest": "^1.5.2"
87
87
  },
88
- "gitHead": "ff520622ff999a103fa038a4236da9a264a8b9be"
88
+ "gitHead": "11f23bbd77d0579b76ce896a31201d307333f1e0"
89
89
  }