@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 +39 -0
- package/dist/actions/fraudAction.d.ts +64 -0
- package/dist/actions/fraudAction.d.ts.map +1 -0
- package/dist/actions/fraudAction.js +196 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +4 -0
- package/dist/entities/fraudEntity.d.ts +16 -0
- package/dist/entities/fraudEntity.d.ts.map +1 -0
- package/dist/entities/fraudEntity.js +82 -0
- package/dist/extractor/fraudExtractor.d.ts +144 -0
- package/dist/extractor/fraudExtractor.d.ts.map +1 -0
- package/dist/extractor/fraudExtractor.js +262 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/interfaces/types.d.ts +15 -0
- package/dist/interfaces/types.d.ts.map +1 -0
- package/dist/interfaces/types.js +2 -0
- package/dist/migrations/index.d.ts +7 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +7 -0
- package/dist/migrations/postgres/1693308311652-migration.d.ts +7 -0
- package/dist/migrations/postgres/1693308311652-migration.d.ts.map +1 -0
- package/dist/migrations/postgres/1693308311652-migration.js +29 -0
- package/dist/migrations/sqlite/1693122371215-migration.d.ts +7 -0
- package/dist/migrations/sqlite/1693122371215-migration.d.ts.map +1 -0
- package/dist/migrations/sqlite/1693122371215-migration.js +28 -0
- package/package.json +52 -0
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 @@
|
|
|
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
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|