@rosen-bridge/abstract-extractor 2.0.3 → 2.1.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 (50) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/abstractExtractor.js +1 -1
  3. package/dist/ergo/AbstractErgoExtractor.js +2 -3
  4. package/dist/ergo/AbstractErgoExtractorAction.d.ts +1 -1
  5. package/dist/ergo/AbstractErgoExtractorAction.d.ts.map +1 -1
  6. package/dist/ergo/AbstractErgoExtractorAction.js +4 -6
  7. package/dist/ergo/AbstractErgoExtractorEntity.d.ts.map +1 -1
  8. package/dist/ergo/AbstractErgoExtractorEntity.js +2 -2
  9. package/dist/ergo/initializable/AbstractInitializable.js +1 -1
  10. package/dist/ergo/initializable/AbstractInitializableAction.d.ts +1 -1
  11. package/dist/ergo/initializable/AbstractInitializableAction.d.ts.map +1 -1
  12. package/dist/ergo/initializable/AbstractInitializableAction.js +1 -1
  13. package/dist/ergo/network/AbstractNetwork.js +1 -1
  14. package/dist/ergo/network/ExplorerNetwork.js +1 -1
  15. package/dist/ergo/network/NodeNetwork.js +1 -1
  16. package/package.json +23 -21
  17. package/.eslintignore +0 -1
  18. package/lib/abstractExtractor.ts +0 -31
  19. package/lib/constants.ts +0 -3
  20. package/lib/ergo/AbstractErgoExtractor.ts +0 -227
  21. package/lib/ergo/AbstractErgoExtractorAction.ts +0 -324
  22. package/lib/ergo/AbstractErgoExtractorEntity.ts +0 -28
  23. package/lib/ergo/index.ts +0 -9
  24. package/lib/ergo/initializable/AbstractInitializable.ts +0 -228
  25. package/lib/ergo/initializable/AbstractInitializableAction.ts +0 -29
  26. package/lib/ergo/initializable/index.ts +0 -2
  27. package/lib/ergo/interfaces.ts +0 -51
  28. package/lib/ergo/network/AbstractNetwork.ts +0 -29
  29. package/lib/ergo/network/ExplorerNetwork.ts +0 -237
  30. package/lib/ergo/network/NodeNetwork.ts +0 -169
  31. package/lib/ergo/utils.ts +0 -15
  32. package/lib/index.ts +0 -3
  33. package/tests/AbstractErgoExtractor.mock.ts +0 -33
  34. package/tests/AbstractErgoExtractor.spec.ts +0 -285
  35. package/tests/AbstractErgoExtractorAction.mock.ts +0 -45
  36. package/tests/AbstractErgoExtractorAction.spec.ts +0 -269
  37. package/tests/initializable/AbstractInitializable.mock.ts +0 -44
  38. package/tests/initializable/AbstractInitializable.spec.ts +0 -387
  39. package/tests/initializable/AbstractInitializableAction.mock.ts +0 -45
  40. package/tests/initializable/AbstractInitializableAction.spec.ts +0 -65
  41. package/tests/initializable/testData.ts +0 -283
  42. package/tests/network/ExplorerNetwork.spec.ts +0 -75
  43. package/tests/network/NodeNetwork.spec.ts +0 -57
  44. package/tests/network/testData.ts +0 -1708
  45. package/tests/testData.ts +0 -140
  46. package/tests/testUtils.ts +0 -22
  47. package/tsconfig.build.json +0 -9
  48. package/tsconfig.build.tsbuildinfo +0 -1
  49. package/tsconfig.json +0 -8
  50. package/vitest.config.ts +0 -17
package/package.json CHANGED
@@ -1,48 +1,50 @@
1
1
  {
2
2
  "name": "@rosen-bridge/abstract-extractor",
3
- "version": "2.0.3",
3
+ "version": "2.1.1",
4
4
  "description": "Rosen Bridge extractor interfaces to work with scanner",
5
- "repository": "",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/rosen-bridge/scanner.git"
8
+ },
6
9
  "license": "MIT",
7
10
  "author": "Rosen Team",
8
11
  "type": "module",
9
12
  "main": "dist/index.js",
10
13
  "types": "dist/index.d.ts",
14
+ "files": [
15
+ "dist",
16
+ "CHANGELOG.md"
17
+ ],
11
18
  "scripts": {
12
19
  "build": "tsc --build tsconfig.build.json",
13
20
  "coverage": "npm run test -- --coverage",
14
21
  "lint": "eslint --fix . && npm run prettify",
15
22
  "prettify": "prettier --write . --ignore-path ./.gitignore",
16
23
  "release": "npm run test -- --run && npm run build && npm publish --access public",
17
- "test": "NODE_OPTIONS=--loader=extensionless vitest",
24
+ "test": "NODE_OPTIONS='--import tsx' vitest",
18
25
  "type-check": "tsc --noEmit"
19
26
  },
20
27
  "devDependencies": {
21
28
  "@types/lodash-es": "^4.17.12",
22
- "@types/node": "^20.11.9",
29
+ "@types/node": "^22.18.0",
23
30
  "@types/uuid": "^10.0.0",
24
- "@typescript-eslint/eslint-plugin": "^6.19.1",
25
- "@typescript-eslint/parser": "^6.19.1",
26
- "@vitest/coverage-istanbul": "^1.2.2",
31
+ "@vitest/coverage-istanbul": "^3.1.4",
27
32
  "await-semaphore": "^0.1.3",
28
- "eslint": "^8.56.0",
29
- "eslint-config-prettier": "^9.1.0",
30
- "extensionless": "^1.9.6",
31
- "prettier": "^3.2.4",
33
+ "tsx": "^4.19.4",
32
34
  "typescript": "^5.3.3",
33
- "vitest": "^1.2.2"
34
- },
35
- "engines": {
36
- "node": ">=20.11.0"
35
+ "vitest": "^3.1.4"
37
36
  },
38
37
  "dependencies": {
39
- "@rosen-bridge/abstract-logger": "^2.0.1",
40
- "@rosen-bridge/json-bigint": "^0.1.0",
41
- "@rosen-bridge/scanner-interfaces": "^0.1.1",
42
- "@rosen-clients/ergo-explorer": "^1.1.5",
43
- "@rosen-clients/ergo-node": "^1.2.3",
38
+ "@rosen-bridge/abstract-logger": "^3.0.0",
39
+ "@rosen-bridge/extended-typeorm": "^1.0.0",
40
+ "@rosen-bridge/json-bigint": "^1.0.0",
41
+ "@rosen-bridge/scanner-interfaces": "^0.2.0",
42
+ "@rosen-clients/ergo-explorer": "^2.0.0",
43
+ "@rosen-clients/ergo-node": "^3.0.0",
44
44
  "lodash-es": "^4.17.21",
45
- "typeorm": "^0.3.20",
46
45
  "uuid": "^9.0.0"
46
+ },
47
+ "engines": {
48
+ "node": ">=22.18.0"
47
49
  }
48
50
  }
package/.eslintignore DELETED
@@ -1 +0,0 @@
1
- dist
@@ -1,31 +0,0 @@
1
- import { BlockInfo, Block } from '@rosen-bridge/scanner-interfaces';
2
-
3
- export abstract class AbstractExtractor<TransactionType> {
4
- /**
5
- * process a list of transactions in a block and store required information
6
- * @param txs list of transactions in the block
7
- * @param block
8
- * @return true if the process is completed successfully and false otherwise
9
- */
10
- abstract processTransactions: (
11
- txs: Array<TransactionType>,
12
- block: Block
13
- ) => Promise<boolean>;
14
-
15
- /**
16
- * return extractor id. This id must be unique over all extractors.
17
- */
18
- abstract getId: () => string;
19
-
20
- /**
21
- * fork one block and remove all stored information for this block
22
- * @param hash block hash
23
- */
24
- abstract forkBlock: (hash: string) => Promise<void>;
25
-
26
- /**
27
- * initialize extractor database with data created below the initial height
28
- * @param initialBlock
29
- */
30
- abstract initializeBoxes: (initialBlock: BlockInfo) => Promise<void>;
31
- }
package/lib/constants.ts DELETED
@@ -1,3 +0,0 @@
1
- export const API_LIMIT = 100;
2
- export const RETRIAL_COUNT = 10;
3
- export const DB_CHUNK_SIZE = 100;
@@ -1,227 +0,0 @@
1
- import { AbstractLogger, DummyLogger } from '@rosen-bridge/abstract-logger';
2
- import JsonBigInt from '@rosen-bridge/json-bigint';
3
- import { Mutex } from 'await-semaphore';
4
- import { v4 as uuidv4 } from 'uuid';
5
- import {
6
- Transaction,
7
- OutputBox,
8
- InputExtension,
9
- BlockInfo,
10
- } from '@rosen-bridge/scanner-interfaces';
11
-
12
- import { AbstractExtractor } from '../abstractExtractor';
13
- import { AbstractErgoExtractorAction } from './AbstractErgoExtractorAction';
14
- import {
15
- AbstractBoxData,
16
- SpendInfo,
17
- CallbackType,
18
- CallbackMap,
19
- CallbackDataMap,
20
- TxExtra,
21
- } from './interfaces';
22
- import { AbstractErgoExtractorEntity } from './AbstractErgoExtractorEntity';
23
-
24
- export abstract class AbstractErgoExtractor<
25
- ExtractedData extends AbstractBoxData,
26
- ExtractorEntity extends AbstractErgoExtractorEntity
27
- > extends AbstractExtractor<Transaction> {
28
- protected abstract actions: AbstractErgoExtractorAction<
29
- ExtractedData,
30
- ExtractorEntity
31
- >;
32
- protected logger: AbstractLogger;
33
- protected callbacks: {
34
- [K in CallbackType]: Map<string, CallbackMap<ExtractedData>[K]>;
35
- } = {
36
- [CallbackType.Update]: new Map(),
37
- [CallbackType.Insert]: new Map(),
38
- [CallbackType.Delete]: new Map(),
39
- [CallbackType.Spend]: new Map(),
40
- };
41
- private callbackMutex = new Mutex();
42
-
43
- constructor(logger = new DummyLogger()) {
44
- super();
45
- this.logger = logger;
46
- }
47
-
48
- /**
49
- * hook a new callback on a callback type
50
- * @param type
51
- * @param id
52
- * @param callback
53
- * @returns callback registered id
54
- */
55
- hook = async <T extends CallbackType>(
56
- type: T,
57
- callback: CallbackMap<ExtractedData>[T]
58
- ): Promise<string> => {
59
- const release = await this.callbackMutex.acquire();
60
- const callbackMap = this.callbacks[type];
61
- const id = uuidv4();
62
- callbackMap.set(id, callback);
63
- release();
64
- return id;
65
- };
66
-
67
- /**
68
- * unhook a callback on a type
69
- * returns false if there is no registered callback with the id
70
- * @param type
71
- * @param id
72
- * @returns success status
73
- */
74
- unhook = async (type: CallbackType, id: string): Promise<boolean> => {
75
- const release = await this.callbackMutex.acquire();
76
- const callbackMap = this.callbacks[type];
77
- if (!callbackMap.has(id)) {
78
- this.logger.warn(
79
- `Callback with Id [${id}] is not registered for type [${type}].`
80
- );
81
- return false;
82
- }
83
- callbackMap.delete(id);
84
- release();
85
- return true;
86
- };
87
-
88
- /**
89
- * trigger all callbacks registered on a specific type with the provided data
90
- * @param type
91
- * @param data
92
- */
93
- protected triggerCallbacks<T extends CallbackType>(
94
- type: T,
95
- data: CallbackDataMap<ExtractedData>[T]
96
- ): void {
97
- const callbackMap = this.callbacks[type];
98
- callbackMap.forEach((callback) => {
99
- callback(data);
100
- });
101
- }
102
-
103
- /**
104
- * extract box data to proper format (not including spending information)
105
- * @param box
106
- * @param inputExtensions all input box extensions in transaction
107
- * @return extracted data in proper format
108
- */
109
- abstract extractBoxData: (
110
- box: OutputBox,
111
- inputExtensions: InputExtension[],
112
- txExtra?: TxExtra
113
- ) => ExtractedData | undefined;
114
-
115
- /**
116
- * check proper data format in the box
117
- * @param box
118
- * @return true if the box has the required data and false otherwise
119
- */
120
- abstract hasData: (box: OutputBox) => boolean;
121
-
122
- /**
123
- * create spend info array for the transaction
124
- * @param tx
125
- * @returns spend info array of the transaction
126
- */
127
- getTransactionSpendInfo = (tx: Transaction) => {
128
- let boxIndex = 1;
129
- const spendInfoArray = [];
130
- for (const input of tx.inputs) {
131
- spendInfoArray.push({ txId: tx.id, boxId: input.boxId, index: boxIndex });
132
- boxIndex += 1;
133
- }
134
- return spendInfoArray;
135
- };
136
-
137
- /**
138
- * extract transaction extra information
139
- * override this function if there is extra needed information
140
- * @param tx
141
- * @returns
142
- */
143
- getTransactionExtraData = (
144
- tx: Transaction // eslint-disable-line @typescript-eslint/no-unused-vars
145
- ): TxExtra => {
146
- return {};
147
- };
148
-
149
- /**
150
- * process a list of transactions in a block and store required information
151
- * @param txs list of transactions in the block
152
- * @param block
153
- * @return true if the process is completed successfully and false otherwise
154
- */
155
- processTransactions = async (
156
- txs: Transaction[],
157
- block: BlockInfo
158
- ): Promise<boolean> => {
159
- try {
160
- const boxes: Array<ExtractedData> = [];
161
- const spentInfos: Array<SpendInfo> = [];
162
- for (const tx of txs) {
163
- const inputExtensions = tx.inputs.map((input) => input.extension || {});
164
- for (const output of tx.outputs) {
165
- if (!this.hasData(output)) {
166
- continue;
167
- }
168
- this.logger.debug(`Trying to extract data from box ${output.boxId}`);
169
- const extractedData = this.extractBoxData(
170
- output,
171
- inputExtensions,
172
- this.getTransactionExtraData(tx)
173
- );
174
- if (extractedData) {
175
- this.logger.debug(
176
- `Extracted data ${JsonBigInt.stringify(extractedData)} from box ${
177
- output.boxId
178
- }`
179
- );
180
- boxes.push(extractedData);
181
- }
182
- }
183
- spentInfos.push(...this.getTransactionSpendInfo(tx));
184
- }
185
-
186
- if (boxes.length > 0) {
187
- if (!(await this.actions.storeBoxes(boxes, block, this.getId()))) {
188
- this.logger.warn(
189
- `Data insertion failed for ${this.getId()} at the block ${
190
- block.height
191
- }`
192
- );
193
- return false;
194
- }
195
- this.triggerCallbacks(CallbackType.Insert, boxes);
196
- }
197
- const spentData = await this.actions.spendBoxes(
198
- spentInfos,
199
- block,
200
- this.getId()
201
- );
202
- if (spentData.length > 0) {
203
- this.triggerCallbacks(CallbackType.Spend, spentData);
204
- }
205
- } catch (e) {
206
- this.logger.error(
207
- `Processing transactions failed for ${this.getId()} at the block ${
208
- block.height
209
- } with error: ${e}`
210
- );
211
- return false;
212
- }
213
- return true;
214
- };
215
-
216
- /**
217
- * fork one block and remove all stored information for this block
218
- * @param hash block hash
219
- */
220
- forkBlock = async (hash: string): Promise<void> => {
221
- const result = await this.actions.deleteBlockBoxes(hash, this.getId());
222
- if (result.deletedData.length > 0)
223
- this.triggerCallbacks(CallbackType.Delete, result.deletedData);
224
- if (result.updatedData.length > 0)
225
- this.triggerCallbacks(CallbackType.Update, result.updatedData);
226
- };
227
- }
@@ -1,324 +0,0 @@
1
- import {
2
- DataSource,
3
- In,
4
- Repository,
5
- Not,
6
- EntityTarget,
7
- FindOptionsWhere,
8
- QueryRunner,
9
- } from 'typeorm';
10
- import { chunk, difference, pick } from 'lodash-es';
11
- import { AbstractLogger, DummyLogger } from '@rosen-bridge/abstract-logger';
12
- import JsonBigInt from '@rosen-bridge/json-bigint';
13
- import { BlockInfo } from '@rosen-bridge/scanner-interfaces';
14
-
15
- import { AbstractBoxData, BoxInfo, SpendInfo } from './interfaces';
16
- import { DB_CHUNK_SIZE } from '../constants';
17
- import { AbstractErgoExtractorEntity } from './AbstractErgoExtractorEntity';
18
- import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
19
-
20
- export abstract class AbstractErgoExtractorAction<
21
- ExtractedData extends AbstractBoxData,
22
- ExtractorEntity extends AbstractErgoExtractorEntity
23
- > {
24
- private readonly datasource: DataSource;
25
- readonly logger: AbstractLogger;
26
- protected readonly repository: Repository<ExtractorEntity>;
27
- private repo: EntityTarget<ExtractorEntity>;
28
-
29
- constructor(
30
- dataSource: DataSource,
31
- repo: EntityTarget<ExtractorEntity>,
32
- logger?: AbstractLogger
33
- ) {
34
- this.datasource = dataSource;
35
- this.logger = logger ? logger : new DummyLogger();
36
- this.repository = this.datasource.getRepository(repo);
37
- this.repo = repo;
38
- }
39
-
40
- /**
41
- * create the database entity from extracted data and block information
42
- */
43
- protected createEntity = (
44
- data: ExtractedData[], // eslint-disable-line @typescript-eslint/no-unused-vars
45
- block: BlockInfo, // eslint-disable-line @typescript-eslint/no-unused-vars
46
- extractor: string // eslint-disable-line @typescript-eslint/no-unused-vars
47
- ): Array<Omit<ExtractorEntity, 'id'>> => {
48
- throw Error(
49
- 'You must implement `createEntity` or override `insertEntities` and `updateEntities`'
50
- );
51
- };
52
-
53
- /**
54
- * convert the database entity back to raw data
55
- */
56
- protected convertEntityToData = (
57
- entities: ExtractorEntity[] // eslint-disable-line @typescript-eslint/no-unused-vars
58
- ): ExtractedData[] => {
59
- throw Error(
60
- 'You must implement `convertEntityToData` or override `deleteBlockEntities`'
61
- );
62
- };
63
-
64
- /**
65
- * insert entities extracted from a block to database
66
- * @param queryRunner
67
- * @param boxesToInsert
68
- * @param block
69
- * @param extractor
70
- */
71
- protected insertEntities = async (
72
- queryRunner: QueryRunner,
73
- boxesToInsert: Array<ExtractedData>,
74
- block: BlockInfo,
75
- extractor: string
76
- ) => {
77
- const repository = queryRunner.manager.getRepository(this.repo);
78
- await repository.insert(
79
- this.createEntity(
80
- boxesToInsert,
81
- block,
82
- extractor
83
- ) as unknown as QueryDeepPartialEntity<ExtractorEntity>[]
84
- );
85
- };
86
-
87
- /**
88
- * update entities related to a box
89
- * @param queryRunner
90
- * @param updateBox
91
- * @param block
92
- * @param extractor
93
- */
94
- protected updateEntity = async (
95
- queryRunner: QueryRunner,
96
- updateBox: ExtractedData, // eslint-disable-line @typescript-eslint/no-unused-vars
97
- block: BlockInfo, // eslint-disable-line @typescript-eslint/no-unused-vars
98
- extractor: string
99
- ) => {
100
- const repository = queryRunner.manager.getRepository(this.repo);
101
- const box = this.createEntity([updateBox], block, extractor)[0];
102
- await repository.update(
103
- {
104
- boxId: box.boxId,
105
- extractor: extractor,
106
- } as FindOptionsWhere<ExtractorEntity>,
107
- box as unknown as QueryDeepPartialEntity<ExtractorEntity>
108
- );
109
- };
110
-
111
- /**
112
- * delete all data extracted from a block
113
- * @param queryRunner
114
- * @param extractor
115
- * @param block
116
- * @returns
117
- */
118
- protected deleteBlockEntities = async (
119
- queryRunner: QueryRunner,
120
- extractor: string,
121
- block: string
122
- ): Promise<ExtractedData[]> => {
123
- const repository = queryRunner.manager.getRepository(this.repo);
124
- const deletedData = await repository.find({
125
- where: {
126
- extractor: extractor,
127
- block: block,
128
- } as FindOptionsWhere<ExtractorEntity>,
129
- });
130
- await repository.delete({
131
- extractor: extractor,
132
- block: block,
133
- } as unknown as FindOptionsWhere<ExtractorEntity>);
134
- return this.convertEntityToData(deletedData);
135
- };
136
-
137
- /**
138
- * delete all data extracted from a block
139
- * @param queryRunner
140
- * @param extractor
141
- * @param block
142
- * @returns
143
- */
144
- protected updateBlockEntities = async (
145
- queryRunner: QueryRunner, // eslint-disable-line @typescript-eslint/no-unused-vars
146
- extractor: string,
147
- block: string
148
- ): Promise<ExtractorEntity[]> => {
149
- const repository = this.datasource.getRepository(
150
- this.repo as EntityTarget<new () => ExtractorEntity>
151
- );
152
- const updatedData = await repository.find({
153
- where: {
154
- extractor: extractor,
155
- spendBlock: block,
156
- block: Not(block),
157
- } as unknown as FindOptionsWhere<ExtractorEntity>,
158
- });
159
- await repository.update(
160
- {
161
- spendBlock: block,
162
- extractor: extractor,
163
- } as unknown as FindOptionsWhere<ExtractorEntity>,
164
- {
165
- spendBlock: null,
166
- spendHeight: 0,
167
- }
168
- );
169
- return updatedData as unknown as ExtractorEntity[];
170
- };
171
-
172
- /**
173
- * insert all extracted box data in an atomic transaction
174
- * update the data if a box with the same id is already stored in db
175
- * @param boxes
176
- * @param block
177
- * @param extractor
178
- * @return inserted items and updated box ids
179
- * returns undefined in case of any problem
180
- */
181
- storeBoxes = async (
182
- boxes: Array<ExtractedData>,
183
- block: BlockInfo,
184
- extractor: string
185
- ): Promise<boolean> => {
186
- let boxesToInsert: ExtractedData[] = [],
187
- boxesToUpdate: ExtractedData[] = [];
188
- const queryRunner = this.datasource.createQueryRunner();
189
- await queryRunner.connect();
190
- await queryRunner.startTransaction();
191
- try {
192
- const repository = queryRunner.manager.getRepository(this.repo);
193
- const dbBoxIds = (
194
- await repository.findBy({
195
- boxId: In(boxes.map((item) => item.boxId)),
196
- extractor: extractor,
197
- } as FindOptionsWhere<ExtractorEntity>)
198
- ).map((box) => box.boxId);
199
- if (dbBoxIds.length > 0)
200
- this.logger.debug(`Found stored boxes with same boxId`, dbBoxIds);
201
-
202
- boxesToUpdate = boxes.filter((box) => dbBoxIds.includes(box.boxId));
203
- boxesToInsert = difference(boxes, boxesToUpdate);
204
-
205
- if (boxesToInsert.length > 0) {
206
- this.logger.debug(`Inserting boxes`);
207
- await this.insertEntities(queryRunner, boxesToInsert, block, extractor);
208
- }
209
- if (boxesToUpdate.length > 0)
210
- this.logger.info(
211
- `Updating boxes with following Ids in the database: [${boxesToUpdate
212
- .map((col) => col.boxId)
213
- .join(', ')}]`
214
- );
215
- for (const box of boxesToUpdate) {
216
- this.logger.debug(
217
- `Updating boxes in database [${JsonBigInt.stringify(box)}]`
218
- );
219
- await this.updateEntity(queryRunner, box, block, extractor);
220
- }
221
- await queryRunner.commitTransaction();
222
- return true;
223
- } catch (e) {
224
- this.logger.error(`An error occurred during store boxes action: ${e}`);
225
- await queryRunner.rollbackTransaction();
226
- return false;
227
- } finally {
228
- await queryRunner.release();
229
- }
230
- };
231
-
232
- /**
233
- * update spending information of stored boxes
234
- * chunk spendInfos to prevent large database queries
235
- * Note: It only updates the spendHeight and spendBlock fields. If updating
236
- * anything else is required, override this implementation to include the
237
- * additional fields.
238
- * @param spendInfos
239
- * @param block
240
- * @param extractor
241
- * @returns spent box ids
242
- */
243
- spendBoxes = async (
244
- spendInfos: Array<SpendInfo>,
245
- block: BlockInfo,
246
- extractor: string
247
- ): Promise<BoxInfo[]> => {
248
- const spentData = [];
249
- const spendInfoChunks = chunk(spendInfos, DB_CHUNK_SIZE);
250
- for (const spendInfoChunk of spendInfoChunks) {
251
- const boxIds = spendInfoChunk.map((info) => info.boxId);
252
- const updateResult = await this.repository.update(
253
- {
254
- boxId: In(boxIds),
255
- extractor: extractor,
256
- } as FindOptionsWhere<ExtractorEntity>,
257
- {
258
- spendBlock: block.hash,
259
- spendHeight: block.height,
260
- } as unknown as QueryDeepPartialEntity<ExtractorEntity>
261
- );
262
-
263
- if (updateResult.affected && updateResult.affected > 0) {
264
- const spentRows = await this.repository.findBy({
265
- boxId: In(boxIds),
266
- spendBlock: block.hash,
267
- } as FindOptionsWhere<ExtractorEntity>);
268
- spentData.push(...spentRows);
269
- for (const row of spentRows) {
270
- this.logger.debug(
271
- `Spent box with boxId [${row.boxId}] at height ${block.height}`
272
- );
273
- }
274
- }
275
- }
276
- return spentData.map((data) => pick(data, 'boxId'));
277
- };
278
-
279
- /**
280
- * delete extracted data from a specific block
281
- * if a box is spend in this block mark it as unspent
282
- * if a box is created in this block remove it from database
283
- * @param block
284
- * @param extractor
285
- * @return deleted items and updated box ids
286
- */
287
- deleteBlockBoxes = async (
288
- block: string,
289
- extractor: string
290
- ): Promise<{ deletedData: ExtractedData[]; updatedData: BoxInfo[] }> => {
291
- const queryRunner = this.datasource.createQueryRunner();
292
- await queryRunner.connect();
293
- await queryRunner.startTransaction();
294
- try {
295
- this.logger.info(
296
- `Deleting boxes in block ${block} and extractor ${extractor}`
297
- );
298
- const updatedData = await this.updateBlockEntities(
299
- queryRunner,
300
- extractor,
301
- block
302
- );
303
- const deletedData = await this.deleteBlockEntities(
304
- queryRunner,
305
- extractor,
306
- block
307
- );
308
- await queryRunner.commitTransaction();
309
- return {
310
- deletedData,
311
- updatedData: updatedData.map((data) => pick(data, 'boxId')),
312
- };
313
- } catch (error) {
314
- await queryRunner.rollbackTransaction();
315
- this.logger.error(
316
- `An error occurred while deleting data extracted from block ${block}`,
317
- error
318
- );
319
- throw error;
320
- } finally {
321
- await queryRunner.release();
322
- }
323
- };
324
- }
@@ -1,28 +0,0 @@
1
- import { Column, PrimaryGeneratedColumn, Unique } from 'typeorm';
2
-
3
- @Unique(['boxId', 'extractor'])
4
- export abstract class AbstractErgoExtractorEntity {
5
- @PrimaryGeneratedColumn()
6
- id: number;
7
-
8
- @Column({ type: 'varchar' })
9
- boxId: string;
10
-
11
- @Column({ type: 'varchar' })
12
- block: string;
13
-
14
- @Column({ type: 'int' })
15
- height: number;
16
-
17
- @Column({ nullable: true, type: 'varchar' })
18
- spendBlock?: string | null;
19
-
20
- @Column({ nullable: true, type: 'int' })
21
- spendHeight?: number | null;
22
-
23
- @Column({ type: 'varchar' })
24
- extractor: string;
25
-
26
- @Column({ type: 'varchar' })
27
- serialized: string;
28
- }
package/lib/ergo/index.ts DELETED
@@ -1,9 +0,0 @@
1
- export * from './AbstractErgoExtractor';
2
- export * from './AbstractErgoExtractorAction';
3
- export * from './interfaces';
4
- export * from './network/ExplorerNetwork';
5
- export * from './network/NodeNetwork';
6
- export * from './network/AbstractNetwork';
7
- export * from './initializable';
8
- export * from './utils';
9
- export * from './AbstractErgoExtractorEntity';