@lido-nestjs/registry 1.1.1 → 1.2.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.
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import { LoggerService } from '@nestjs/common';
3
3
  import { Registry } from '@lido-nestjs/contracts';
4
- import { EntityManager } from '@mikro-orm/core';
4
+ import { EntityManager } from '@mikro-orm/knex';
5
5
  import EventEmitter from 'events';
6
6
  import { CronJob } from 'cron';
7
7
  import { RegistryMetaFetchService } from '../fetch/meta.fetch';
@@ -47,6 +47,10 @@ export declare abstract class AbstractRegistryService {
47
47
  getMetaDataFromStorage(): Promise<RegistryMeta | null>;
48
48
  /** returns the latest operators data from the db */
49
49
  getOperatorsFromStorage(): Promise<RegistryOperator[]>;
50
+ /** returns all the keys from storage */
51
+ getOperatorsKeysFromStorage(): Promise<RegistryKey[]>;
52
+ /** saves all the data to the db */
53
+ save(updatedKeys: RegistryKey[], currentOperators: RegistryOperator[], currMeta: RegistryMeta): Promise<void>;
50
54
  /** clears the db */
51
55
  clear(): Promise<void>;
52
56
  }
@@ -5,7 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var tslib = require('tslib');
6
6
  var common = require('@nestjs/common');
7
7
  var contracts = require('@lido-nestjs/contracts');
8
- var core = require('@mikro-orm/core');
8
+ var knex = require('@mikro-orm/knex');
9
9
  var logger = require('@lido-nestjs/logger');
10
10
  var decorators = require('@lido-nestjs/decorators');
11
11
  var EventEmitter = require('events');
@@ -22,6 +22,7 @@ var operator_entity = require('../storage/operator.entity.js');
22
22
  var meta_utils = require('../utils/meta.utils.js');
23
23
  var operator_utils = require('../utils/operator.utils.js');
24
24
  var constants = require('./constants.js');
25
+ var utils = require('@lido-nestjs/utils');
25
26
 
26
27
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
27
28
 
@@ -40,7 +41,7 @@ exports.AbstractRegistryService = class AbstractRegistryService {
40
41
  this.entityManager = entityManager;
41
42
  this.options = options;
42
43
  this.eventEmitter = new EventEmitter__default["default"]();
43
- this.cronJob = new cron.CronJob((options === null || options === void 0 ? void 0 : options.subscribeInterval) || '*/10 * * * * *', this.cronHandler);
44
+ this.cronJob = new cron.CronJob((options === null || options === void 0 ? void 0 : options.subscribeInterval) || '*/10 * * * * *', () => this.cronHandler());
44
45
  }
45
46
  async cronHandler() {
46
47
  try {
@@ -85,7 +86,10 @@ exports.AbstractRegistryService = class AbstractRegistryService {
85
86
  }
86
87
  if (isSameContractState) {
87
88
  (_c = (_b = this.logger).debug) === null || _c === void 0 ? void 0 : _c.call(_b, 'Same state, no data update required', { currMeta });
88
- await this.metaStorage.save(currMeta);
89
+ await this.entityManager.transactional(async (entityManager) => {
90
+ await entityManager.nativeDelete(meta_entity.RegistryMeta, {});
91
+ await entityManager.persist(new meta_entity.RegistryMeta(currMeta));
92
+ });
89
93
  (_e = (_d = this.logger).debug) === null || _e === void 0 ? void 0 : _e.call(_d, 'Updated metadata in the DB', { currMeta });
90
94
  return;
91
95
  }
@@ -100,19 +104,7 @@ exports.AbstractRegistryService = class AbstractRegistryService {
100
104
  this.logger.log('Fetched updated keys', {
101
105
  updatedKeys: updatedKeys.length,
102
106
  });
103
- // save all data in a transaction
104
- await this.entityManager.transactional(async (entityManager) => {
105
- updatedKeys.forEach(async (operatorKey) => {
106
- const instance = new key_entity.RegistryKey(operatorKey);
107
- entityManager.persist(instance);
108
- });
109
- currentOperators.forEach(async (operator) => {
110
- const instance = new operator_entity.RegistryOperator(operator);
111
- entityManager.persist(instance);
112
- });
113
- const meta = new meta_entity.RegistryMeta(currMeta);
114
- entityManager.persist(meta);
115
- });
107
+ await this.save(updatedKeys, currentOperators, currMeta);
116
108
  this.logger.log('Saved data to the DB', {
117
109
  operators: currentOperators.length,
118
110
  updatedKeys: updatedKeys.length,
@@ -156,8 +148,12 @@ exports.AbstractRegistryService = class AbstractRegistryService {
156
148
  const unchangedKeysMaxIndex = isSameOperator
157
149
  ? prevOperator.usedSigningKeys
158
150
  : 0;
159
- const fromIndex = unchangedKeysMaxIndex;
151
+ // get the right border up to which the keys should be updated
152
+ // it's different for different scenarios
160
153
  const toIndex = this.getToIndex(currOperator);
154
+ // fromIndex may become larger than toIndex if used keys are deleted
155
+ // this should not happen in mainnet, but sometimes keys can be deleted in testnet by modification of the contract
156
+ const fromIndex = unchangedKeysMaxIndex <= toIndex ? unchangedKeysMaxIndex : 0;
161
157
  const operatorIndex = currOperator.index;
162
158
  const overrides = { blockTag: { blockHash } };
163
159
  const result = await this.keyFetch.fetch(operatorIndex, fromIndex, toIndex, overrides);
@@ -169,7 +165,7 @@ exports.AbstractRegistryService = class AbstractRegistryService {
169
165
  });
170
166
  return result;
171
167
  }));
172
- return keysByOperator.flat();
168
+ return keysByOperator.flat().filter((key) => key);
173
169
  }
174
170
  /** storage */
175
171
  /** returns the latest meta data from the db */
@@ -180,6 +176,48 @@ exports.AbstractRegistryService = class AbstractRegistryService {
180
176
  async getOperatorsFromStorage() {
181
177
  return await this.operatorStorage.findAll();
182
178
  }
179
+ /** returns all the keys from storage */
180
+ async getOperatorsKeysFromStorage() {
181
+ return await this.keyStorage.findAll();
182
+ }
183
+ /** saves all the data to the db */
184
+ async save(updatedKeys, currentOperators, currMeta) {
185
+ // save all data in a transaction
186
+ await this.entityManager.transactional(async (entityManager) => {
187
+ await Promise.all(
188
+ // remove all keys from the database that are greater than the total number of keys
189
+ // it's needed to clear the list in db when removing keys from the contract
190
+ currentOperators.map(async (operator) => {
191
+ await entityManager.nativeDelete(key_entity.RegistryKey, {
192
+ index: { $gte: operator.totalSigningKeys },
193
+ operatorIndex: operator.index,
194
+ });
195
+ }));
196
+ await Promise.all(
197
+ // 500 — SQLite limit in insert operation
198
+ utils.chunk(updatedKeys, 499).map(async (keysChunk) => {
199
+ await entityManager
200
+ .createQueryBuilder(key_entity.RegistryKey)
201
+ .insert(keysChunk)
202
+ .onConflict(['index', 'operator_index'])
203
+ .merge()
204
+ .execute();
205
+ }));
206
+ await Promise.all(
207
+ // 500 — SQLite limit in insert operation
208
+ utils.chunk(currentOperators, 499).map(async (operatorsChunk) => {
209
+ await entityManager
210
+ .createQueryBuilder(operator_entity.RegistryOperator)
211
+ .insert(operatorsChunk)
212
+ .onConflict('index')
213
+ .merge()
214
+ .execute();
215
+ }));
216
+ // replace metadata with new one
217
+ await entityManager.nativeDelete(meta_entity.RegistryMeta, {});
218
+ await entityManager.persist(new meta_entity.RegistryMeta(currMeta));
219
+ });
220
+ }
183
221
  /** clears the db */
184
222
  async clear() {
185
223
  await this.entityManager.transactional(async (entityManager) => {
@@ -207,5 +245,5 @@ exports.AbstractRegistryService = tslib.__decorate([
207
245
  key_storage.RegistryKeyStorageService,
208
246
  operator_fetch.RegistryOperatorFetchService,
209
247
  operator_storage.RegistryOperatorStorageService,
210
- core.EntityManager, Object])
248
+ knex.EntityManager, Object])
211
249
  ], exports.AbstractRegistryService);
@@ -1,4 +1,4 @@
1
- import { EntityRepository } from '@mikro-orm/core';
1
+ import { EntityRepository } from '@mikro-orm/knex';
2
2
  import { RegistryKey } from './key.entity';
3
3
  export declare class RegistryKeyRepository extends EntityRepository<RegistryKey> {
4
4
  }
@@ -2,9 +2,9 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var core = require('@mikro-orm/core');
5
+ var knex = require('@mikro-orm/knex');
6
6
 
7
- class RegistryKeyRepository extends core.EntityRepository {
7
+ class RegistryKeyRepository extends knex.EntityRepository {
8
8
  }
9
9
 
10
10
  exports.RegistryKeyRepository = RegistryKeyRepository;
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var tslib = require('tslib');
6
+ var core = require('@mikro-orm/core');
6
7
  var common = require('@nestjs/common');
7
8
  var key_entity = require('./key.entity.js');
8
9
  var key_repository = require('./key.repository.js');
@@ -13,7 +14,9 @@ exports.RegistryKeyStorageService = class RegistryKeyStorageService {
13
14
  }
14
15
  /** find all keys */
15
16
  async findAll() {
16
- return await this.repository.findAll();
17
+ return await this.repository.findAll({
18
+ orderBy: [{ operatorIndex: core.QueryOrder.ASC }, { index: core.QueryOrder.ASC }],
19
+ });
17
20
  }
18
21
  /** find used keys */
19
22
  async findUsed() {
@@ -1,4 +1,4 @@
1
- import { EntityRepository } from '@mikro-orm/core';
1
+ import { EntityRepository } from '@mikro-orm/knex';
2
2
  import { RegistryMeta } from './meta.entity';
3
3
  export declare class RegistryMetaRepository extends EntityRepository<RegistryMeta> {
4
4
  }
@@ -2,9 +2,9 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var core = require('@mikro-orm/core');
5
+ var knex = require('@mikro-orm/knex');
6
6
 
7
- class RegistryMetaRepository extends core.EntityRepository {
7
+ class RegistryMetaRepository extends knex.EntityRepository {
8
8
  }
9
9
 
10
10
  exports.RegistryMetaRepository = RegistryMetaRepository;
@@ -1,4 +1,4 @@
1
- import { EntityRepository } from '@mikro-orm/core';
1
+ import { EntityRepository } from '@mikro-orm/knex';
2
2
  import { RegistryOperator } from './operator.entity';
3
3
  export declare class RegistryOperatorRepository extends EntityRepository<RegistryOperator> {
4
4
  }
@@ -2,9 +2,9 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var core = require('@mikro-orm/core');
5
+ var knex = require('@mikro-orm/knex');
6
6
 
7
- class RegistryOperatorRepository extends core.EntityRepository {
7
+ class RegistryOperatorRepository extends knex.EntityRepository {
8
8
  }
9
9
 
10
10
  exports.RegistryOperatorRepository = RegistryOperatorRepository;
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var tslib = require('tslib');
6
+ var core = require('@mikro-orm/core');
6
7
  var common = require('@nestjs/common');
7
8
  var operator_entity = require('./operator.entity.js');
8
9
  var operator_repository = require('./operator.repository.js');
@@ -13,7 +14,9 @@ exports.RegistryOperatorStorageService = class RegistryOperatorStorageService {
13
14
  }
14
15
  /** find all operators */
15
16
  async findAll() {
16
- return await this.repository.findAll();
17
+ return await this.repository.findAll({
18
+ orderBy: [{ index: core.QueryOrder.ASC }],
19
+ });
17
20
  }
18
21
  /** find operator by index */
19
22
  async findOneByIndex(operatorIndex) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lido-nestjs/registry",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "MIT",
@@ -31,11 +31,12 @@
31
31
  "@lido-nestjs/contracts": "2.1.0",
32
32
  "@lido-nestjs/decorators": "1.0.0",
33
33
  "@lido-nestjs/logger": "1.1.0",
34
- "@lido-nestjs/utils": "1.1.0",
34
+ "@lido-nestjs/utils": "1.2.0",
35
35
  "cron": "^2.0.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@mikro-orm/core": "^5.2.0",
39
+ "@mikro-orm/knex": "^5.2.0",
39
40
  "@mikro-orm/nestjs": "^5.0.2",
40
41
  "@nestjs/common": "^8.2.5",
41
42
  "@nestjs/core": "^8.2.5",
@@ -46,6 +47,7 @@
46
47
  "devDependencies": {
47
48
  "@lido-nestjs/execution": "1.7.0",
48
49
  "@mikro-orm/core": "^5.2.0",
50
+ "@mikro-orm/knex": "^5.2.0",
49
51
  "@mikro-orm/nestjs": "^5.0.2",
50
52
  "@mikro-orm/sqlite": "^5.2.0",
51
53
  "@nestjs/common": "^8.2.5",