@rosen-bridge/fraud-extractor 0.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.
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Fraud Extractor
2
+
3
+ ### Table of Contents
4
+
5
+ - [Description](#description)
6
+ - [Related Projects](#related-projects)
7
+ - [How to Use the Fraud Extractor](#how-to-use-the-fraud-extractor)
8
+ - [Install](#install)
9
+ - [Usage](#usage)
10
+ - [Contributing](#contributing)
11
+ - [License](#license)
12
+
13
+ <a name="headers"/>
14
+
15
+ ## Description
16
+
17
+ Data extractors are modules that are integrated within a scanner. They drive the required information from the scanned blocks and store them in their own database. Fraud extractor, extracts fraud boxes information from blocks and stores them in the database. Cleanup service creates frauds from timed out unspent triggers; these triggers might have incorrect data or be a duplicated version of a valid trigger. Then the fraud funds will be seized by the service to punish the faulty reports.
18
+
19
+ ## Related Projects
20
+
21
+ TBD
22
+
23
+ ## How to Use the Fraud Extractor
24
+
25
+ ### Install
26
+
27
+ TBD
28
+
29
+ ### Usage
30
+
31
+ TBD
32
+
33
+ ## Contributing
34
+
35
+ TBD
36
+
37
+ ## License
38
+
39
+ TBD
@@ -0,0 +1,64 @@
1
+ import { DataSource } from 'typeorm';
2
+ import { AbstractLogger } from '@rosen-bridge/abstract-logger';
3
+ import { BlockEntity } from '@rosen-bridge/scanner';
4
+ import { ExtractedFraud } from '../interfaces/types';
5
+ export declare class FraudAction {
6
+ private readonly datasource;
7
+ private readonly logger;
8
+ private readonly repository;
9
+ constructor(dataSource: DataSource, logger: AbstractLogger);
10
+ /**
11
+ * Store a list of frauds in a specific block
12
+ * @param frauds
13
+ * @param spendBoxes
14
+ * @param block
15
+ * @param extractor
16
+ */
17
+ storeBlockFrauds: (frauds: Array<ExtractedFraud>, block: BlockEntity, extractor: string) => Promise<boolean>;
18
+ /**
19
+ * Insert a new fraud into database
20
+ * @param fraud
21
+ * @param extractor
22
+ */
23
+ insertFraud: (fraud: ExtractedFraud, extractor: string) => Promise<import("typeorm").InsertResult>;
24
+ /**
25
+ * Update an unspent fraud information in the database
26
+ * @param fraud
27
+ * @param extractor
28
+ */
29
+ updateFraud: (fraud: ExtractedFraud, extractor: string) => Promise<import("typeorm").UpdateResult>;
30
+ /**
31
+ * Update spendBlock and spendHeight of frauds spent on the block
32
+ * @param spendIds
33
+ * @param block
34
+ * @param extractor
35
+ */
36
+ spendFrauds: (spendIds: Array<string>, block: BlockEntity, extractor: string, txId: string) => Promise<void>;
37
+ /**
38
+ * Update all frauds related to an specific invalid block
39
+ * if box had been spent in the block mark it as unspent,
40
+ * and if it was created within the block remove it from database
41
+ * @param block
42
+ * @param extractor
43
+ */
44
+ deleteBlock: (block: string, extractor: string) => Promise<void>;
45
+ /**
46
+ * Return all stored fraud box ids
47
+ */
48
+ getAllBoxIds: (extractor: string) => Promise<Array<string>>;
49
+ /**
50
+ * Remove an specified fraud
51
+ * @param boxId
52
+ * @param extractor
53
+ */
54
+ removeFraud: (boxId: string, extractor: string) => Promise<import("typeorm").DeleteResult>;
55
+ /**
56
+ * Update the fraud spending information
57
+ * @param boxId
58
+ * @param extractor
59
+ * @param blockId
60
+ * @param blockHeight
61
+ */
62
+ updateSpendBlock: (boxId: string, extractor: string, blockId: string, blockHeight: number) => Promise<import("typeorm").UpdateResult>;
63
+ }
64
+ //# sourceMappingURL=fraudAction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fraudAction.d.ts","sourceRoot":"","sources":["../../lib/actions/fraudAction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAkB,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0B;gBAEzC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc;IAK1D;;;;;;OAMG;IACH,gBAAgB,WACN,MAAM,cAAc,CAAC,SACtB,WAAW,aACP,MAAM,sBAgDjB;IAEF;;;;OAIG;IACH,WAAW,UAAiB,cAAc,aAAa,MAAM,6CAY3D;IAEF;;;;OAIG;IACH,WAAW,UAAiB,cAAc,aAAa,MAAM,6CAe3D;IAEF;;;;;OAKG;IACH,WAAW,aACC,MAAM,MAAM,CAAC,SAChB,WAAW,aACP,MAAM,QACX,MAAM,KACX,QAAQ,IAAI,CAAC,CAqBd;IAEF;;;;;;OAMG;IACH,WAAW,UAAiB,MAAM,aAAa,MAAM,KAAG,QAAQ,IAAI,CAAC,CAgCnE;IAEF;;OAEG;IACH,YAAY,cAAqB,MAAM,KAAG,QAAQ,MAAM,MAAM,CAAC,CAAC,CAU9D;IAEF;;;;OAIG;IACH,WAAW,UAAiB,MAAM,aAAa,MAAM,6CAEnD;IAEF;;;;;;OAMG;IACH,gBAAgB,UACP,MAAM,aACF,MAAM,WACR,MAAM,eACF,MAAM,6CAMnB;CACH"}
@@ -0,0 +1,196 @@
1
+ import { In } from 'typeorm';
2
+ import { FraudEntity } from '../entities/fraudEntity';
3
+ import { dbIdChunkSize } from '../constants';
4
+ import { chunk } from 'lodash-es';
5
+ export class FraudAction {
6
+ datasource;
7
+ logger;
8
+ repository;
9
+ constructor(dataSource, logger) {
10
+ this.datasource = dataSource;
11
+ this.logger = logger;
12
+ this.repository = dataSource.getRepository(FraudEntity);
13
+ }
14
+ /**
15
+ * Store a list of frauds in a specific block
16
+ * @param frauds
17
+ * @param spendBoxes
18
+ * @param block
19
+ * @param extractor
20
+ */
21
+ storeBlockFrauds = async (frauds, block, extractor) => {
22
+ const boxIds = frauds.map((item) => item.boxId);
23
+ const dbBoxes = await this.repository.findBy({
24
+ boxId: In(boxIds),
25
+ extractor: extractor,
26
+ });
27
+ let success = true;
28
+ const queryRunner = this.datasource.createQueryRunner();
29
+ await queryRunner.connect();
30
+ await queryRunner.startTransaction();
31
+ const repository = await queryRunner.manager.getRepository(FraudEntity);
32
+ try {
33
+ for (const fraud of frauds) {
34
+ const entity = {
35
+ triggerBoxId: fraud.triggerBoxId,
36
+ boxId: fraud.boxId,
37
+ wid: fraud.wid,
38
+ rwtCount: fraud.rwtCount,
39
+ creationBlock: block.hash,
40
+ creationHeight: block.height,
41
+ creationTxId: fraud.txId,
42
+ serialized: fraud.serialized,
43
+ extractor: extractor,
44
+ spendBlock: undefined,
45
+ spendHeight: undefined,
46
+ spendTxId: undefined,
47
+ };
48
+ const dbBox = dbBoxes.filter((item) => item.boxId === fraud.boxId);
49
+ if (dbBox.length > 0) {
50
+ this.logger.info(`Updating fraud with boxId [${fraud.boxId}]`);
51
+ this.logger.debug(`Updated fraud: [${JSON.stringify(entity)}]`);
52
+ await repository.update({ id: dbBox[0].id }, entity);
53
+ }
54
+ else {
55
+ this.logger.info(`Storing fraud with boxId: [${fraud.boxId}]`);
56
+ this.logger.debug(`Inserted fraud: [${JSON.stringify(entity)}]`);
57
+ await repository.insert(entity);
58
+ }
59
+ }
60
+ await queryRunner.commitTransaction();
61
+ }
62
+ catch (e) {
63
+ this.logger.error(`An error occurred during storing fraud boxes: ${e}`);
64
+ await queryRunner.rollbackTransaction();
65
+ success = false;
66
+ }
67
+ finally {
68
+ await queryRunner.release();
69
+ }
70
+ return success;
71
+ };
72
+ /**
73
+ * Insert a new fraud into database
74
+ * @param fraud
75
+ * @param extractor
76
+ */
77
+ insertFraud = async (fraud, extractor) => {
78
+ return this.repository.insert({
79
+ boxId: fraud.boxId,
80
+ triggerBoxId: fraud.triggerBoxId,
81
+ wid: fraud.wid,
82
+ rwtCount: fraud.rwtCount,
83
+ creationBlock: fraud.blockId,
84
+ creationHeight: fraud.height,
85
+ creationTxId: fraud.txId,
86
+ serialized: fraud.serialized,
87
+ extractor: extractor,
88
+ });
89
+ };
90
+ /**
91
+ * Update an unspent fraud information in the database
92
+ * @param fraud
93
+ * @param extractor
94
+ */
95
+ updateFraud = async (fraud, extractor) => {
96
+ return this.repository.update({ boxId: fraud.boxId, extractor: extractor }, {
97
+ triggerBoxId: fraud.triggerBoxId,
98
+ creationBlock: fraud.blockId,
99
+ creationHeight: fraud.height,
100
+ creationTxId: fraud.txId,
101
+ serialized: fraud.serialized,
102
+ wid: fraud.wid,
103
+ rwtCount: fraud.rwtCount,
104
+ spendBlock: null,
105
+ spendHeight: 0,
106
+ });
107
+ };
108
+ /**
109
+ * Update spendBlock and spendHeight of frauds spent on the block
110
+ * @param spendIds
111
+ * @param block
112
+ * @param extractor
113
+ */
114
+ spendFrauds = async (spendIds, block, extractor, txId) => {
115
+ const spendIdChunks = chunk(spendIds, dbIdChunkSize);
116
+ for (const spendIdChunk of spendIdChunks) {
117
+ const updateResult = await this.repository.update({ boxId: In(spendIdChunk), extractor: extractor }, { spendBlock: block.hash, spendHeight: block.height, spendTxId: txId });
118
+ if (updateResult.affected && updateResult.affected > 0) {
119
+ const spentRows = await this.repository.findBy({
120
+ boxId: In(spendIdChunk),
121
+ spendBlock: block.hash,
122
+ spendTxId: txId,
123
+ });
124
+ for (const row of spentRows) {
125
+ this.logger.debug(`Spent box with boxId [${row.boxId}] at transaction [${txId}] at height ${block.height}`);
126
+ }
127
+ }
128
+ }
129
+ };
130
+ /**
131
+ * Update all frauds related to an specific invalid block
132
+ * if box had been spent in the block mark it as unspent,
133
+ * and if it was created within the block remove it from database
134
+ * @param block
135
+ * @param extractor
136
+ */
137
+ deleteBlock = async (block, extractor) => {
138
+ this.logger.info(`Deleting frauds in block [${block}]`);
139
+ const invalidRows = await this.repository.findBy({
140
+ extractor: extractor,
141
+ creationBlock: block,
142
+ });
143
+ if (invalidRows.length > 0) {
144
+ await this.repository.delete({
145
+ extractor: extractor,
146
+ creationBlock: block,
147
+ });
148
+ for (const row of invalidRows) {
149
+ this.logger.debug(`deleted invalid fraud with boxId [${row.boxId}] at the forked block [${block}]`);
150
+ }
151
+ }
152
+ const updatingRows = await this.repository.findBy({
153
+ extractor: extractor,
154
+ spendBlock: block,
155
+ });
156
+ if (updatingRows.length > 0) {
157
+ await this.repository.update({ spendBlock: block, extractor: extractor }, { spendBlock: null, spendHeight: 0, spendTxId: null });
158
+ for (const row of updatingRows) {
159
+ this.logger.debug(`removed spending information of the fraud with boxId [${row.boxId}], spent at the forked block [${block}]`);
160
+ }
161
+ }
162
+ };
163
+ /**
164
+ * Return all stored fraud box ids
165
+ */
166
+ getAllBoxIds = async (extractor) => {
167
+ const boxIds = await this.repository.find({
168
+ select: {
169
+ boxId: true,
170
+ },
171
+ where: {
172
+ extractor: extractor,
173
+ },
174
+ });
175
+ return boxIds.map((item) => item.boxId);
176
+ };
177
+ /**
178
+ * Remove an specified fraud
179
+ * @param boxId
180
+ * @param extractor
181
+ */
182
+ removeFraud = async (boxId, extractor) => {
183
+ return await this.repository.delete({ boxId: boxId, extractor: extractor });
184
+ };
185
+ /**
186
+ * Update the fraud spending information
187
+ * @param boxId
188
+ * @param extractor
189
+ * @param blockId
190
+ * @param blockHeight
191
+ */
192
+ updateSpendBlock = async (boxId, extractor, blockId, blockHeight) => {
193
+ return await this.repository.update({ boxId: boxId, extractor: extractor }, { spendBlock: blockId, spendHeight: blockHeight });
194
+ };
195
+ }
196
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhdWRBY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvYWN0aW9ucy9mcmF1ZEFjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWMsRUFBRSxFQUFjLE1BQU0sU0FBUyxDQUFDO0FBSXJELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV0RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFbEMsTUFBTSxPQUFPLFdBQVc7SUFDTCxVQUFVLENBQWE7SUFDdkIsTUFBTSxDQUFpQjtJQUN2QixVQUFVLENBQTBCO0lBRXJELFlBQVksVUFBc0IsRUFBRSxNQUFzQjtRQUN4RCxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUNEOzs7Ozs7T0FNRztJQUNILGdCQUFnQixHQUFHLEtBQUssRUFDdEIsTUFBNkIsRUFDN0IsS0FBa0IsRUFDbEIsU0FBaUIsRUFDakIsRUFBRTtRQUNGLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoRCxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDO1lBQzNDLEtBQUssRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDO1lBQ2pCLFNBQVMsRUFBRSxTQUFTO1NBQ3JCLENBQUMsQ0FBQztRQUNILElBQUksT0FBTyxHQUFHLElBQUksQ0FBQztRQUNuQixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsVUFBVSxD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QUssRUFBRSxLQUFhLEVBQUUsU0FBaUIsRUFBRSxFQUFFO1FBQ3ZELE9BQU8sTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFDOUUsQ0FBQyxDQUFDO0lBRUY7Ozs7OztPQU1HO0lBQ0gsZ0JBQWdCLEdBQUcsS0FBSyxFQUN0QixLQUFhLEVBQ2IsU0FBaUIsRUFDakIsT0FBZSxFQUNmLFdBQW1CLEVBQ25CLEVBQUU7UUFDRixPQUFPLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQ2pDLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEVBQ3RDLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLENBQ2xELENBQUM7SUFDSixDQUFDLENBQUM7Q0FDSCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGFTb3VyY2UsIEluLCBSZXBvc2l0b3J5IH0gZnJvbSAndHlwZW9ybSc7XG5pbXBvcnQgeyBBYnN0cmFjdExvZ2dlciB9IGZyb20gJ0Byb3Nlbi1icmlkZ2UvYWJzdHJhY3QtbG9nZ2VyJztcbmltcG9ydCB7IEJsb2NrRW50aXR5IH0gZnJvbSAnQHJvc2VuLWJyaWRnZS9zY2FubmVyJztcblxuaW1wb3J0IHsgRnJhdWRFbnRpdHkgfSBmcm9tICcuLi9lbnRpdGllcy9mcmF1ZEVudGl0eSc7XG5pbXBvcnQgeyBFeHRyYWN0ZWRGcmF1ZCB9IGZyb20gJy4uL2ludGVyZmFjZXMvdHlwZXMnO1xuaW1wb3J0IHsgZGJJZENodW5rU2l6ZSB9IGZyb20gJy4uL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBjaHVuayB9IGZyb20gJ2xvZGFzaC1lcyc7XG5cbmV4cG9ydCBjbGFzcyBGcmF1ZEFjdGlvbiB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGF0YXNvdXJjZTogRGF0YVNvdXJjZTtcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXI6IEFic3RyYWN0TG9nZ2VyO1xuICBwcml2YXRlIHJlYWRvbmx5IHJlcG9zaXRvcnk6IFJlcG9zaXRvcnk8RnJhdWRFbnRpdHk+O1xuXG4gIGNvbnN0cnVjdG9yKGRhdGFTb3VyY2U6IERhdGFTb3VyY2UsIGxvZ2dlcjogQWJzdHJhY3RMb2dnZXIpIHtcbiAgICB0aGlzLmRhdGFzb3VyY2UgPSBkYXRhU291cmNlO1xuICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyO1xuICAgIHRoaXMucmVwb3NpdG9yeSA9IGRhdGFTb3VyY2UuZ2V0UmVwb3NpdG9yeShGcmF1ZEVudGl0eSk7XG4gIH1cbiAgLyoqXG4gICAqIFN0b3JlIGEgbGlzdCBvZiBmcmF1ZHMgaW4gYSBzcGVjaWZpYyBibG9ja1xuICAgKiBAcGFyYW0gZnJhdWRzXG4gICAqIEBwYXJhbSBzcGVuZEJveGVzXG4gICAqIEBwYXJhbSBibG9ja1xuICAgKiBAcGFyYW0gZXh0cmFjdG9yXG4gICAqL1xuICBzdG9yZUJsb2NrRnJhdWRzID0gYXN5bmMgKFxuICAgIGZyYXVkczogQXJyYXk8RXh0cmFjdGVkRnJhdWQ+LFxuICAgIGJsb2NrOiBCbG9ja0VudGl0eSxcbiAgICBleHRyYWN0b3I6IHN0cmluZ1xuICApID0+IHtcbiAgICBjb25zdCBib3hJZHMgPSBmcmF1ZHMubWFwKChpdGVtKSA9PiBpdGVtLmJveElkKTtcbiAgICBjb25zdCBkYkJveGVzID0gYXdhaXQgdGhpcy5yZXBvc2l0b3J5LmZpbmRCeSh7XG4gICAgICBib3hJZDogSW4oYm94SWRzKSxcbiAgICAgIGV4dHJhY3RvcjogZXh0cmFjdG9yLFxuICAgIH0pO1xuICAgIGxldCBzdWNjZXNzID0gdHJ1ZTtcbiAgICBjb25zdCBxdWVyeVJ1bm5lciA9IHRoaXMuZGF0YXNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lcigpO1xuICAgIGF3YWl0IHF1ZXJ5UnVubmVyLmNvbm5lY3QoKTtcbiAgICBhd2FpdCBxdWVyeVJ1bm5lci5zdGFydFRyYW5zYWN0aW9uKCk7XG4gICAgY29uc3QgcmVwb3NpdG9yeSA9IGF3YWl0IHF1ZXJ5UnVubmVyLm1hbmFnZXIuZ2V0UmVwb3NpdG9yeShGcmF1ZEVudGl0eSk7XG4gICAgdHJ5IHtcbiAgICAgIGZvciAoY29uc3QgZnJhdWQgb2YgZnJhdWRzKSB7XG4gICAgICAgIGNvbnN0IGVudGl0eSA9IHtcbiAgICAgICAgICB0cmlnZ2VyQm94SWQ6IGZyYXVkLnRyaWdnZXJCb3hJZCxcbiAgICAgICAgICBib3hJZDogZnJhdWQuYm94SWQsXG4gICAgICAgICAgd2lkOiBmcmF1ZC53aWQsXG4gICAgICAgICAgcnd0Q291bnQ6IGZyYXVkLnJ3dENvdW50LFxuICAgICAgICAgIGNyZWF0aW9uQmxvY2s6IGJsb2NrLmhhc2gsXG4gICAgICAgICAgY3JlYXRpb25IZWlnaHQ6IGJsb2NrLmhlaWdodCxcbiAgICAgICAgICBjcmVhdGlvblR4SWQ6IGZyYXVkLnR4SWQsXG4gICAgICAgICAgc2VyaWFsaXplZDogZnJhdWQuc2VyaWFsaXplZCxcbiAgICAgICAgICBleHRyYWN0b3I6IGV4dHJhY3RvcixcbiAgICAgICAgICBzcGVuZEJsb2NrOiB1bmRlZmluZWQsXG4gICAgICAgICAgc3BlbmRIZWlnaHQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICBzcGVuZFR4SWQ6IHVuZGVmaW5lZCxcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZGJCb3ggPSBkYkJveGVzLmZpbHRlcigoaXRlbSkgPT4gaXRlbS5ib3hJZCA9PT0gZnJhdWQuYm94SWQpO1xuICAgICAgICBpZiAoZGJCb3gubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLmluZm8oYFVwZGF0aW5nIGZyYXVkIHdpdGggYm94SWQgWyR7ZnJhdWQuYm94SWR9XWApO1xuICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKGBVcGRhdGVkIGZyYXVkOiBbJHtKU09OLnN0cmluZ2lmeShlbnRpdHkpfV1gKTtcbiAgICAgICAgICBhd2FpdCByZXBvc2l0b3J5LnVwZGF0ZSh7IGlkOiBkYkJveFswXS5pZCB9LCBlbnRpdHkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLmluZm8oYFN0b3JpbmcgZnJhdWQgd2l0aCBib3hJZDogWyR7ZnJhdWQuYm94SWR9XWApO1xuICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKGBJbnNlcnRlZCBmcmF1ZDogWyR7SlNPTi5zdHJpbmdpZnkoZW50aXR5KX1dYCk7XG4gICAgICAgICAgYXdhaXQgcmVwb3NpdG9yeS5pbnNlcnQoZW50aXR5KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIuY29tbWl0VHJhbnNhY3Rpb24oKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihgQW4gZXJyb3Igb2NjdXJyZWQgZHVyaW5nIHN0b3JpbmcgZnJhdWQgYm94ZXM6ICR7ZX1gKTtcbiAgICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnJvbGxiYWNrVHJhbnNhY3Rpb24oKTtcbiAgICAgIHN1Y2Nlc3MgPSBmYWxzZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgcXVlcnlSdW5uZXIucmVsZWFzZSgpO1xuICAgIH1cbiAgICByZXR1cm4gc3VjY2VzcztcbiAgfTtcblxuICAvKipcbiAgICogSW5zZXJ0IGEgbmV3IGZyYXVkIGludG8gZGF0YWJhc2VcbiAgICogQHBhcmFtIGZyYXVkXG4gICAqIEBwYXJhbSBleHRyYWN0b3JcbiAgICovXG4gIGluc2VydEZyYXVkID0gYXN5bmMgKGZyYXVkOiBFeHRyYWN0ZWRGcmF1ZCwgZXh0cmFjdG9yOiBzdHJpbmcpID0+IHtcbiAgICByZXR1cm4gdGhpcy5yZXBvc2l0b3J5Lmluc2VydCh7XG4gICAgICBib3hJZDogZnJhdWQuYm94SWQsXG4gICAgICB0cmlnZ2VyQm94SWQ6IGZyYXVkLnRyaWdnZXJCb3hJZCxcbiAgICAgIHdpZDogZnJhdWQud2lkLFxuICAgICAgcnd0Q291bnQ6IGZyYXVkLnJ3dENvdW50LFxuICAgICAgY3JlYXRpb25CbG9jazogZnJhdWQuYmxvY2tJZCxcbiAgICAgIGNyZWF0aW9uSGVpZ2h0OiBmcmF1ZC5oZWlnaHQsXG4gICAgICBjcmVhdGlvblR4SWQ6IGZyYXVkLnR4SWQsXG4gICAgICBzZXJpYWxpemVkOiBmcmF1ZC5zZXJpYWxpemVkLFxuICAgICAgZXh0cmFjdG9yOiBleHRyYWN0b3IsXG4gICAgfSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBhbiB1bnNwZW50IGZyYXVkIGluZm9ybWF0aW9uIGluIHRoZSBkYXRhYmFzZVxuICAgKiBAcGFyYW0gZnJhdWRcbiAgICogQHBhcmFtIGV4dHJhY3RvclxuICAgKi9cbiAgdXBkYXRlRnJhdWQgPSBhc3luYyAoZnJhdWQ6IEV4dHJhY3RlZEZyYXVkLCBleHRyYWN0b3I6IHN0cmluZykgPT4ge1xuICAgIHJldHVybiB0aGlzLnJlcG9zaXRvcnkudXBkYXRlKFxuICAgICAgeyBib3hJZDogZnJhdWQuYm94SWQsIGV4dHJhY3RvcjogZXh0cmFjdG9yIH0sXG4gICAgICB7XG4gICAgICAgIHRyaWdnZXJCb3hJZDogZnJhdWQudHJpZ2dlckJveElkLFxuICAgICAgICBjcmVhdGlvbkJsb2NrOiBmcmF1ZC5ibG9ja0lkLFxuICAgICAgICBjcmVhdGlvbkhlaWdodDogZnJhdWQuaGVpZ2h0LFxuICAgICAgICBjcmVhdGlvblR4SWQ6IGZyYXVkLnR4SWQsXG4gICAgICAgIHNlcmlhbGl6ZWQ6IGZyYXVkLnNlcmlhbGl6ZWQsXG4gICAgICAgIHdpZDogZnJhdWQud2lkLFxuICAgICAgICByd3RDb3VudDogZnJhdWQucnd0Q291bnQsXG4gICAgICAgIHNwZW5kQmxvY2s6IG51bGwsXG4gICAgICAgIHNwZW5kSGVpZ2h0OiAwLFxuICAgICAgfVxuICAgICk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBzcGVuZEJsb2NrIGFuZCBzcGVuZEhlaWdodCBvZiBmcmF1ZHMgc3BlbnQgb24gdGhlIGJsb2NrXG4gICAqIEBwYXJhbSBzcGVuZElkc1xuICAgKiBAcGFyYW0gYmxvY2tcbiAgICogQHBhcmFtIGV4dHJhY3RvclxuICAgKi9cbiAgc3BlbmRGcmF1ZHMgPSBhc3luYyAoXG4gICAgc3BlbmRJZHM6IEFycmF5PHN0cmluZz4sXG4gICAgYmxvY2s6IEJsb2NrRW50aXR5LFxuICAgIGV4dHJhY3Rvcjogc3RyaW5nLFxuICAgIHR4SWQ6IHN0cmluZ1xuICApOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICBjb25zdCBzcGVuZElkQ2h1bmtzID0gY2h1bmsoc3BlbmRJZHMsIGRiSWRDaHVua1NpemUpO1xuICAgIGZvciAoY29uc3Qgc3BlbmRJZENodW5rIG9mIHNwZW5kSWRDaHVua3MpIHtcbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3VsdCA9IGF3YWl0IHRoaXMucmVwb3NpdG9yeS51cGRhdGUoXG4gICAgICAgIHsgYm94SWQ6IEluKHNwZW5kSWRDaHVuayksIGV4dHJhY3RvcjogZXh0cmFjdG9yIH0sXG4gICAgICAgIHsgc3BlbmRCbG9jazogYmxvY2suaGFzaCwgc3BlbmRIZWlnaHQ6IGJsb2NrLmhlaWdodCwgc3BlbmRUeElkOiB0eElkIH1cbiAgICAgICk7XG5cbiAgICAgIGlmICh1cGRhdGVSZXN1bHQuYWZmZWN0ZWQgJiYgdXBkYXRlUmVzdWx0LmFmZmVjdGVkID4gMCkge1xuICAgICAgICBjb25zdCBzcGVudFJvd3MgPSBhd2FpdCB0aGlzLnJlcG9zaXRvcnkuZmluZEJ5KHtcbiAgICAgICAgICBib3hJZDogSW4oc3BlbmRJZENodW5rKSxcbiAgICAgICAgICBzcGVuZEJsb2NrOiBibG9jay5oYXNoLFxuICAgICAgICAgIHNwZW5kVHhJZDogdHhJZCxcbiAgICAgICAgfSk7XG4gICAgICAgIGZvciAoY29uc3Qgcm93IG9mIHNwZW50Um93cykge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgYFNwZW50IGJveCB3aXRoIGJveElkIFske3Jvdy5ib3hJZH1dIGF0IHRyYW5zYWN0aW9uIFske3R4SWR9XSBhdCBoZWlnaHQgJHtibG9jay5oZWlnaHR9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBhbGwgZnJhdWRzIHJlbGF0ZWQgdG8gYW4gc3BlY2lmaWMgaW52YWxpZCBibG9ja1xuICAgKiBpZiBib3ggaGFkIGJlZW4gc3BlbnQgaW4gdGhlIGJsb2NrIG1hcmsgaXQgYXMgdW5zcGVudCxcbiAgICogYW5kIGlmIGl0IHdhcyBjcmVhdGVkIHdpdGhpbiB0aGUgYmxvY2sgcmVtb3ZlIGl0IGZyb20gZGF0YWJhc2VcbiAgICogQHBhcmFtIGJsb2NrXG4gICAqIEBwYXJhbSBleHRyYWN0b3JcbiAgICovXG4gIGRlbGV0ZUJsb2NrID0gYXN5bmMgKGJsb2NrOiBzdHJpbmcsIGV4dHJhY3Rvcjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgdGhpcy5sb2dnZXIuaW5mbyhgRGVsZXRpbmcgZnJhdWRzIGluIGJsb2NrIFske2Jsb2NrfV1gKTtcbiAgICBjb25zdCBpbnZhbGlkUm93cyA9IGF3YWl0IHRoaXMucmVwb3NpdG9yeS5maW5kQnkoe1xuICAgICAgZXh0cmFjdG9yOiBleHRyYWN0b3IsXG4gICAgICBjcmVhdGlvbkJsb2NrOiBibG9jayxcbiAgICB9KTtcbiAgICBpZiAoaW52YWxpZFJvd3MubGVuZ3RoID4gMCkge1xuICAgICAgYXdhaXQgdGhpcy5yZXBvc2l0b3J5LmRlbGV0ZSh7XG4gICAgICAgIGV4dHJhY3RvcjogZXh0cmFjdG9yLFxuICAgICAgICBjcmVhdGlvbkJsb2NrOiBibG9jayxcbiAgICAgIH0pO1xuICAgICAgZm9yIChjb25zdCByb3cgb2YgaW52YWxpZFJvd3MpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICAgICAgYGRlbGV0ZWQgaW52YWxpZCBmcmF1ZCB3aXRoIGJveElkIFske3Jvdy5ib3hJZH1dIGF0IHRoZSBmb3JrZWQgYmxvY2sgWyR7YmxvY2t9XWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgdXBkYXRpbmdSb3dzID0gYXdhaXQgdGhpcy5yZXBvc2l0b3J5LmZpbmRCeSh7XG4gICAgICBleHRyYWN0b3I6IGV4dHJhY3RvcixcbiAgICAgIHNwZW5kQmxvY2s6IGJsb2NrLFxuICAgIH0pO1xuICAgIGlmICh1cGRhdGluZ1Jvd3MubGVuZ3RoID4gMCkge1xuICAgICAgYXdhaXQgdGhpcy5yZXBvc2l0b3J5LnVwZGF0ZShcbiAgICAgICAgeyBzcGVuZEJsb2NrOiBibG9jaywgZXh0cmFjdG9yOiBleHRyYWN0b3IgfSxcbiAgICAgICAgeyBzcGVuZEJsb2NrOiBudWxsLCBzcGVuZEhlaWdodDogMCwgc3BlbmRUeElkOiBudWxsIH1cbiAgICAgICk7XG4gICAgICBmb3IgKGNvbnN0IHJvdyBvZiB1cGRhdGluZ1Jvd3MpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICAgICAgYHJlbW92ZWQgc3BlbmRpbmcgaW5mb3JtYXRpb24gb2YgdGhlIGZyYXVkIHdpdGggYm94SWQgWyR7cm93LmJveElkfV0sIHNwZW50IGF0IHRoZSBmb3JrZWQgYmxvY2sgWyR7YmxvY2t9XWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIFJldHVybiBhbGwgc3RvcmVkIGZyYXVkIGJveCBpZHNcbiAgICovXG4gIGdldEFsbEJveElkcyA9IGFzeW5jIChleHRyYWN0b3I6IHN0cmluZyk6IFByb21pc2U8QXJyYXk8c3RyaW5nPj4gPT4ge1xuICAgIGNvbnN0IGJveElkcyA9IGF3YWl0IHRoaXMucmVwb3NpdG9yeS5maW5kKHtcbiAgICAgIHNlbGVjdDoge1xuICAgICAgICBib3hJZDogdHJ1ZSxcbiAgICAgIH0sXG4gICAgICB3aGVyZToge1xuICAgICAgICBleHRyYWN0b3I6IGV4dHJhY3RvcixcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgcmV0dXJuIGJveElkcy5tYXAoKGl0ZW06IHsgYm94SWQ6IHN0cmluZyB9KSA9PiBpdGVtLmJveElkKTtcbiAgfTtcblxuICAvKipcbiAgICogUmVtb3ZlIGFuIHNwZWNpZmllZCBmcmF1ZFxuICAgKiBAcGFyYW0gYm94SWRcbiAgICogQHBhcmFtIGV4dHJhY3RvclxuICAgKi9cbiAgcmVtb3ZlRnJhdWQgPSBhc3luYyAoYm94SWQ6IHN0cmluZywgZXh0cmFjdG9yOiBzdHJpbmcpID0+IHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5yZXBvc2l0b3J5LmRlbGV0ZSh7IGJveElkOiBib3hJZCwgZXh0cmFjdG9yOiBleHRyYWN0b3IgfSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgZnJhdWQgc3BlbmRpbmcgaW5mb3JtYXRpb25cbiAgICogQHBhcmFtIGJveElkXG4gICAqIEBwYXJhbSBleHRyYWN0b3JcbiAgICogQHBhcmFtIGJsb2NrSWRcbiAgICogQHBhcmFtIGJsb2NrSGVpZ2h0XG4gICAqL1xuICB1cGRhdGVTcGVuZEJsb2NrID0gYXN5bmMgKFxuICAgIGJveElkOiBzdHJpbmcsXG4gICAgZXh0cmFjdG9yOiBzdHJpbmcsXG4gICAgYmxvY2tJZDogc3RyaW5nLFxuICAgIGJsb2NrSGVpZ2h0OiBudW1iZXJcbiAgKSA9PiB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucmVwb3NpdG9yeS51cGRhdGUoXG4gICAgICB7IGJveElkOiBib3hJZCwgZXh0cmFjdG9yOiBleHRyYWN0b3IgfSxcbiAgICAgIHsgc3BlbmRCbG9jazogYmxvY2tJZCwgc3BlbmRIZWlnaHQ6IGJsb2NrSGVpZ2h0IH1cbiAgICApO1xuICB9O1xufVxuIl19
@@ -0,0 +1,4 @@
1
+ declare const DefaultApiLimit = 100;
2
+ declare const dbIdChunkSize = 100;
3
+ export { DefaultApiLimit, dbIdChunkSize };
4
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../lib/constants.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,eAAe,MAAM,CAAC;AAC5B,QAAA,MAAM,aAAa,MAAM,CAAC;AAE1B,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ const DefaultApiLimit = 100;
2
+ const dbIdChunkSize = 100;
3
+ export { DefaultApiLimit, dbIdChunkSize };
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vbGliL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLGVBQWUsR0FBRyxHQUFHLENBQUM7QUFDNUIsTUFBTSxhQUFhLEdBQUcsR0FBRyxDQUFDO0FBRTFCLE9BQU8sRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBEZWZhdWx0QXBpTGltaXQgPSAxMDA7XG5jb25zdCBkYklkQ2h1bmtTaXplID0gMTAwO1xuXG5leHBvcnQgeyBEZWZhdWx0QXBpTGltaXQsIGRiSWRDaHVua1NpemUgfTtcbiJdfQ==
@@ -0,0 +1,16 @@
1
+ export declare class FraudEntity {
2
+ id: number;
3
+ boxId: string;
4
+ creationBlock: string;
5
+ creationHeight: number;
6
+ creationTxId: string;
7
+ serialized: string;
8
+ triggerBoxId: string;
9
+ wid: string;
10
+ rwtCount: string;
11
+ spendBlock?: string | null;
12
+ spendHeight?: number;
13
+ spendTxId?: string | null;
14
+ extractor: string;
15
+ }
16
+ //# sourceMappingURL=fraudEntity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fraudEntity.d.ts","sourceRoot":"","sources":["../../lib/entities/fraudEntity.ts"],"names":[],"mappings":"AAEA,qBACa,WAAW;IAEtB,EAAE,EAAE,MAAM,CAAC;IAGX,KAAK,EAAE,MAAM,CAAC;IAGd,aAAa,EAAE,MAAM,CAAC;IAGtB,cAAc,EAAE,MAAM,CAAC;IAGvB,YAAY,EAAE,MAAM,CAAC;IAGrB,UAAU,EAAE,MAAM,CAAC;IAGnB,YAAY,EAAE,MAAM,CAAC;IAGrB,GAAG,EAAE,MAAM,CAAC;IAGZ,QAAQ,EAAE,MAAM,CAAC;IAGjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,82 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
11
+ let FraudEntity = class FraudEntity {
12
+ id;
13
+ boxId;
14
+ creationBlock;
15
+ creationHeight;
16
+ creationTxId;
17
+ serialized;
18
+ triggerBoxId;
19
+ wid;
20
+ rwtCount;
21
+ spendBlock;
22
+ spendHeight;
23
+ spendTxId;
24
+ extractor;
25
+ };
26
+ __decorate([
27
+ PrimaryGeneratedColumn(),
28
+ __metadata("design:type", Number)
29
+ ], FraudEntity.prototype, "id", void 0);
30
+ __decorate([
31
+ Column(),
32
+ __metadata("design:type", String)
33
+ ], FraudEntity.prototype, "boxId", void 0);
34
+ __decorate([
35
+ Column(),
36
+ __metadata("design:type", String)
37
+ ], FraudEntity.prototype, "creationBlock", void 0);
38
+ __decorate([
39
+ Column(),
40
+ __metadata("design:type", Number)
41
+ ], FraudEntity.prototype, "creationHeight", void 0);
42
+ __decorate([
43
+ Column(),
44
+ __metadata("design:type", String)
45
+ ], FraudEntity.prototype, "creationTxId", void 0);
46
+ __decorate([
47
+ Column(),
48
+ __metadata("design:type", String)
49
+ ], FraudEntity.prototype, "serialized", void 0);
50
+ __decorate([
51
+ Column(),
52
+ __metadata("design:type", String)
53
+ ], FraudEntity.prototype, "triggerBoxId", void 0);
54
+ __decorate([
55
+ Column(),
56
+ __metadata("design:type", String)
57
+ ], FraudEntity.prototype, "wid", void 0);
58
+ __decorate([
59
+ Column(),
60
+ __metadata("design:type", String)
61
+ ], FraudEntity.prototype, "rwtCount", void 0);
62
+ __decorate([
63
+ Column({ nullable: true, type: 'text' }),
64
+ __metadata("design:type", Object)
65
+ ], FraudEntity.prototype, "spendBlock", void 0);
66
+ __decorate([
67
+ Column({ nullable: true }),
68
+ __metadata("design:type", Number)
69
+ ], FraudEntity.prototype, "spendHeight", void 0);
70
+ __decorate([
71
+ Column({ nullable: true, type: 'text' }),
72
+ __metadata("design:type", Object)
73
+ ], FraudEntity.prototype, "spendTxId", void 0);
74
+ __decorate([
75
+ Column(),
76
+ __metadata("design:type", String)
77
+ ], FraudEntity.prototype, "extractor", void 0);
78
+ FraudEntity = __decorate([
79
+ Entity()
80
+ ], FraudEntity);
81
+ export { FraudEntity };
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhdWRFbnRpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvZW50aXRpZXMvZnJhdWRFbnRpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFHMUQsSUFBTSxXQUFXLEdBQWpCLE1BQU0sV0FBVztJQUV0QixFQUFFLENBQVM7SUFHWCxLQUFLLENBQVM7SUFHZCxhQUFhLENBQVM7SUFHdEIsY0FBYyxDQUFTO0lBR3ZCLFlBQVksQ0FBUztJQUdyQixVQUFVLENBQVM7SUFHbkIsWUFBWSxDQUFTO0lBR3JCLEdBQUcsQ0FBUztJQUdaLFFBQVEsQ0FBUztJQUdqQixVQUFVLENBQWlCO0lBRzNCLFdBQVcsQ0FBVTtJQUdyQixTQUFTLENBQWlCO0lBRzFCLFNBQVMsQ0FBUztDQUNuQixDQUFBO0FBdENDO0lBQUMsc0JBQXNCLEVBQUU7O3VDQUNkO0FBRVg7SUFBQyxNQUFNLEVBQUU7OzBDQUNLO0FBRWQ7SUFBQyxNQUFNLEVBQUU7O2tEQUNhO0FBRXRCO0lBQUMsTUFBTSxFQUFFOzttREFDYztBQUV2QjtJQUFDLE1BQU0sRUFBRTs7aURBQ1k7QUFFckI7SUFBQyxNQUFNLEVBQUU7OytDQUNVO0FBRW5CO0lBQUMsTUFBTSxFQUFFOztpREFDWTtBQUVyQjtJQUFDLE1BQU0sRUFBRTs7d0NBQ0c7QUFFWjtJQUFDLE1BQU0sRUFBRTs7NkNBQ1E7QUFFakI7SUFBQyxNQUFNLENBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQzs7K0NBQ2Q7QUFFM0I7SUFBQyxNQUFNLENBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUM7O2dEQUNOO0FBRXJCO0lBQUMsTUFBTSxDQUFDLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7OzhDQUNmO0FBRTFCO0lBQUMsTUFBTSxFQUFFOzs4Q0FDUztBQXRDUCxXQUFXO0lBRHZCLE1BQU0sRUFBRTtHQUNJLFdBQVcsQ0F1Q3ZCO1NBdkNZLFdBQVciLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb2x1bW4sIEVudGl0eSwgUHJpbWFyeUdlbmVyYXRlZENvbHVtbiB9IGZyb20gJ3R5cGVvcm0nO1xuXG5ARW50aXR5KClcbmV4cG9ydCBjbGFzcyBGcmF1ZEVudGl0eSB7XG4gIEBQcmltYXJ5R2VuZXJhdGVkQ29sdW1uKClcbiAgaWQ6IG51bWJlcjtcblxuICBAQ29sdW1uKClcbiAgYm94SWQ6IHN0cmluZztcblxuICBAQ29sdW1uKClcbiAgY3JlYXRpb25CbG9jazogc3RyaW5nO1xuXG4gIEBDb2x1bW4oKVxuICBjcmVhdGlvbkhlaWdodDogbnVtYmVyO1xuXG4gIEBDb2x1bW4oKVxuICBjcmVhdGlvblR4SWQ6IHN0cmluZztcblxuICBAQ29sdW1uKClcbiAgc2VyaWFsaXplZDogc3RyaW5nO1xuXG4gIEBDb2x1bW4oKVxuICB0cmlnZ2VyQm94SWQ6IHN0cmluZztcblxuICBAQ29sdW1uKClcbiAgd2lkOiBzdHJpbmc7XG5cbiAgQENvbHVtbigpXG4gIHJ3dENvdW50OiBzdHJpbmc7XG5cbiAgQENvbHVtbih7IG51bGxhYmxlOiB0cnVlLCB0eXBlOiAndGV4dCcgfSlcbiAgc3BlbmRCbG9jaz86IHN0cmluZyB8IG51bGw7XG5cbiAgQENvbHVtbih7IG51bGxhYmxlOiB0cnVlIH0pXG4gIHNwZW5kSGVpZ2h0PzogbnVtYmVyO1xuXG4gIEBDb2x1bW4oeyBudWxsYWJsZTogdHJ1ZSwgdHlwZTogJ3RleHQnIH0pXG4gIHNwZW5kVHhJZD86IHN0cmluZyB8IG51bGw7XG5cbiAgQENvbHVtbigpXG4gIGV4dHJhY3Rvcjogc3RyaW5nO1xufVxuIl19
@@ -0,0 +1,144 @@
1
+ import { DataSource } from 'typeorm';
2
+ import { AbstractExtractor } from '@rosen-bridge/scanner';
3
+ import { AbstractLogger } from '@rosen-bridge/abstract-logger';
4
+ import { BlockEntity, Transaction } from '@rosen-bridge/scanner';
5
+ import { V1 } from '@rosen-clients/ergo-explorer';
6
+ import { ExtractedFraud } from '../interfaces/types';
7
+ export declare class FraudExtractor implements AbstractExtractor<Transaction> {
8
+ private readonly logger;
9
+ private readonly actions;
10
+ private readonly id;
11
+ private readonly ergoTree;
12
+ private readonly rwt;
13
+ readonly api: {
14
+ v0: {
15
+ getApiV0AddressesP1: (p1: string, params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0AddressesP1Params | undefined) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").AddressInfo>;
16
+ getApiV0AddressesP1Transactions: (p1: string, params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0AddressesP1TransactionsParams | undefined) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").ItemsTransactionInfo>;
17
+ getApiV0AddressesAssetholdersP1: (p1: string, params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0AddressesAssetholdersP1Params | undefined) => Promise<string[]>;
18
+ getApiV0AddressesBalances: (params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0AddressesBalancesParams | undefined) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").ItemsBalanceInfo>;
19
+ getApiV0AssetsIssuingboxes: (params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0AssetsIssuingboxesParams | undefined) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").ItemsOutputInfo>;
20
+ getApiV0AssetsP1Issuingbox: (p1: string) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").OutputInfo[]>;
21
+ getApiV0Blocks: (params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0BlocksParams | undefined) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").ItemsBlockInfo>;
22
+ getApiV0BlocksP1: (p1: string) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").BlockSummary>;
23
+ getApiV0BlocksAtP1: (p1: number) => Promise<string[]>;
24
+ getApiV0DexTokensP1Unspentsellorders: (p1: string, params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0DexTokensP1UnspentsellordersParams | undefined) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").DexSellOrderInfo[]>;
25
+ getApiV0DexTokensP1Unspentbuyorders: (p1: string, params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0DexTokensP1UnspentbuyordersParams | undefined) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").DexBuyOrderInfo[]>;
26
+ getApiV0TransactionsP1: (p1: string) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").TransactionSummary>;
27
+ getApiV0TransactionsUnconfirmedP1: (p1: string) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").UTransactionSummary>;
28
+ getApiV0TransactionsUnconfirmedByaddressP1: (p1: string, params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0TransactionsUnconfirmedByaddressP1Params | undefined) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").ItemsUTransactionInfo>;
29
+ getApiV0TransactionsUnconfirmed: (params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0TransactionsUnconfirmedParams | undefined) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").ItemsUTransactionInfo>;
30
+ getApiV0TransactionsSinceP1: (p1: number, params?: import("@rosen-clients/ergo-explorer/dist/src/v0/types").GetApiV0TransactionsSinceP1Params | undefined) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").TransactionInfo[]>;
31
+ postApiV0TransactionsSend: (postApiV0TransactionsSendBody: import("@rosen-clients/ergo-explorer/dist/src/v0/types").PostApiV0TransactionsSendBody) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").TxIdResponse>;
32
+ getApiV0TransactionsBoxesP1: (p1: string) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").OutputInfo>;
33
+ getApiV0TransactionsBoxesByergotreeP1: (p1: string) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").OutputInfo[]>;
34
+ getApiV0TransactionsBoxesByergotreeUnspentP1: (p1: string) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").OutputInfo[]>;
35
+ getApiV0TransactionsBoxesByaddressP1: (p1: string) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").OutputInfo[]>;
36
+ getApiV0TransactionsBoxesByaddressUnspentP1: (p1: string) => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").OutputInfo[]>;
37
+ getApiV0Info: () => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").BlockChainInfo>;
38
+ getApiV0InfoSupply: () => Promise<string>;
39
+ getApiV0Stats: () => Promise<import("@rosen-clients/ergo-explorer/dist/src/v0/types").StatsSummary>;
40
+ getApiV0DocsOpenapi: () => Promise<string>;
41
+ };
42
+ v1: {
43
+ getApiV1TransactionsP1: (p1: string) => Promise<V1.TransactionInfo>;
44
+ getApiV1TransactionsByinputsscripttemplatehashP1: (p1: string, params?: V1.GetApiV1TransactionsByinputsscripttemplatehashP1Params | undefined) => Promise<V1.ItemsTransactionInfo>;
45
+ getApiV1TransactionsByglobalindexStream: (params: V1.GetApiV1TransactionsByglobalindexStreamParams) => Promise<V1.ListTransactionInfo>;
46
+ getApiV1BoxesUnspentBylastepochsStream: (params: V1.GetApiV1BoxesUnspentBylastepochsStreamParams) => Promise<V1.ListOutputInfo>;
47
+ getApiV1BoxesUnspentByglobalindexStream: (params: V1.GetApiV1BoxesUnspentByglobalindexStreamParams) => Promise<V1.ListOutputInfo>;
48
+ getApiV1BoxesUnspentStream: (params: V1.GetApiV1BoxesUnspentStreamParams) => Promise<V1.ListOutputInfo>;
49
+ getApiV1BoxesByergotreetemplatehashP1Stream: (p1: string, params: V1.GetApiV1BoxesByergotreetemplatehashP1StreamParams) => Promise<V1.ListOutputInfo>;
50
+ getApiV1BoxesUnspentByergotreetemplatehashP1Stream: (p1: string, params: V1.GetApiV1BoxesUnspentByergotreetemplatehashP1StreamParams) => Promise<V1.ListOutputInfo>;
51
+ getApiV1BoxesUnspentBytokenidP1: (p1: string, params?: V1.GetApiV1BoxesUnspentBytokenidP1Params | undefined) => Promise<V1.ItemsOutputInfo>;
52
+ getApiV1BoxesBytokenidP1: (p1: string, params?: V1.GetApiV1BoxesBytokenidP1Params | undefined) => Promise<V1.ItemsOutputInfo>;
53
+ getApiV1BoxesP1: (p1: string) => Promise<V1.OutputInfo>;
54
+ getApiV1BoxesByergotreeP1: (p1: string, params?: V1.GetApiV1BoxesByergotreeP1Params | undefined) => Promise<V1.ItemsOutputInfo>;
55
+ getApiV1BoxesByergotreetemplatehashP1: (p1: string, params?: V1.GetApiV1BoxesByergotreetemplatehashP1Params | undefined) => Promise<V1.ItemsOutputInfo>;
56
+ getApiV1BoxesUnspentByergotreeP1: (p1: string, params?: V1.GetApiV1BoxesUnspentByergotreeP1Params | undefined) => Promise<V1.ItemsOutputInfo>;
57
+ getApiV1BoxesUnspentByergotreetemplatehashP1: (p1: string, params?: V1.GetApiV1BoxesUnspentByergotreetemplatehashP1Params | undefined) => Promise<V1.ItemsOutputInfo>;
58
+ getApiV1BoxesByaddressP1: (p1: string, params?: V1.GetApiV1BoxesByaddressP1Params | undefined) => Promise<V1.ItemsOutputInfo>;
59
+ getApiV1BoxesUnspentByaddressP1: (p1: string, params?: V1.GetApiV1BoxesUnspentByaddressP1Params | undefined) => Promise<V1.ItemsOutputInfo>;
60
+ getApiV1BoxesByglobalindexStream: (params: V1.GetApiV1BoxesByglobalindexStreamParams) => Promise<V1.ListOutputInfo>;
61
+ postApiV1BoxesUnspentSearchUnion: (boxAssetsQuery: V1.BoxAssetsQuery, params?: V1.PostApiV1BoxesUnspentSearchUnionParams | undefined) => Promise<V1.ItemsOutputInfo>;
62
+ postApiV1BoxesUnspentSearch: (boxQuery: V1.BoxQuery, params?: V1.PostApiV1BoxesUnspentSearchParams | undefined) => Promise<V1.ItemsOutputInfo>;
63
+ postApiV1BoxesSearch: (boxQuery: V1.BoxQuery, params?: V1.PostApiV1BoxesSearchParams | undefined) => Promise<V1.ItemsOutputInfo>;
64
+ getApiV1Tokens: (params?: V1.GetApiV1TokensParams | undefined) => Promise<V1.ItemsTokenInfo>;
65
+ getApiV1TokensSearch: (params: V1.GetApiV1TokensSearchParams) => Promise<V1.ItemsTokenInfo>;
66
+ getApiV1TokensBysymbolP1: (p1: string) => Promise<V1.TokenInfo[]>;
67
+ getApiV1TokensP1: (p1: string) => Promise<V1.TokenInfo>;
68
+ getApiV1Assets: (params?: V1.GetApiV1AssetsParams | undefined) => Promise<V1.ItemsTokenInfo>;
69
+ getApiV1AssetsSearchBytokenid: (params: V1.GetApiV1AssetsSearchBytokenidParams) => Promise<V1.ItemsAssetInfo>;
70
+ getApiV1EpochsParams: () => Promise<V1.EpochInfo>;
71
+ getApiV1AddressesP1Transactions: (p1: string, params?: V1.GetApiV1AddressesP1TransactionsParams | undefined) => Promise<V1.ItemsTransactionInfo>;
72
+ getApiV1AddressesP1BalanceConfirmed: (p1: string, params?: V1.GetApiV1AddressesP1BalanceConfirmedParams | undefined) => Promise<V1.Balance>;
73
+ getApiV1AddressesP1BalanceTotal: (p1: string) => Promise<V1.TotalBalance>;
74
+ getApiV1Blocks: (params?: V1.GetApiV1BlocksParams | undefined) => Promise<V1.ItemsBlockInfo>;
75
+ getApiV1BlocksP1: (p1: string) => Promise<V1.BlockSummary>;
76
+ getApiV1BlocksHeaders: (params?: V1.GetApiV1BlocksHeadersParams | undefined) => Promise<V1.ItemsBlockHeader>;
77
+ getApiV1BlocksByglobalindexStream: (params: V1.GetApiV1BlocksByglobalindexStreamParams) => Promise<V1.ListBlockInfo>;
78
+ getApiV1BlocksStreamSummary: (params?: V1.GetApiV1BlocksStreamSummaryParams | undefined) => Promise<V1.ListBlockSummaryV1>;
79
+ postApiV1MempoolTransactionsSubmit: (postApiV1MempoolTransactionsSubmitBody: V1.PostApiV1MempoolTransactionsSubmitBody) => Promise<V1.TxIdResponse>;
80
+ getApiV1MempoolTransactionsByaddressP1: (p1: string, params?: V1.GetApiV1MempoolTransactionsByaddressP1Params | undefined) => Promise<V1.ItemsUTransactionInfo>;
81
+ getApiV1MempoolBoxesUnspent: () => Promise<V1.ListOutputInfo>;
82
+ getApiV1Info: () => Promise<V1.NetworkState>;
83
+ getApiV1Networkstate: () => Promise<V1.NetworkState>;
84
+ getApiV1Networkstats: () => Promise<V1.NetworkStats>;
85
+ };
86
+ };
87
+ constructor(dataSource: DataSource, id: string, explorerUrl: string, fraudAddress: string, rwt: string, logger?: AbstractLogger);
88
+ /**
89
+ * get Id for current extractor
90
+ */
91
+ getId: () => string;
92
+ /**
93
+ * Extract fraud boxes in the specified block transactions
94
+ * @param txs
95
+ * @param block
96
+ */
97
+ processTransactions: (txs: Array<Transaction>, block: BlockEntity) => Promise<boolean>;
98
+ /**
99
+ * fork one block and remove all stored information for this block
100
+ * @param hash: block hash
101
+ */
102
+ forkBlock: (hash: string) => Promise<void>;
103
+ /**
104
+ * Initializes the database with older frauds
105
+ */
106
+ initializeBoxes: (initialHeight: number) => Promise<void>;
107
+ /**
108
+ * Validate all remaining boxes in the database
109
+ * update the correct ones and remove the invalid ones
110
+ * @param unchangedStoredBoxIds
111
+ * @param initialHeight
112
+ */
113
+ validateOldStoredFrauds: (unchangedStoredBoxIds: Array<string>, initialHeight: number) => Promise<void>;
114
+ /**
115
+ * Return extracted information of a fraud with its boxId
116
+ * @param boxId
117
+ */
118
+ getFraudInfoWithBoxId: (boxId: string) => Promise<ExtractedFraud | undefined>;
119
+ /**
120
+ * Get unspent frauds created bellow the initial height
121
+ * @param initialHeight
122
+ * @returns
123
+ */
124
+ getUnspentFrauds: (initialHeight: number) => Promise<Array<ExtractedFraud>>;
125
+ /**
126
+ * Returns block information of tx
127
+ * @param txId
128
+ */
129
+ getTxBlock: (txId: string) => Promise<{
130
+ id: string;
131
+ height: number;
132
+ }>;
133
+ /**
134
+ * Returns trigger boxId from fraud transaction id
135
+ * @param txId
136
+ */
137
+ getTriggerBoxId: (txId: string) => Promise<string | undefined>;
138
+ /**
139
+ * Extract needed information for storing in database from api json outputs
140
+ * @param boxes
141
+ */
142
+ extractBoxData: (boxes: Array<V1.OutputInfo>) => Promise<ExtractedFraud[]>;
143
+ }
144
+ //# sourceMappingURL=fraudExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fraudExtractor.d.ts","sourceRoot":"","sources":["../../lib/extractor/fraudExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAIrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAe,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EAAE,EAAE,EAAE,MAAM,8BAA8B,CAAC;AAKlD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,qBAAa,cAAe,YAAW,iBAAiB,CAAC,WAAW,CAAC;IACnE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,QAAQ,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAAC;gBAGX,UAAU,EAAE,UAAU,EACtB,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,cAAc;IAYzB;;OAEG;IACH,KAAK,eAAsB;IAE3B;;;;OAIG;IACH,mBAAmB,QACZ,MAAM,WAAW,CAAC,SAChB,WAAW,KACjB,QAAQ,OAAO,CAAC,CA2EjB;IAEF;;;OAGG;IACH,SAAS,SAAgB,MAAM,KAAG,QAAQ,IAAI,CAAC,CAE7C;IAEF;;OAEG;IACH,eAAe,kBAAyB,MAAM,mBAkC5C;IAEF;;;;;OAKG;IACH,uBAAuB,0BACE,MAAM,MAAM,CAAC,iBACrB,MAAM,mBA2BrB;IAEF;;;OAGG;IACH,qBAAqB,UACZ,MAAM,KACZ,QAAQ,cAAc,GAAG,SAAS,CAAC,CAQpC;IAEF;;;;OAIG;IACH,gBAAgB,kBACC,MAAM,KACpB,QAAQ,MAAM,cAAc,CAAC,CAAC,CA+B/B;IAEF;;;OAGG;IACH,UAAU,SAAgB,MAAM;;;OAM9B;IAEF;;;OAGG;IACH,eAAe,SAAgB,MAAM,iCAGnC;IAEF;;;OAGG;IACH,cAAc,UAAiB,MAAM,GAAG,UAAU,CAAC,+BAoDjD;CACH"}
@@ -0,0 +1,262 @@
1
+ import * as wasm from 'ergo-lib-wasm-nodejs';
2
+ import { Buffer } from 'buffer';
3
+ import { difference } from 'lodash-es';
4
+ import { DummyLogger } from '@rosen-bridge/abstract-logger';
5
+ import ergoExplorerClientFactory from '@rosen-clients/ergo-explorer';
6
+ import JsonBI from '@rosen-bridge/json-bigint';
7
+ import { FraudAction } from '../actions/fraudAction';
8
+ import { DefaultApiLimit } from '../constants';
9
+ export class FraudExtractor {
10
+ logger;
11
+ actions;
12
+ id;
13
+ ergoTree;
14
+ rwt;
15
+ api;
16
+ constructor(dataSource, id, explorerUrl, fraudAddress, rwt, logger) {
17
+ this.id = id;
18
+ this.ergoTree = wasm.Address.from_base58(fraudAddress)
19
+ .to_ergo_tree()
20
+ .to_base16_bytes();
21
+ this.rwt = rwt;
22
+ this.logger = logger ? logger : new DummyLogger();
23
+ this.actions = new FraudAction(dataSource, this.logger);
24
+ this.api = ergoExplorerClientFactory(explorerUrl);
25
+ }
26
+ /**
27
+ * get Id for current extractor
28
+ */
29
+ getId = () => `${this.id}`;
30
+ /**
31
+ * Extract fraud boxes in the specified block transactions
32
+ * @param txs
33
+ * @param block
34
+ */
35
+ processTransactions = (txs, block) => {
36
+ return new Promise((resolve, reject) => {
37
+ try {
38
+ const newFrauds = [];
39
+ const txSpendIds = [];
40
+ txs.forEach((transaction) => {
41
+ for (const output of transaction.outputs) {
42
+ if (output.ergoTree !== this.ergoTree ||
43
+ !output.assets ||
44
+ output.assets[0].tokenId !== this.rwt) {
45
+ continue;
46
+ }
47
+ const boxOutput = wasm.ErgoBox.from_json(JsonBI.stringify(output));
48
+ const r4 = boxOutput
49
+ .register_value(wasm.NonMandatoryRegisterId.R4)
50
+ ?.to_coll_coll_byte();
51
+ if (!r4) {
52
+ this.logger.debug(`A new fraud box found without correct wid format at height ${block.height}`);
53
+ continue;
54
+ }
55
+ const newFraud = {
56
+ boxId: output.boxId,
57
+ txId: transaction.id,
58
+ triggerBoxId: transaction.inputs[0].boxId,
59
+ wid: Buffer.from(r4[0]).toString('hex'),
60
+ rwtCount: output.assets[0].amount.toString(),
61
+ serialized: Buffer.from(wasm.ErgoBox.from_json(JsonBI.stringify(output)).sigma_serialize_bytes()).toString('base64'),
62
+ };
63
+ newFrauds.push(newFraud);
64
+ this.logger.debug(`new fraud found [${newFraud}] at height ${block.height}`);
65
+ }
66
+ txSpendIds.push({
67
+ txId: transaction.id,
68
+ spendBoxes: transaction.inputs.map((box) => box.boxId),
69
+ });
70
+ });
71
+ this.actions
72
+ .storeBlockFrauds(newFrauds, block, this.getId())
73
+ .then(async (status) => {
74
+ if (status) {
75
+ if (newFrauds.length > 0)
76
+ this.logger.debug(`successfully stored new frauds at hight ${block.height}`);
77
+ for (const spendIds of txSpendIds)
78
+ await this.actions.spendFrauds(spendIds.spendBoxes, block, this.getId(), spendIds.txId);
79
+ }
80
+ resolve(status);
81
+ })
82
+ .catch((e) => {
83
+ this.logger.error(`An error occurred in processing frauds in block [${block.hash}]: ${e}`);
84
+ reject(e);
85
+ });
86
+ }
87
+ catch (e) {
88
+ reject(e);
89
+ }
90
+ });
91
+ };
92
+ /**
93
+ * fork one block and remove all stored information for this block
94
+ * @param hash: block hash
95
+ */
96
+ forkBlock = async (hash) => {
97
+ await this.actions.deleteBlock(hash, this.getId());
98
+ };
99
+ /**
100
+ * Initializes the database with older frauds
101
+ */
102
+ initializeBoxes = async (initialHeight) => {
103
+ // Getting unspent boxes
104
+ this.logger.debug(`Initializing fraud table. storing fraud boxes created bellow height ${initialHeight}.`);
105
+ const unspentFrauds = await this.getUnspentFrauds(initialHeight);
106
+ const unspentBoxIds = unspentFrauds.map((box) => box.boxId);
107
+ this.logger.debug(`Unspent fraud boxIds ${unspentBoxIds}`);
108
+ // Storing extracted boxes
109
+ let allStoredBoxIds = await this.actions.getAllBoxIds(this.getId());
110
+ for (const fraud of unspentFrauds) {
111
+ if (allStoredBoxIds.includes(fraud.boxId)) {
112
+ await this.actions.updateFraud(fraud, this.getId());
113
+ this.logger.info(`Updated the existing unspent fraud with boxId, [${fraud.boxId}]`);
114
+ this.logger.debug(`Updated fraud: [${JSON.stringify(fraud)}]`);
115
+ }
116
+ else {
117
+ await this.actions.insertFraud(fraud, this.getId());
118
+ this.logger.info(`Inserted new unspent fraud with boxId, [${fraud.boxId}]`);
119
+ this.logger.debug(`Inserted fraud: [${JSON.stringify(fraud)}]`);
120
+ }
121
+ }
122
+ // Remove updated box ids from existing boxes in database
123
+ allStoredBoxIds = difference(allStoredBoxIds, unspentBoxIds);
124
+ // Validating remained boxes
125
+ this.logger.debug(`Validating and updating stored fraud boxes with boxIds ${allStoredBoxIds}`);
126
+ await this.validateOldStoredFrauds(allStoredBoxIds, initialHeight);
127
+ };
128
+ /**
129
+ * Validate all remaining boxes in the database
130
+ * update the correct ones and remove the invalid ones
131
+ * @param unchangedStoredBoxIds
132
+ * @param initialHeight
133
+ */
134
+ validateOldStoredFrauds = async (unchangedStoredBoxIds, initialHeight) => {
135
+ for (const boxId of unchangedStoredBoxIds) {
136
+ const box = await this.getFraudInfoWithBoxId(boxId);
137
+ if (box && box.spendBlock && box.spendHeight) {
138
+ if (box.spendHeight < initialHeight) {
139
+ this.logger.debug(`updating spending information of fraud with boxId [${box.boxId}] spent at height [${box.spendHeight}]`);
140
+ await this.actions.updateSpendBlock(boxId, this.getId(), box.spendBlock, box.spendHeight);
141
+ }
142
+ else {
143
+ this.logger.debug(`fraud with boxId [${box.boxId}] has been spent after the initialization height, updating spending information skipped.`);
144
+ }
145
+ }
146
+ else {
147
+ await this.actions.removeFraud(boxId, this.getId());
148
+ this.logger.info(`Removed invalid fraud [${boxId}] in initialization validation`);
149
+ }
150
+ }
151
+ };
152
+ /**
153
+ * Return extracted information of a fraud with its boxId
154
+ * @param boxId
155
+ */
156
+ getFraudInfoWithBoxId = async (boxId) => {
157
+ try {
158
+ const box = await this.api.v1.getApiV1BoxesP1(boxId);
159
+ return (await this.extractBoxData([box]))[0];
160
+ }
161
+ catch {
162
+ this.logger.warn(`Box with id [${boxId}] does not exists`);
163
+ return undefined;
164
+ }
165
+ };
166
+ /**
167
+ * Get unspent frauds created bellow the initial height
168
+ * @param initialHeight
169
+ * @returns
170
+ */
171
+ getUnspentFrauds = async (initialHeight) => {
172
+ let allBoxes = [];
173
+ let offset = 0, total = DefaultApiLimit, boxes;
174
+ while (offset < total) {
175
+ boxes = await this.api.v1.getApiV1BoxesUnspentByergotreeP1(this.ergoTree, {
176
+ offset: offset,
177
+ limit: DefaultApiLimit,
178
+ });
179
+ if (!boxes.items) {
180
+ throw new Error('Explorer api output items should not be undefined.');
181
+ }
182
+ allBoxes = [
183
+ ...allBoxes,
184
+ ...(await this.extractBoxData(boxes.items.filter((box) => box.creationHeight < initialHeight &&
185
+ box.assets &&
186
+ box.assets[0].tokenId == this.rwt))),
187
+ ];
188
+ total = boxes.total;
189
+ offset += DefaultApiLimit;
190
+ }
191
+ return allBoxes;
192
+ };
193
+ /**
194
+ * Returns block information of tx
195
+ * @param txId
196
+ */
197
+ getTxBlock = async (txId) => {
198
+ const tx = await this.api.v1.getApiV1TransactionsP1(txId);
199
+ return {
200
+ id: tx.blockId,
201
+ height: tx.inclusionHeight,
202
+ };
203
+ };
204
+ /**
205
+ * Returns trigger boxId from fraud transaction id
206
+ * @param txId
207
+ */
208
+ getTriggerBoxId = async (txId) => {
209
+ const tx = await this.api.v1.getApiV1TransactionsP1(txId);
210
+ return tx.inputs?.[0].boxId;
211
+ };
212
+ /**
213
+ * Extract needed information for storing in database from api json outputs
214
+ * @param boxes
215
+ */
216
+ extractBoxData = async (boxes) => {
217
+ const extractedFrauds = [];
218
+ for (const box of boxes) {
219
+ try {
220
+ this.logger.debug(`Extracting box fraud information from box with boxId [${box.boxId}]`);
221
+ let spendBlock, spendHeight;
222
+ // Extract spending information
223
+ if (box.spentTransactionId) {
224
+ const block = await this.getTxBlock(box.spentTransactionId);
225
+ spendBlock = block.id;
226
+ spendHeight = block.height;
227
+ }
228
+ // Extract WID
229
+ const ergoBox = wasm.ErgoBox.from_json(JsonBI.stringify(box));
230
+ const r4 = ergoBox
231
+ .register_value(wasm.NonMandatoryRegisterId.R4)
232
+ ?.to_coll_coll_byte();
233
+ // Extract trigger boxId
234
+ const triggerBoxId = await this.getTriggerBoxId(box.transactionId);
235
+ if (!r4 || !triggerBoxId) {
236
+ this.logger.warn(`Skipping storing fraud with boxId [${box.boxId}], wid or trigger box id is undefined`);
237
+ continue;
238
+ }
239
+ const extractedFraud = {
240
+ boxId: ergoBox.box_id().to_str(),
241
+ triggerBoxId: triggerBoxId,
242
+ wid: Buffer.from(r4[0]).toString('hex'),
243
+ rwtCount: box.assets[0].amount.toString(),
244
+ serialized: Buffer.from(ergoBox.sigma_serialize_bytes()).toString('base64'),
245
+ blockId: box.blockId,
246
+ height: box.settlementHeight,
247
+ txId: box.transactionId,
248
+ spendBlock: spendBlock,
249
+ spendHeight: spendHeight,
250
+ spendTxId: box.spentTransactionId,
251
+ };
252
+ extractedFrauds.push(extractedFraud);
253
+ this.logger.debug(`Extracted fraud: [${extractedFraud}]`);
254
+ }
255
+ catch (e) {
256
+ this.logger.error(`Extracting fraud information failed for box [${box.boxId}] with error: ${e}`);
257
+ }
258
+ }
259
+ return extractedFrauds;
260
+ };
261
+ }
262
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnJhdWRFeHRyYWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvZXh0cmFjdG9yL2ZyYXVkRXh0cmFjdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxJQUFJLE1BQU0sc0JBQXNCLENBQUM7QUFDN0MsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUNoQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXZDLE9BQU8sRUFBa0IsV0FBVyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFNUUsT0FBTyx5QkFBeUIsTUFBTSw4QkFBOEIsQ0FBQztBQUVyRSxPQUFPLE1BQU0sTUFBTSwyQkFBMkIsQ0FBQztBQUUvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDckQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUcvQyxNQUFNLE9BQU8sY0FBYztJQUNSLE1BQU0sQ0FBaUI7SUFDdkIsT0FBTyxDQUFjO0lBQ3JCLEVBQUUsQ0FBUztJQUNYLFFBQVEsQ0FBUztJQUNqQixHQUFHLENBQVM7SUFDcEIsR0FBRyxDQUFDO0lBRWIsWUFDRSxVQUFzQixFQUN0QixFQUFVLEVBQ1YsV0FBbUIsRUFDbkIsWUFBb0IsRUFDcEIsR0FBVyxFQUNYLE1BQXVCO1FBRXZCLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDO1FBQ2IsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUM7YUFDbkQsWUFBWSxFQUFFO2FBQ2QsZUFBZSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDZixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLFdBQVcsRUFBRSxDQUFDO1FBQ2xELElB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aEMsWUFBWSxFQUFFLFlBQVk7b0JBQzFCLEdBQUcsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7b0JBQ3ZDLFFBQVEsRUFBRSxHQUFHLENBQUMsTUFBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUU7b0JBQzFDLFVBQVUsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUMvRCxRQUFRLENBQ1Q7b0JBQ0QsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPO29CQUNwQixNQUFNLEVBQUUsR0FBRyxDQUFDLGdCQUFnQjtvQkFDNUIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxhQUFhO29CQUN2QixVQUFVLEVBQUUsVUFBVTtvQkFDdEIsV0FBVyxFQUFFLFdBQVc7b0JBQ3hCLFNBQVMsRUFBRSxHQUFHLENBQUMsa0JBQWtCO2lCQUNsQyxDQUFDO2dCQUNGLGVBQWUsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7Z0JBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHFCQUFxQixjQUFjLEdBQUcsQ0FBQyxDQUFDO2FBQzNEO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ2YsZ0RBQWdELEdBQUcsQ0FBQyxLQUFLLGlCQUFpQixDQUFDLEVBQUUsQ0FDOUUsQ0FBQzthQUNIO1NBQ0Y7UUFDRCxPQUFPLGVBQWUsQ0FBQztJQUN6QixDQUFDLENBQUM7Q0FDSCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGFTb3VyY2UgfSBmcm9tICd0eXBlb3JtJztcbmltcG9ydCAqIGFzIHdhc20gZnJvbSAnZXJnby1saWItd2FzbS1ub2RlanMnO1xuaW1wb3J0IHsgQnVmZmVyIH0gZnJvbSAnYnVmZmVyJztcbmltcG9ydCB7IGRpZmZlcmVuY2UgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgQWJzdHJhY3RFeHRyYWN0b3IgfSBmcm9tICdAcm9zZW4tYnJpZGdlL3NjYW5uZXInO1xuaW1wb3J0IHsgQWJzdHJhY3RMb2dnZXIsIER1bW15TG9nZ2VyIH0gZnJvbSAnQHJvc2VuLWJyaWRnZS9hYnN0cmFjdC1sb2dnZXInO1xuaW1wb3J0IHsgQmxvY2tFbnRpdHksIFRyYW5zYWN0aW9uIH0gZnJvbSAnQHJvc2VuLWJyaWRnZS9zY2FubmVyJztcbmltcG9ydCBlcmdvRXhwbG9yZXJDbGllbnRGYWN0b3J5IGZyb20gJ0Byb3Nlbi1jbGllbnRzL2VyZ28tZXhwbG9yZXInO1xuaW1wb3J0IHsgVjEgfSBmcm9tICdAcm9zZW4tY2xpZW50cy9lcmdvLWV4cGxvcmVyJztcbmltcG9ydCBKc29uQkkgZnJvbSAnQHJvc2VuLWJyaWRnZS9qc29uLWJpZ2ludCc7XG5cbmltcG9ydCB7IEZyYXVkQWN0aW9uIH0gZnJvbSAnLi4vYWN0aW9ucy9mcmF1ZEFjdGlvbic7XG5pbXBvcnQgeyBEZWZhdWx0QXBpTGltaXQgfSBmcm9tICcuLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgRXh0cmFjdGVkRnJhdWQgfSBmcm9tICcuLi9pbnRlcmZhY2VzL3R5cGVzJztcblxuZXhwb3J0IGNsYXNzIEZyYXVkRXh0cmFjdG9yIGltcGxlbWVudHMgQWJzdHJhY3RFeHRyYWN0b3I8VHJhbnNhY3Rpb24+IHtcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXI6IEFic3RyYWN0TG9nZ2VyO1xuICBwcml2YXRlIHJlYWRvbmx5IGFjdGlvbnM6IEZyYXVkQWN0aW9uO1xuICBwcml2YXRlIHJlYWRvbmx5IGlkOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgZXJnb1RyZWU6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSByd3Q6IHN0cmluZztcbiAgcmVhZG9ubHkgYXBpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGRhdGFTb3VyY2U6IERhdGFTb3VyY2UsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBleHBsb3JlclVybDogc3RyaW5nLFxuICAgIGZyYXVkQWRkcmVzczogc3RyaW5nLFxuICAgIHJ3dDogc3RyaW5nLFxuICAgIGxvZ2dlcj86IEFic3RyYWN0TG9nZ2VyXG4gICkge1xuICAgIHRoaXMuaWQgPSBpZDtcbiAgICB0aGlzLmVyZ29UcmVlID0gd2FzbS5BZGRyZXNzLmZyb21fYmFzZTU4KGZyYXVkQWRkcmVzcylcbiAgICAgIC50b19lcmdvX3RyZWUoKVxuICAgICAgLnRvX2Jhc2UxNl9ieXRlcygpO1xuICAgIHRoaXMucnd0ID0gcnd0O1xuICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyID8gbG9nZ2VyIDogbmV3IER1bW15TG9nZ2VyKCk7XG4gICAgdGhpcy5hY3Rpb25zID0gbmV3IEZyYXVkQWN0aW9uKGRhdGFTb3VyY2UsIHRoaXMubG9nZ2VyKTtcbiAgICB0aGlzLmFwaSA9IGVyZ29FeHBsb3JlckNsaWVudEZhY3RvcnkoZXhwbG9yZXJVcmwpO1xuICB9XG5cbiAgLyoqXG4gICAqIGdldCBJZCBmb3IgY3VycmVudCBleHRyYWN0b3JcbiAgICovXG4gIGdldElkID0gKCkgPT4gYCR7dGhpcy5pZH1gO1xuXG4gIC8qKlxuICAgKiBFeHRyYWN0IGZyYXVkIGJveGVzIGluIHRoZSBzcGVjaWZpZWQgYmxvY2sgdHJhbnNhY3Rpb25zXG4gICAqIEBwYXJhbSB0eHNcbiAgICogQHBhcmFtIGJsb2NrXG4gICAqL1xuICBwcm9jZXNzVHJhbnNhY3Rpb25zID0gKFxuICAgIHR4czogQXJyYXk8VHJhbnNhY3Rpb24+LFxuICAgIGJsb2NrOiBCbG9ja0VudGl0eVxuICApOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgbmV3RnJhdWRzOiBBcnJheTxFeHRyYWN0ZWRGcmF1ZD4gPSBbXTtcbiAgICAgICAgY29uc3QgdHhTcGVuZElkczogQXJyYXk8eyB0eElkOiBzdHJpbmc7IHNwZW5kQm94ZXM6IEFycmF5PHN0cmluZz4gfT4gPVxuICAgICAgICAgIFtdO1xuICAgICAgICB0eHMuZm9yRWFjaCgodHJhbnNhY3Rpb24pID0+IHtcbiAgICAgICAgICBmb3IgKGNvbnN0IG91dHB1dCBvZiB0cmFuc2FjdGlvbi5vdXRwdXRzKSB7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIG91dHB1dC5lcmdvVHJlZSAhPT0gdGhpcy5lcmdvVHJlZSB8fFxuICAgICAgICAgICAgICAhb3V0cHV0LmFzc2V0cyB8fFxuICAgICAgICAgICAgICBvdXRwdXQuYXNzZXRzWzBdLnRva2VuSWQgIT09IHRoaXMucnd0XG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBib3hPdXRwdXQgPSB3YXNtLkVyZ29Cb3guZnJvbV9qc29uKEpzb25CSS5zdHJpbmdpZnkob3V0cHV0KSk7XG4gICAgICAgICAgICBjb25zdCByNCA9IGJveE91dHB1dFxuICAgICAgICAgICAgICAucmVnaXN0ZXJfdmFsdWUod2FzbS5Ob25NYW5kYXRvcnlSZWdpc3RlcklkLlI0KVxuICAgICAgICAgICAgICA/LnRvX2NvbGxfY29sbF9ieXRlKCk7XG4gICAgICAgICAgICBpZiAoIXI0KSB7XG4gICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgICAgIGBBIG5ldyBmcmF1ZCBib3ggZm91bmQgd2l0aG91dCBjb3JyZWN0IHdpZCBmb3JtYXQgYXQgaGVpZ2h0ICR7YmxvY2suaGVpZ2h0fWBcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBuZXdGcmF1ZCA9IHtcbiAgICAgICAgICAgICAgYm94SWQ6IG91dHB1dC5ib3hJZCxcbiAgICAgICAgICAgICAgdHhJZDogdHJhbnNhY3Rpb24uaWQsXG4gICAgICAgICAgICAgIHRyaWdnZXJCb3hJZDogdHJhbnNhY3Rpb24uaW5wdXRzWzBdLmJveElkLFxuICAgICAgICAgICAgICB3aWQ6IEJ1ZmZlci5mcm9tKHI0WzBdKS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgICAgIHJ3dENvdW50OiBvdXRwdXQuYXNzZXRzWzBdLmFtb3VudC50b1N0cmluZygpLFxuICAgICAgICAgICAgICBzZXJpYWxpemVkOiBCdWZmZXIuZnJvbShcbiAgICAgICAgICAgICAgICB3YXNtLkVyZ29Cb3guZnJvbV9qc29uKFxuICAgICAgICAgICAgICAgICAgSnNvbkJJLnN0cmluZ2lmeShvdXRwdXQpXG4gICAgICAgICAgICAgICAgKS5zaWdtYV9zZXJpYWxpemVfYnl0ZXMoKVxuICAgICAgICAgICAgICApLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBuZXdGcmF1ZHMucHVzaChuZXdGcmF1ZCk7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICAgICAgYG5ldyBmcmF1ZCBmb3VuZCBbJHtuZXdGcmF1ZH1dIGF0IGhlaWdodCAke2Jsb2NrLmhlaWdodH1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0eFNwZW5kSWRzLnB1c2goe1xuICAgICAgICAgICAgdHhJZDogdHJhbnNhY3Rpb24uaWQsXG4gICAgICAgICAgICBzcGVuZEJveGVzOiB0cmFuc2FjdGlvbi5pbnB1dHMubWFwKChib3gpID0+IGJveC5ib3hJZCksXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFjdGlvbnNcbiAgICAgICAgICAuc3RvcmVCbG9ja0ZyYXVkcyhuZXdGcmF1ZHMsIGJsb2NrLCB0aGlzLmdldElkKCkpXG4gICAgICAgICAgLnRoZW4oYXN5bmMgKHN0YXR1cykgPT4ge1xuICAgICAgICAgICAgaWYgKHN0YXR1cykge1xuICAgICAgICAgICAgICBpZiAobmV3RnJhdWRzLmxlbmd0aCA+IDApXG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICAgICAgICAgICAgICBgc3VjY2Vzc2Z1bGx5IHN0b3JlZCBuZXcgZnJhdWRzIGF0IGhpZ2h0ICR7YmxvY2suaGVpZ2h0fWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBmb3IgKGNvbnN0IHNwZW5kSWRzIG9mIHR4U3BlbmRJZHMpXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5hY3Rpb25zLnNwZW5kRnJhdWRzKFxuICAgICAgICAgICAgICAgICAgc3BlbmRJZHMuc3BlbmRCb3hlcyxcbiAgICAgICAgICAgICAgICAgIGJsb2NrLFxuICAgICAgICAgICAgICAgICAgdGhpcy5nZXRJZCgpLFxuICAgICAgICAgICAgICAgICAgc3BlbmRJZHMudHhJZFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXNvbHZlKHN0YXR1cyk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICBgQW4gZXJyb3Igb2NjdXJyZWQgaW4gcHJvY2Vzc2luZyBmcmF1ZHMgaW4gYmxvY2sgWyR7YmxvY2suaGFzaH1dOiAke2V9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBmb3JrIG9uZSBibG9jayBhbmQgcmVtb3ZlIGFsbCBzdG9yZWQgaW5mb3JtYXRpb24gZm9yIHRoaXMgYmxvY2tcbiAgICogQHBhcmFtIGhhc2g6IGJsb2NrIGhhc2hcbiAgICovXG4gIGZvcmtCbG9jayA9IGFzeW5jIChoYXNoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICBhd2FpdCB0aGlzLmFjdGlvbnMuZGVsZXRlQmxvY2soaGFzaCwgdGhpcy5nZXRJZCgpKTtcbiAgfTtcblxuICAvKipcbiAgICogSW5pdGlhbGl6ZXMgdGhlIGRhdGFiYXNlIHdpdGggb2xkZXIgZnJhdWRzXG4gICAqL1xuICBpbml0aWFsaXplQm94ZXMgPSBhc3luYyAoaW5pdGlhbEhlaWdodDogbnVtYmVyKSA9PiB7XG4gICAgLy8gR2V0dGluZyB1bnNwZW50IGJveGVzXG4gICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICBgSW5pdGlhbGl6aW5nIGZyYXVkIHRhYmxlLiBzdG9yaW5nIGZyYXVkIGJveGVzIGNyZWF0ZWQgYmVsbG93IGhlaWdodCAke2luaXRpYWxIZWlnaHR9LmBcbiAgICApO1xuICAgIGNvbnN0IHVuc3BlbnRGcmF1ZHMgPSBhd2FpdCB0aGlzLmdldFVuc3BlbnRGcmF1ZHMoaW5pdGlhbEhlaWdodCk7XG4gICAgY29uc3QgdW5zcGVudEJveElkcyA9IHVuc3BlbnRGcmF1ZHMubWFwKChib3gpID0+IGJveC5ib3hJZCk7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoYFVuc3BlbnQgZnJhdWQgYm94SWRzICR7dW5zcGVudEJveElkc31gKTtcblxuICAgIC8vIFN0b3JpbmcgZXh0cmFjdGVkIGJveGVzXG4gICAgbGV0IGFsbFN0b3JlZEJveElkcyA9IGF3YWl0IHRoaXMuYWN0aW9ucy5nZXRBbGxCb3hJZHModGhpcy5nZXRJZCgpKTtcbiAgICBmb3IgKGNvbnN0IGZyYXVkIG9mIHVuc3BlbnRGcmF1ZHMpIHtcbiAgICAgIGlmIChhbGxTdG9yZWRCb3hJZHMuaW5jbHVkZXMoZnJhdWQuYm94SWQpKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYWN0aW9ucy51cGRhdGVGcmF1ZChmcmF1ZCwgdGhpcy5nZXRJZCgpKTtcbiAgICAgICAgdGhpcy5sb2dnZXIuaW5mbyhcbiAgICAgICAgICBgVXBkYXRlZCB0aGUgZXhpc3RpbmcgdW5zcGVudCBmcmF1ZCB3aXRoIGJveElkLCBbJHtmcmF1ZC5ib3hJZH1dYFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgVXBkYXRlZCBmcmF1ZDogWyR7SlNPTi5zdHJpbmdpZnkoZnJhdWQpfV1gKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYWN0aW9ucy5pbnNlcnRGcmF1ZChmcmF1ZCwgdGhpcy5nZXRJZCgpKTtcbiAgICAgICAgdGhpcy5sb2dnZXIuaW5mbyhcbiAgICAgICAgICBgSW5zZXJ0ZWQgbmV3IHVuc3BlbnQgZnJhdWQgd2l0aCBib3hJZCwgWyR7ZnJhdWQuYm94SWR9XWBcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoYEluc2VydGVkIGZyYXVkOiBbJHtKU09OLnN0cmluZ2lmeShmcmF1ZCl9XWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlbW92ZSB1cGRhdGVkIGJveCBpZHMgZnJvbSBleGlzdGluZyBib3hlcyBpbiBkYXRhYmFzZVxuICAgIGFsbFN0b3JlZEJveElkcyA9IGRpZmZlcmVuY2UoYWxsU3RvcmVkQm94SWRzLCB1bnNwZW50Qm94SWRzKTtcbiAgICAvLyBWYWxpZGF0aW5nIHJlbWFpbmVkIGJveGVzXG4gICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICBgVmFsaWRhdGluZyBhbmQgdXBkYXRpbmcgc3RvcmVkIGZyYXVkIGJveGVzIHdpdGggYm94SWRzICR7YWxsU3RvcmVkQm94SWRzfWBcbiAgICApO1xuICAgIGF3YWl0IHRoaXMudmFsaWRhdGVPbGRTdG9yZWRGcmF1ZHMoYWxsU3RvcmVkQm94SWRzLCBpbml0aWFsSGVpZ2h0KTtcbiAgfTtcblxuICAvKipcbiAgICogVmFsaWRhdGUgYWxsIHJlbWFpbmluZyBib3hlcyBpbiB0aGUgZGF0YWJhc2VcbiAgICogdXBkYXRlIHRoZSBjb3JyZWN0IG9uZXMgYW5kIHJlbW92ZSB0aGUgaW52YWxpZCBvbmVzXG4gICAqIEBwYXJhbSB1bmNoYW5nZWRTdG9yZWRCb3hJZHNcbiAgICogQHBhcmFtIGluaXRpYWxIZWlnaHRcbiAgICovXG4gIHZhbGlkYXRlT2xkU3RvcmVkRnJhdWRzID0gYXN5bmMgKFxuICAgIHVuY2hhbmdlZFN0b3JlZEJveElkczogQXJyYXk8c3RyaW5nPixcbiAgICBpbml0aWFsSGVpZ2h0OiBudW1iZXJcbiAgKSA9PiB7XG4gICAgZm9yIChjb25zdCBib3hJZCBvZiB1bmNoYW5nZWRTdG9yZWRCb3hJZHMpIHtcbiAgICAgIGNvbnN0IGJveCA9IGF3YWl0IHRoaXMuZ2V0RnJhdWRJbmZvV2l0aEJveElkKGJveElkKTtcbiAgICAgIGlmIChib3ggJiYgYm94LnNwZW5kQmxvY2sgJiYgYm94LnNwZW5kSGVpZ2h0KSB7XG4gICAgICAgIGlmIChib3guc3BlbmRIZWlnaHQgPCBpbml0aWFsSGVpZ2h0KSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICAgICAgICBgdXBkYXRpbmcgc3BlbmRpbmcgaW5mb3JtYXRpb24gb2YgZnJhdWQgd2l0aCBib3hJZCBbJHtib3guYm94SWR9XSBzcGVudCBhdCBoZWlnaHQgWyR7Ym94LnNwZW5kSGVpZ2h0fV1gXG4gICAgICAgICAgKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLmFjdGlvbnMudXBkYXRlU3BlbmRCbG9jayhcbiAgICAgICAgICAgIGJveElkLFxuICAgICAgICAgICAgdGhpcy5nZXRJZCgpLFxuICAgICAgICAgICAgYm94LnNwZW5kQmxvY2ssXG4gICAgICAgICAgICBib3guc3BlbmRIZWlnaHRcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgYGZyYXVkIHdpdGggYm94SWQgWyR7Ym94LmJveElkfV0gaGFzIGJlZW4gc3BlbnQgYWZ0ZXIgdGhlIGluaXRpYWxpemF0aW9uIGhlaWdodCwgdXBkYXRpbmcgc3BlbmRpbmcgaW5mb3JtYXRpb24gc2tpcHBlZC5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgdGhpcy5hY3Rpb25zLnJlbW92ZUZyYXVkKGJveElkLCB0aGlzLmdldElkKCkpO1xuICAgICAgICB0aGlzLmxvZ2dlci5pbmZvKFxuICAgICAgICAgIGBSZW1vdmVkIGludmFsaWQgZnJhdWQgWyR7Ym94SWR9XSBpbiBpbml0aWFsaXphdGlvbiB2YWxpZGF0aW9uYFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogUmV0dXJuIGV4dHJhY3RlZCBpbmZvcm1hdGlvbiBvZiBhIGZyYXVkIHdpdGggaXRzIGJveElkXG4gICAqIEBwYXJhbSBib3hJZFxuICAgKi9cbiAgZ2V0RnJhdWRJbmZvV2l0aEJveElkID0gYXN5bmMgKFxuICAgIGJveElkOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxFeHRyYWN0ZWRGcmF1ZCB8IHVuZGVmaW5lZD4gPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBib3ggPSBhd2FpdCB0aGlzLmFwaS52MS5nZXRBcGlWMUJveGVzUDEoYm94SWQpO1xuICAgICAgcmV0dXJuIChhd2FpdCB0aGlzLmV4dHJhY3RCb3hEYXRhKFtib3hdKSlbMF07XG4gICAgfSBjYXRjaCB7XG4gICAgICB0aGlzLmxvZ2dlci53YXJuKGBCb3ggd2l0aCBpZCBbJHtib3hJZH1dIGRvZXMgbm90IGV4aXN0c2ApO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCB1bnNwZW50IGZyYXVkcyBjcmVhdGVkIGJlbGxvdyB0aGUgaW5pdGlhbCBoZWlnaHRcbiAgICogQHBhcmFtIGluaXRpYWxIZWlnaHRcbiAgICogQHJldHVybnNcbiAgICovXG4gIGdldFVuc3BlbnRGcmF1ZHMgPSBhc3luYyAoXG4gICAgaW5pdGlhbEhlaWdodDogbnVtYmVyXG4gICk6IFByb21pc2U8QXJyYXk8RXh0cmFjdGVkRnJhdWQ+PiA9PiB7XG4gICAgbGV0IGFsbEJveGVzOiBBcnJheTxFeHRyYWN0ZWRGcmF1ZD4gPSBbXTtcbiAgICBsZXQgb2Zmc2V0ID0gMCxcbiAgICAgIHRvdGFsID0gRGVmYXVsdEFwaUxpbWl0LFxuICAgICAgYm94ZXM6IFYxLkl0ZW1zT3V0cHV0SW5mbztcbiAgICB3aGlsZSAob2Zmc2V0IDwgdG90YWwpIHtcbiAgICAgIGJveGVzID0gYXdhaXQgdGhpcy5hcGkudjEuZ2V0QXBpVjFCb3hlc1Vuc3BlbnRCeWVyZ290cmVlUDEoXG4gICAgICAgIHRoaXMuZXJnb1RyZWUsXG4gICAgICAgIHtcbiAgICAgICAgICBvZmZzZXQ6IG9mZnNldCxcbiAgICAgICAgICBsaW1pdDogRGVmYXVsdEFwaUxpbWl0LFxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgaWYgKCFib3hlcy5pdGVtcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGxvcmVyIGFwaSBvdXRwdXQgaXRlbXMgc2hvdWxkIG5vdCBiZSB1bmRlZmluZWQuJyk7XG4gICAgICB9XG4gICAgICBhbGxCb3hlcyA9IFtcbiAgICAgICAgLi4uYWxsQm94ZXMsXG4gICAgICAgIC4uLihhd2FpdCB0aGlzLmV4dHJhY3RCb3hEYXRhKFxuICAgICAgICAgIGJveGVzLml0ZW1zLmZpbHRlcihcbiAgICAgICAgICAgIChib3gpID0+XG4gICAgICAgICAgICAgIGJveC5jcmVhdGlvbkhlaWdodCA8IGluaXRpYWxIZWlnaHQgJiZcbiAgICAgICAgICAgICAgYm94LmFzc2V0cyAmJlxuICAgICAgICAgICAgICBib3guYXNzZXRzWzBdLnRva2VuSWQgPT0gdGhpcy5yd3RcbiAgICAgICAgICApXG4gICAgICAgICkpLFxuICAgICAgXTtcbiAgICAgIHRvdGFsID0gYm94ZXMudG90YWw7XG4gICAgICBvZmZzZXQgKz0gRGVmYXVsdEFwaUxpbWl0O1xuICAgIH1cbiAgICByZXR1cm4gYWxsQm94ZXM7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYmxvY2sgaW5mb3JtYXRpb24gb2YgdHhcbiAgICogQHBhcmFtIHR4SWRcbiAgICovXG4gIGdldFR4QmxvY2sgPSBhc3luYyAodHhJZDogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgdHggPSBhd2FpdCB0aGlzLmFwaS52MS5nZXRBcGlWMVRyYW5zYWN0aW9uc1AxKHR4SWQpO1xuICAgIHJldHVybiB7XG4gICAgICBpZDogdHguYmxvY2tJZCxcbiAgICAgIGhlaWdodDogdHguaW5jbHVzaW9uSGVpZ2h0LFxuICAgIH07XG4gIH07XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJpZ2dlciBib3hJZCBmcm9tIGZyYXVkIHRyYW5zYWN0aW9uIGlkXG4gICAqIEBwYXJhbSB0eElkXG4gICAqL1xuICBnZXRUcmlnZ2VyQm94SWQgPSBhc3luYyAodHhJZDogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgdHggPSBhd2FpdCB0aGlzLmFwaS52MS5nZXRBcGlWMVRyYW5zYWN0aW9uc1AxKHR4SWQpO1xuICAgIHJldHVybiB0eC5pbnB1dHM/LlswXS5ib3hJZDtcbiAgfTtcblxuICAvKipcbiAgICogRXh0cmFjdCBuZWVkZWQgaW5mb3JtYXRpb24gZm9yIHN0b3JpbmcgaW4gZGF0YWJhc2UgZnJvbSBhcGkganNvbiBvdXRwdXRzXG4gICAqIEBwYXJhbSBib3hlc1xuICAgKi9cbiAgZXh0cmFjdEJveERhdGEgPSBhc3luYyAoYm94ZXM6IEFycmF5PFYxLk91dHB1dEluZm8+KSA9PiB7XG4gICAgY29uc3QgZXh0cmFjdGVkRnJhdWRzOiBBcnJheTxFeHRyYWN0ZWRGcmF1ZD4gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGJveCBvZiBib3hlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICAgICAgYEV4dHJhY3RpbmcgYm94IGZyYXVkIGluZm9ybWF0aW9uIGZyb20gYm94IHdpdGggYm94SWQgWyR7Ym94LmJveElkfV1gXG4gICAgICAgICk7XG4gICAgICAgIGxldCBzcGVuZEJsb2NrLCBzcGVuZEhlaWdodDtcbiAgICAgICAgLy8gRXh0cmFjdCBzcGVuZGluZyBpbmZvcm1hdGlvblxuICAgICAgICBpZiAoYm94LnNwZW50VHJhbnNhY3Rpb25JZCkge1xuICAgICAgICAgIGNvbnN0IGJsb2NrID0gYXdhaXQgdGhpcy5nZXRUeEJsb2NrKGJveC5zcGVudFRyYW5zYWN0aW9uSWQpO1xuICAgICAgICAgIHNwZW5kQmxvY2sgPSBibG9jay5pZDtcbiAgICAgICAgICBzcGVuZEhlaWdodCA9IGJsb2NrLmhlaWdodDtcbiAgICAgICAgfVxuICAgICAgICAvLyBFeHRyYWN0IFdJRFxuICAgICAgICBjb25zdCBlcmdvQm94ID0gd2FzbS5FcmdvQm94LmZyb21fanNvbihKc29uQkkuc3RyaW5naWZ5KGJveCkpO1xuICAgICAgICBjb25zdCByNCA9IGVyZ29Cb3hcbiAgICAgICAgICAucmVnaXN0ZXJfdmFsdWUod2FzbS5Ob25NYW5kYXRvcnlSZWdpc3RlcklkLlI0KVxuICAgICAgICAgID8udG9fY29sbF9jb2xsX2J5dGUoKTtcbiAgICAgICAgLy8gRXh0cmFjdCB0cmlnZ2VyIGJveElkXG4gICAgICAgIGNvbnN0IHRyaWdnZXJCb3hJZCA9IGF3YWl0IHRoaXMuZ2V0VHJpZ2dlckJveElkKGJveC50cmFuc2FjdGlvbklkKTtcbiAgICAgICAgaWYgKCFyNCB8fCAhdHJpZ2dlckJveElkKSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIud2FybihcbiAgICAgICAgICAgIGBTa2lwcGluZyBzdG9yaW5nIGZyYXVkIHdpdGggYm94SWQgWyR7Ym94LmJveElkfV0sIHdpZCBvciB0cmlnZ2VyIGJveCBpZCBpcyB1bmRlZmluZWRgXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGV4dHJhY3RlZEZyYXVkID0ge1xuICAgICAgICAgIGJveElkOiBlcmdvQm94LmJveF9pZCgpLnRvX3N0cigpLFxuICAgICAgICAgIHRyaWdnZXJCb3hJZDogdHJpZ2dlckJveElkLFxuICAgICAgICAgIHdpZDogQnVmZmVyLmZyb20ocjRbMF0pLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgICByd3RDb3VudDogYm94LmFzc2V0cyFbMF0uYW1vdW50LnRvU3RyaW5nKCksXG4gICAgICAgICAgc2VyaWFsaXplZDogQnVmZmVyLmZyb20oZXJnb0JveC5zaWdtYV9zZXJpYWxpemVfYnl0ZXMoKSkudG9TdHJpbmcoXG4gICAgICAgICAgICAnYmFzZTY0J1xuICAgICAgICAgICksXG4gICAgICAgICAgYmxvY2tJZDogYm94LmJsb2NrSWQsXG4gICAgICAgICAgaGVpZ2h0OiBib3guc2V0dGxlbWVudEhlaWdodCxcbiAgICAgICAgICB0eElkOiBib3gudHJhbnNhY3Rpb25JZCxcbiAgICAgICAgICBzcGVuZEJsb2NrOiBzcGVuZEJsb2NrLFxuICAgICAgICAgIHNwZW5kSGVpZ2h0OiBzcGVuZEhlaWdodCxcbiAgICAgICAgICBzcGVuZFR4SWQ6IGJveC5zcGVudFRyYW5zYWN0aW9uSWQsXG4gICAgICAgIH07XG4gICAgICAgIGV4dHJhY3RlZEZyYXVkcy5wdXNoKGV4dHJhY3RlZEZyYXVkKTtcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoYEV4dHJhY3RlZCBmcmF1ZDogWyR7ZXh0cmFjdGVkRnJhdWR9XWApO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihcbiAgICAgICAgICBgRXh0cmFjdGluZyBmcmF1ZCBpbmZvcm1hdGlvbiBmYWlsZWQgZm9yIGJveCBbJHtib3guYm94SWR9XSB3aXRoIGVycm9yOiAke2V9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZXh0cmFjdGVkRnJhdWRzO1xuICB9O1xufVxuIl19
@@ -0,0 +1,4 @@
1
+ export { FraudExtractor } from './extractor/fraudExtractor';
2
+ export { FraudEntity } from './entities/fraudEntity';
3
+ export { migrations } from './migrations/index';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { FraudExtractor } from './extractor/fraudExtractor';
2
+ export { FraudEntity } from './entities/fraudEntity';
3
+ export { migrations } from './migrations/index';
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9saWIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzVELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgeyBGcmF1ZEV4dHJhY3RvciB9IGZyb20gJy4vZXh0cmFjdG9yL2ZyYXVkRXh0cmFjdG9yJztcbmV4cG9ydCB7IEZyYXVkRW50aXR5IH0gZnJvbSAnLi9lbnRpdGllcy9mcmF1ZEVudGl0eSc7XG5leHBvcnQgeyBtaWdyYXRpb25zIH0gZnJvbSAnLi9taWdyYXRpb25zL2luZGV4JztcbiJdfQ==
@@ -0,0 +1,15 @@
1
+ interface ExtractedFraud {
2
+ boxId: string;
3
+ serialized: string;
4
+ triggerBoxId: string;
5
+ wid: string;
6
+ rwtCount: string;
7
+ blockId?: string;
8
+ height?: number;
9
+ txId?: string;
10
+ spendBlock?: string;
11
+ spendHeight?: number;
12
+ spendTxId?: string;
13
+ }
14
+ export { ExtractedFraud };
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../lib/interfaces/types.ts"],"names":[],"mappings":"AAAA,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvaW50ZXJmYWNlcy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiaW50ZXJmYWNlIEV4dHJhY3RlZEZyYXVkIHtcbiAgYm94SWQ6IHN0cmluZztcbiAgc2VyaWFsaXplZDogc3RyaW5nO1xuICB0cmlnZ2VyQm94SWQ6IHN0cmluZztcbiAgd2lkOiBzdHJpbmc7XG4gIHJ3dENvdW50OiBzdHJpbmc7XG4gIGJsb2NrSWQ/OiBzdHJpbmc7XG4gIGhlaWdodD86IG51bWJlcjtcbiAgdHhJZD86IHN0cmluZztcbiAgc3BlbmRCbG9jaz86IHN0cmluZztcbiAgc3BlbmRIZWlnaHQ/OiBudW1iZXI7XG4gIHNwZW5kVHhJZD86IHN0cmluZztcbn1cblxuZXhwb3J0IHsgRXh0cmFjdGVkRnJhdWQgfTtcbiJdfQ==
@@ -0,0 +1,7 @@
1
+ import { migration1693308311652 } from './postgres/1693308311652-migration';
2
+ import { migration1693122371215 } from './sqlite/1693122371215-migration';
3
+ export declare const migrations: {
4
+ sqlite: (typeof migration1693122371215)[];
5
+ postgres: (typeof migration1693308311652)[];
6
+ };
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,eAAO,MAAM,UAAU;;;CAGtB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { migration1693308311652 } from './postgres/1693308311652-migration';
2
+ import { migration1693122371215 } from './sqlite/1693122371215-migration';
3
+ export const migrations = {
4
+ sqlite: [migration1693122371215],
5
+ postgres: [migration1693308311652],
6
+ };
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvbWlncmF0aW9ucy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUM1RSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUUxRSxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUc7SUFDeEIsTUFBTSxFQUFFLENBQUMsc0JBQXNCLENBQUM7SUFDaEMsUUFBUSxFQUFFLENBQUMsc0JBQXNCLENBQUM7Q0FDbkMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG1pZ3JhdGlvbjE2OTMzMDgzMTE2NTIgfSBmcm9tICcuL3Bvc3RncmVzLzE2OTMzMDgzMTE2NTItbWlncmF0aW9uJztcbmltcG9ydCB7IG1pZ3JhdGlvbjE2OTMxMjIzNzEyMTUgfSBmcm9tICcuL3NxbGl0ZS8xNjkzMTIyMzcxMjE1LW1pZ3JhdGlvbic7XG5cbmV4cG9ydCBjb25zdCBtaWdyYXRpb25zID0ge1xuICBzcWxpdGU6IFttaWdyYXRpb24xNjkzMTIyMzcxMjE1XSxcbiAgcG9zdGdyZXM6IFttaWdyYXRpb24xNjkzMzA4MzExNjUyXSxcbn07XG4iXX0=
@@ -0,0 +1,7 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm';
2
+ export declare class migration1693308311652 implements MigrationInterface {
3
+ name: string;
4
+ up(queryRunner: QueryRunner): Promise<void>;
5
+ down(queryRunner: QueryRunner): Promise<void>;
6
+ }
7
+ //# sourceMappingURL=1693308311652-migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"1693308311652-migration.d.ts","sourceRoot":"","sources":["../../../lib/migrations/postgres/1693308311652-migration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1D,qBAAa,sBAAuB,YAAW,kBAAkB;IAC/D,IAAI,SAA4B;IAEnB,EAAE,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB3C,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAK3D"}
@@ -0,0 +1,29 @@
1
+ export class migration1693308311652 {
2
+ name = 'migration1693308311652';
3
+ async up(queryRunner) {
4
+ await queryRunner.query(`
5
+ CREATE TABLE "fraud_entity" (
6
+ "id" SERIAL NOT NULL,
7
+ "boxId" character varying NOT NULL,
8
+ "creationBlock" character varying NOT NULL,
9
+ "creationHeight" integer NOT NULL,
10
+ "creationTxId" character varying NOT NULL,
11
+ "serialized" character varying NOT NULL,
12
+ "triggerBoxId" character varying NOT NULL,
13
+ "wid" character varying NOT NULL,
14
+ "rwtCount" character varying NOT NULL,
15
+ "spendBlock" text,
16
+ "spendHeight" integer,
17
+ "spendTxId" text,
18
+ "extractor" character varying NOT NULL,
19
+ CONSTRAINT "PK_2cf2cfa218dd4a5642bc3f3cf98" PRIMARY KEY ("id")
20
+ )
21
+ `);
22
+ }
23
+ async down(queryRunner) {
24
+ await queryRunner.query(`
25
+ DROP TABLE "fraud_entity"
26
+ `);
27
+ }
28
+ }
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTY5MzMwODMxMTY1Mi1taWdyYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9saWIvbWlncmF0aW9ucy9wb3N0Z3Jlcy8xNjkzMzA4MzExNjUyLW1pZ3JhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxNQUFNLE9BQU8sc0JBQXNCO0lBQ2pDLElBQUksR0FBRyx3QkFBd0IsQ0FBQztJQUV6QixLQUFLLENBQUMsRUFBRSxDQUFDLFdBQXdCO1FBQ3RDLE1BQU0sV0FBVyxDQUFDLEtBQUssQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7U0FpQm5CLENBQUMsQ0FBQztJQUNULENBQUM7SUFFTSxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQXdCO1FBQ3hDLE1BQU0sV0FBVyxDQUFDLEtBQUssQ0FBQzs7U0FFbkIsQ0FBQyxDQUFDO0lBQ1QsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTWlncmF0aW9uSW50ZXJmYWNlLCBRdWVyeVJ1bm5lciB9IGZyb20gJ3R5cGVvcm0nO1xuXG5leHBvcnQgY2xhc3MgbWlncmF0aW9uMTY5MzMwODMxMTY1MiBpbXBsZW1lbnRzIE1pZ3JhdGlvbkludGVyZmFjZSB7XG4gIG5hbWUgPSAnbWlncmF0aW9uMTY5MzMwODMxMTY1Mic7XG5cbiAgcHVibGljIGFzeW5jIHVwKHF1ZXJ5UnVubmVyOiBRdWVyeVJ1bm5lcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnF1ZXJ5KGBcbiAgICAgICAgICAgIENSRUFURSBUQUJMRSBcImZyYXVkX2VudGl0eVwiIChcbiAgICAgICAgICAgICAgICBcImlkXCIgU0VSSUFMIE5PVCBOVUxMLFxuICAgICAgICAgICAgICAgIFwiYm94SWRcIiBjaGFyYWN0ZXIgdmFyeWluZyBOT1QgTlVMTCxcbiAgICAgICAgICAgICAgICBcImNyZWF0aW9uQmxvY2tcIiBjaGFyYWN0ZXIgdmFyeWluZyBOT1QgTlVMTCxcbiAgICAgICAgICAgICAgICBcImNyZWF0aW9uSGVpZ2h0XCIgaW50ZWdlciBOT1QgTlVMTCxcbiAgICAgICAgICAgICAgICBcImNyZWF0aW9uVHhJZFwiIGNoYXJhY3RlciB2YXJ5aW5nIE5PVCBOVUxMLFxuICAgICAgICAgICAgICAgIFwic2VyaWFsaXplZFwiIGNoYXJhY3RlciB2YXJ5aW5nIE5PVCBOVUxMLFxuICAgICAgICAgICAgICAgIFwidHJpZ2dlckJveElkXCIgY2hhcmFjdGVyIHZhcnlpbmcgTk9UIE5VTEwsXG4gICAgICAgICAgICAgICAgXCJ3aWRcIiBjaGFyYWN0ZXIgdmFyeWluZyBOT1QgTlVMTCxcbiAgICAgICAgICAgICAgICBcInJ3dENvdW50XCIgY2hhcmFjdGVyIHZhcnlpbmcgTk9UIE5VTEwsXG4gICAgICAgICAgICAgICAgXCJzcGVuZEJsb2NrXCIgdGV4dCxcbiAgICAgICAgICAgICAgICBcInNwZW5kSGVpZ2h0XCIgaW50ZWdlcixcbiAgICAgICAgICAgICAgICBcInNwZW5kVHhJZFwiIHRleHQsXG4gICAgICAgICAgICAgICAgXCJleHRyYWN0b3JcIiBjaGFyYWN0ZXIgdmFyeWluZyBOT1QgTlVMTCxcbiAgICAgICAgICAgICAgICBDT05TVFJBSU5UIFwiUEtfMmNmMmNmYTIxOGRkNGE1NjQyYmMzZjNjZjk4XCIgUFJJTUFSWSBLRVkgKFwiaWRcIilcbiAgICAgICAgICAgIClcbiAgICAgICAgYCk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZG93bihxdWVyeVJ1bm5lcjogUXVlcnlSdW5uZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBxdWVyeVJ1bm5lci5xdWVyeShgXG4gICAgICAgICAgICBEUk9QIFRBQkxFIFwiZnJhdWRfZW50aXR5XCJcbiAgICAgICAgYCk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,7 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm';
2
+ export declare class migration1693122371215 implements MigrationInterface {
3
+ name: string;
4
+ up(queryRunner: QueryRunner): Promise<void>;
5
+ down(queryRunner: QueryRunner): Promise<void>;
6
+ }
7
+ //# sourceMappingURL=1693122371215-migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"1693122371215-migration.d.ts","sourceRoot":"","sources":["../../../lib/migrations/sqlite/1693122371215-migration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1D,qBAAa,sBAAuB,YAAW,kBAAkB;IAC/D,IAAI,SAA4B;IAEnB,EAAE,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB3C,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAK3D"}
@@ -0,0 +1,28 @@
1
+ export class migration1693122371215 {
2
+ name = 'migration1693122371215';
3
+ async up(queryRunner) {
4
+ await queryRunner.query(`
5
+ CREATE TABLE "fraud_entity" (
6
+ "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
7
+ "boxId" varchar NOT NULL,
8
+ "creationBlock" varchar NOT NULL,
9
+ "creationHeight" integer NOT NULL,
10
+ "creationTxId" varchar NOT NULL,
11
+ "serialized" varchar NOT NULL,
12
+ "triggerBoxId" varchar NOT NULL,
13
+ "wid" varchar NOT NULL,
14
+ "rwtCount" varchar NOT NULL,
15
+ "spendBlock" text,
16
+ "spendHeight" integer,
17
+ "spendTxId" text,
18
+ "extractor" varchar NOT NULL
19
+ )
20
+ `);
21
+ }
22
+ async down(queryRunner) {
23
+ await queryRunner.query(`
24
+ DROP TABLE "fraud_entity"
25
+ `);
26
+ }
27
+ }
28
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTY5MzEyMjM3MTIxNS1taWdyYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9saWIvbWlncmF0aW9ucy9zcWxpdGUvMTY5MzEyMjM3MTIxNS1taWdyYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTSxPQUFPLHNCQUFzQjtJQUNqQyxJQUFJLEdBQUcsd0JBQXdCLENBQUM7SUFFekIsS0FBSyxDQUFDLEVBQUUsQ0FBQyxXQUF3QjtRQUN0QyxNQUFNLFdBQVcsQ0FBQyxLQUFLLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7U0FnQm5CLENBQUMsQ0FBQztJQUNULENBQUM7SUFFTSxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQXdCO1FBQ3hDLE1BQU0sV0FBVyxDQUFDLEtBQUssQ0FBQzs7U0FFbkIsQ0FBQyxDQUFDO0lBQ1QsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTWlncmF0aW9uSW50ZXJmYWNlLCBRdWVyeVJ1bm5lciB9IGZyb20gJ3R5cGVvcm0nO1xuXG5leHBvcnQgY2xhc3MgbWlncmF0aW9uMTY5MzEyMjM3MTIxNSBpbXBsZW1lbnRzIE1pZ3JhdGlvbkludGVyZmFjZSB7XG4gIG5hbWUgPSAnbWlncmF0aW9uMTY5MzEyMjM3MTIxNSc7XG5cbiAgcHVibGljIGFzeW5jIHVwKHF1ZXJ5UnVubmVyOiBRdWVyeVJ1bm5lcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHF1ZXJ5UnVubmVyLnF1ZXJ5KGBcbiAgICAgICAgICAgIENSRUFURSBUQUJMRSBcImZyYXVkX2VudGl0eVwiIChcbiAgICAgICAgICAgICAgICBcImlkXCIgaW50ZWdlciBQUklNQVJZIEtFWSBBVVRPSU5DUkVNRU5UIE5PVCBOVUxMLFxuICAgICAgICAgICAgICAgIFwiYm94SWRcIiB2YXJjaGFyIE5PVCBOVUxMLFxuICAgICAgICAgICAgICAgIFwiY3JlYXRpb25CbG9ja1wiIHZhcmNoYXIgTk9UIE5VTEwsXG4gICAgICAgICAgICAgICAgXCJjcmVhdGlvbkhlaWdodFwiIGludGVnZXIgTk9UIE5VTEwsXG4gICAgICAgICAgICAgICAgXCJjcmVhdGlvblR4SWRcIiB2YXJjaGFyIE5PVCBOVUxMLFxuICAgICAgICAgICAgICAgIFwic2VyaWFsaXplZFwiIHZhcmNoYXIgTk9UIE5VTEwsXG4gICAgICAgICAgICAgICAgXCJ0cmlnZ2VyQm94SWRcIiB2YXJjaGFyIE5PVCBOVUxMLFxuICAgICAgICAgICAgICAgIFwid2lkXCIgdmFyY2hhciBOT1QgTlVMTCxcbiAgICAgICAgICAgICAgICBcInJ3dENvdW50XCIgdmFyY2hhciBOT1QgTlVMTCxcbiAgICAgICAgICAgICAgICBcInNwZW5kQmxvY2tcIiB0ZXh0LFxuICAgICAgICAgICAgICAgIFwic3BlbmRIZWlnaHRcIiBpbnRlZ2VyLFxuICAgICAgICAgICAgICAgIFwic3BlbmRUeElkXCIgdGV4dCxcbiAgICAgICAgICAgICAgICBcImV4dHJhY3RvclwiIHZhcmNoYXIgTk9UIE5VTExcbiAgICAgICAgICAgIClcbiAgICAgICAgYCk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZG93bihxdWVyeVJ1bm5lcjogUXVlcnlSdW5uZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBxdWVyeVJ1bm5lci5xdWVyeShgXG4gICAgICAgICAgICBEUk9QIFRBQkxFIFwiZnJhdWRfZW50aXR5XCJcbiAgICAgICAgYCk7XG4gIH1cbn1cbiJdfQ==
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@rosen-bridge/fraud-extractor",
3
+ "version": "0.1.1",
4
+ "description": "fraud information extractor for watcher faulty reports",
5
+ "author": "Rosen Team",
6
+ "license": "GPL-3.0",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "prettify": "prettier --write . --ignore-path ../../.gitignore",
14
+ "lint": "eslint --fix . && npm run prettify",
15
+ "test": "jest --detectOpenHandles",
16
+ "coverage": "jest --detectOpenHandles --coverage",
17
+ "build": "tsc --build",
18
+ "type-check": "tsc --noEmit",
19
+ "release": "npm run test && npm run build && npm publish --access public"
20
+ },
21
+ "dependencies": {
22
+ "@rosen-bridge/abstract-logger": "^0.3.0",
23
+ "@rosen-bridge/json-bigint": "^0.1.0",
24
+ "@rosen-bridge/scanner": "^2.2.1",
25
+ "blakejs": "^1.2.1",
26
+ "ergo-lib-wasm-nodejs": "^0.24.1",
27
+ "lodash-es": "^4.17.21",
28
+ "reflect-metadata": "^0.1.13",
29
+ "sqlite3": "^5.0.9",
30
+ "typeorm": "^0.3.7"
31
+ },
32
+ "type": "module",
33
+ "devDependencies": {
34
+ "@babel/preset-env": "^7.19.0",
35
+ "@types/jest": "^28.1.6",
36
+ "@types/json-bigint": "^1.0.1",
37
+ "@types/node": "^18.0.6",
38
+ "@typescript-eslint/eslint-plugin": "^5.30.7",
39
+ "@typescript-eslint/parser": "^5.26.0",
40
+ "eslint": "^8.16.0",
41
+ "eslint-config-prettier": "^8.5.0",
42
+ "jest": "^28.1.3",
43
+ "json-bigint": "^1.0.0",
44
+ "prettier": "2.7.1",
45
+ "ts-jest": "^28.0.7",
46
+ "ts-node": "^10.9.1",
47
+ "typescript": "^4.7.4"
48
+ },
49
+ "engines": {
50
+ "node": ">=16.14.0"
51
+ }
52
+ }