@my-packages-changeit/abstract-scanner 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +135 -0
  2. package/README.md +49 -0
  3. package/dist/entities/blockEntity.d.ts +17 -0
  4. package/dist/entities/blockEntity.d.ts.map +1 -0
  5. package/dist/entities/blockEntity.js +78 -0
  6. package/dist/entities/extractorStatusEntity.d.ts +7 -0
  7. package/dist/entities/extractorStatusEntity.d.ts.map +1 -0
  8. package/dist/entities/extractorStatusEntity.js +37 -0
  9. package/dist/index.d.ts +11 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +10 -0
  12. package/dist/migrations/index.d.ts +7 -0
  13. package/dist/migrations/index.d.ts.map +1 -0
  14. package/dist/migrations/index.js +31 -0
  15. package/dist/migrations/postgres/1688545690867-migration.d.ts +7 -0
  16. package/dist/migrations/postgres/1688545690867-migration.d.ts.map +1 -0
  17. package/dist/migrations/postgres/1688545690867-migration.js +30 -0
  18. package/dist/migrations/postgres/1713803486477-migration.d.ts +7 -0
  19. package/dist/migrations/postgres/1713803486477-migration.d.ts.map +1 -0
  20. package/dist/migrations/postgres/1713803486477-migration.js +20 -0
  21. package/dist/migrations/postgres/1718789786123-migration.d.ts +7 -0
  22. package/dist/migrations/postgres/1718789786123-migration.d.ts.map +1 -0
  23. package/dist/migrations/postgres/1718789786123-migration.js +12 -0
  24. package/dist/migrations/postgres/1722697954558-migration.d.ts +7 -0
  25. package/dist/migrations/postgres/1722697954558-migration.d.ts.map +1 -0
  26. package/dist/migrations/postgres/1722697954558-migration.js +52 -0
  27. package/dist/migrations/postgres/1746701087567-migration.d.ts +7 -0
  28. package/dist/migrations/postgres/1746701087567-migration.d.ts.map +1 -0
  29. package/dist/migrations/postgres/1746701087567-migration.js +32 -0
  30. package/dist/migrations/postgres/1747657653564-migration.d.ts +7 -0
  31. package/dist/migrations/postgres/1747657653564-migration.d.ts.map +1 -0
  32. package/dist/migrations/postgres/1747657653564-migration.js +134 -0
  33. package/dist/migrations/sqlite/1688555497475-migration.d.ts +7 -0
  34. package/dist/migrations/sqlite/1688555497475-migration.d.ts.map +1 -0
  35. package/dist/migrations/sqlite/1688555497475-migration.js +29 -0
  36. package/dist/migrations/sqlite/1713786682123-migration.d.ts +7 -0
  37. package/dist/migrations/sqlite/1713786682123-migration.d.ts.map +1 -0
  38. package/dist/migrations/sqlite/1713786682123-migration.js +20 -0
  39. package/dist/migrations/sqlite/1718789744123-migration.d.ts +7 -0
  40. package/dist/migrations/sqlite/1718789744123-migration.d.ts.map +1 -0
  41. package/dist/migrations/sqlite/1718789744123-migration.js +12 -0
  42. package/dist/migrations/sqlite/1722697111974-migration.d.ts +7 -0
  43. package/dist/migrations/sqlite/1722697111974-migration.d.ts.map +1 -0
  44. package/dist/migrations/sqlite/1722697111974-migration.js +112 -0
  45. package/dist/migrations/sqlite/1746701087234-migration.d.ts +7 -0
  46. package/dist/migrations/sqlite/1746701087234-migration.d.ts.map +1 -0
  47. package/dist/migrations/sqlite/1746701087234-migration.js +32 -0
  48. package/dist/migrations/sqlite/1747655941239-migration.d.ts +7 -0
  49. package/dist/migrations/sqlite/1747655941239-migration.d.ts.map +1 -0
  50. package/dist/migrations/sqlite/1747655941239-migration.js +134 -0
  51. package/dist/scanner/abstract/generalScanner.d.ts +78 -0
  52. package/dist/scanner/abstract/generalScanner.d.ts.map +1 -0
  53. package/dist/scanner/abstract/generalScanner.js +210 -0
  54. package/dist/scanner/abstract/scanner.d.ts +49 -0
  55. package/dist/scanner/abstract/scanner.d.ts.map +1 -0
  56. package/dist/scanner/abstract/scanner.js +142 -0
  57. package/dist/scanner/abstract/webSocketScanner.d.ts +29 -0
  58. package/dist/scanner/abstract/webSocketScanner.d.ts.map +1 -0
  59. package/dist/scanner/abstract/webSocketScanner.js +90 -0
  60. package/dist/scanner/action.d.ts +83 -0
  61. package/dist/scanner/action.d.ts.map +1 -0
  62. package/dist/scanner/action.js +251 -0
  63. package/dist/scanner/interfaces.d.ts +13 -0
  64. package/dist/scanner/interfaces.d.ts.map +1 -0
  65. package/dist/scanner/interfaces.js +2 -0
  66. package/dist/scanner/network/connectorSelectionStrategies.d.ts +27 -0
  67. package/dist/scanner/network/connectorSelectionStrategies.d.ts.map +1 -0
  68. package/dist/scanner/network/connectorSelectionStrategies.js +22 -0
  69. package/dist/scanner/network/networkConnectorManager.d.ts +65 -0
  70. package/dist/scanner/network/networkConnectorManager.d.ts.map +1 -0
  71. package/dist/scanner/network/networkConnectorManager.js +126 -0
  72. package/dist/tsconfig.tsbuildinfo +1 -0
  73. package/package.json +46 -0
@@ -0,0 +1,251 @@
1
+ import { DummyLogger } from '@rosen-bridge/abstract-logger';
2
+ import { MoreThanOrEqual, In, } from '@rosen-bridge/extended-typeorm';
3
+ import { BlockEntity, PROCEED, PROCESSING } from '../entities/blockEntity';
4
+ import { ExtractorStatusEntity } from '../entities/extractorStatusEntity';
5
+ export class BlockDbAction {
6
+ blockRepository;
7
+ extractorStatusRepository;
8
+ dataSource;
9
+ scannerName;
10
+ logger;
11
+ constructor(dataSource, scannerName, logger) {
12
+ this.blockRepository = dataSource.getRepository(BlockEntity);
13
+ this.extractorStatusRepository = dataSource.getRepository(ExtractorStatusEntity);
14
+ this.dataSource = dataSource;
15
+ this.scannerName = scannerName;
16
+ this.logger = logger ? logger : new DummyLogger();
17
+ }
18
+ name = () => this.scannerName;
19
+ /**
20
+ * get last saved block
21
+ * @return Promise<BlockEntity or undefined>
22
+ */
23
+ getLastSavedBlock = async () => {
24
+ const lastBlock = await this.blockRepository.find({
25
+ where: { status: PROCEED, scanner: this.name() },
26
+ order: { height: 'DESC' },
27
+ take: 1,
28
+ });
29
+ if (lastBlock.length !== 0) {
30
+ return lastBlock[0];
31
+ }
32
+ else {
33
+ return undefined;
34
+ }
35
+ };
36
+ /**
37
+ * get last n stored blocks in database
38
+ * @param skip
39
+ * @param count
40
+ */
41
+ getLastSavedBlocks = async (skip, count) => {
42
+ return await this.blockRepository.find({
43
+ where: { status: PROCEED, scanner: this.name() },
44
+ order: { height: 'DESC' },
45
+ skip: skip,
46
+ take: count,
47
+ });
48
+ };
49
+ /**
50
+ * get first saved block
51
+ * @return Promise<BlockEntity or undefined>
52
+ */
53
+ getFirstSavedBlock = async () => {
54
+ const lastBlock = await this.blockRepository.find({
55
+ where: { status: PROCEED, scanner: this.name() },
56
+ order: { height: 'ASC' },
57
+ take: 1,
58
+ });
59
+ if (lastBlock.length !== 0) {
60
+ return lastBlock[0];
61
+ }
62
+ else {
63
+ return undefined;
64
+ }
65
+ };
66
+ /**
67
+ * get block hash and height
68
+ * @param height
69
+ * @param status
70
+ * @return Promise<BlockEntity|undefined>
71
+ */
72
+ getBlockAtHeight = async (height, status = PROCEED) => {
73
+ const block = await this.blockRepository.findOneBy({
74
+ status: status,
75
+ height: height,
76
+ scanner: this.name(),
77
+ });
78
+ if (block !== null) {
79
+ return block;
80
+ }
81
+ else {
82
+ return undefined;
83
+ }
84
+ };
85
+ /**
86
+ * get block with entered blockhash
87
+ * @param hash
88
+ * @param status
89
+ */
90
+ getBlockWithHash = async (hash, status = PROCEED) => {
91
+ return this.blockRepository.findOneBy({
92
+ hash: hash,
93
+ status: status,
94
+ scanner: this.name(),
95
+ });
96
+ };
97
+ /**
98
+ * it deletes every block that more than or equal height
99
+ * @param height
100
+ * @return Promise<DeleteResult>
101
+ */
102
+ removeBlocksFromHeight = async (height) => {
103
+ this.logger.debug(`Removing blocks from height ${height}`);
104
+ return await this.blockRepository.delete({
105
+ height: MoreThanOrEqual(height),
106
+ scanner: this.name(),
107
+ });
108
+ };
109
+ /**
110
+ * store a block into database.
111
+ * @param block
112
+ */
113
+ saveBlock = async (block) => {
114
+ try {
115
+ const instance = await this.blockRepository.findOneBy({
116
+ height: block.height,
117
+ scanner: this.name(),
118
+ });
119
+ const date = new Date(block.timestamp * 1000);
120
+ const blockInfo = {
121
+ height: block.height,
122
+ hash: block.hash,
123
+ parentHash: block.parentHash,
124
+ status: PROCESSING,
125
+ scanner: this.name(),
126
+ extra: block.extra,
127
+ timestamp: block.timestamp,
128
+ year: date.getFullYear(),
129
+ month: date.getMonth() + 1,
130
+ day: date.getDate(),
131
+ };
132
+ if (!instance) {
133
+ this.logger.debug(`Inserting block with info: ${JSON.stringify(blockInfo)}`);
134
+ await this.blockRepository.insert(blockInfo);
135
+ }
136
+ else {
137
+ this.logger.debug(`Updating block with info: ${JSON.stringify(blockInfo)}`);
138
+ await this.blockRepository.update({ height: block.height, scanner: this.name() }, blockInfo);
139
+ }
140
+ const res = await this.blockRepository.findOneBy({
141
+ height: block.height,
142
+ scanner: this.name(),
143
+ });
144
+ return res ? res : false;
145
+ }
146
+ catch (exp) {
147
+ this.logger.error(`An error occurred during save new block: ${exp}`);
148
+ return false;
149
+ }
150
+ };
151
+ /**
152
+ * Update status of a block to proceed
153
+ * @param height: height of expected block
154
+ */
155
+ updateBlockStatus = async (height, blockHash, extractorIds) => {
156
+ let success = true;
157
+ this.logger.debug(`Block at height ${height} has been proceed in scanner ${this.name()}, updating status`);
158
+ const runner = this.dataSource.createQueryRunner();
159
+ await runner.connect();
160
+ await runner.startTransaction();
161
+ try {
162
+ await runner.manager.getRepository(BlockEntity).update({
163
+ height: height,
164
+ status: PROCESSING,
165
+ scanner: this.name(),
166
+ }, {
167
+ status: PROCEED,
168
+ });
169
+ this.logger.debug('Updating extractors status', {
170
+ extractorIds,
171
+ });
172
+ await runner.manager
173
+ .getRepository(ExtractorStatusEntity)
174
+ .update({ extractorId: In(extractorIds), scannerId: this.name() }, { updateHeight: height, updateBlockHash: blockHash });
175
+ await runner.commitTransaction();
176
+ }
177
+ catch {
178
+ await runner.rollbackTransaction();
179
+ success = false;
180
+ }
181
+ finally {
182
+ await runner.release();
183
+ }
184
+ return success;
185
+ };
186
+ /**
187
+ * Update status of a block to processing in case of fork
188
+ * @param height: height of expected block
189
+ */
190
+ revertBlockStatus = async (height, parentHash, extractorIds) => {
191
+ let success = true;
192
+ const runner = this.dataSource.createQueryRunner();
193
+ await runner.connect();
194
+ await runner.startTransaction();
195
+ try {
196
+ this.logger.debug(`Reverting block status at height ${height}`);
197
+ await runner.manager.getRepository(BlockEntity).update({
198
+ height: height,
199
+ status: PROCEED,
200
+ scanner: this.name(),
201
+ }, {
202
+ status: PROCESSING,
203
+ });
204
+ this.logger.debug(`Reverting extractors update height to previous block at height ${height - 1}`);
205
+ await runner.manager
206
+ .getRepository(ExtractorStatusEntity)
207
+ .update({ extractorId: In(extractorIds), scannerId: this.name() }, { updateHeight: height - 1, updateBlockHash: parentHash });
208
+ await runner.commitTransaction();
209
+ }
210
+ catch (e) {
211
+ this.logger.warn(`An Error occurred while reverting block status: ${e}`);
212
+ await runner.rollbackTransaction();
213
+ success = false;
214
+ }
215
+ finally {
216
+ await runner.release();
217
+ }
218
+ return success;
219
+ };
220
+ /**
221
+ * Insert a newly initialized extractor or update an existing extractor status
222
+ * @param extractorId
223
+ * @param height
224
+ * @returns
225
+ */
226
+ updateOrInsertExtractorStatus = async (extractorId, height, blockHash) => {
227
+ this.logger.debug('Inserting new extractor status or Updating existing resynced extractor status', {
228
+ extractorId,
229
+ height,
230
+ blockHash,
231
+ });
232
+ return await this.extractorStatusRepository.save({
233
+ scannerId: this.name(),
234
+ extractorId,
235
+ updateHeight: height,
236
+ updateBlockHash: blockHash,
237
+ });
238
+ };
239
+ /**
240
+ * Return extractors` status specified by id
241
+ * @param extractorIds
242
+ * @returns extractors` status
243
+ */
244
+ getExtractorsStatus = async (extractorIds) => {
245
+ return await this.extractorStatusRepository.findBy({
246
+ scannerId: this.name(),
247
+ extractorId: In(extractorIds),
248
+ });
249
+ };
250
+ }
251
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vbGliL3NjYW5uZXIvYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBa0IsV0FBVyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDNUUsT0FBTyxFQUdMLGVBQWUsRUFFZixFQUFFLEdBQ0gsTUFBTSxnQ0FBZ0MsQ0FBQztBQUd4QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMzRSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUUxRSxNQUFNLE9BQU8sYUFBYTtJQUNmLGVBQWUsQ0FBMEI7SUFDekMseUJBQXlCLENBQW9DO0lBQzdELFVBQVUsQ0FBYTtJQUN2QixXQUFXLENBQVM7SUFDcEIsTUFBTSxDQUFpQjtJQUVoQyxZQUNFLFVBQXNCLEVBQ3RCLFdBQW1CLEVBQ25CLE1BQXVCO1FBRXZCLElBQUksQ0FBQyxlQUFlLEdBQUcsVUFBVSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM3RCxJQUFJLENBQUMseUJBQXlCLEdBQUcsVUFBVSxDQUFDLGFBQWEsQ0FDdkQscUJBQXFCLENBQ3RCLENBQUM7UUFDRixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUMvQixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLFdBQVcsRUFBRSxDQUFDO0lBQ3BELENBQUM7SUFFUSxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztJQUV2Qzs7O09BR0c7SUFDSCxpQkFBaUIsR0FBRyxLQUFLLElBQXNDLEVBQUU7UUFDL0QsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFD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LE9BQU8sQ0FBQztJQUNqQixDQUFDLENBQUM7SUFFRjs7Ozs7T0FLRztJQUNILDZCQUE2QixHQUFHLEtBQUssRUFDbkMsV0FBbUIsRUFDbkIsTUFBYyxFQUNkLFNBQWlCLEVBQ2pCLEVBQUU7UUFDRixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDZiwrRUFBK0UsRUFDL0U7WUFDRSxXQUFXO1lBQ1gsTUFBTTtZQUNOLFNBQVM7U0FDVixDQUNGLENBQUM7UUFDRixPQUFPLE1BQU0sSUFBSSxDQUFDLHlCQUF5QixDQUFDLElBQUksQ0FBQztZQUMvQyxTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRTtZQUN0QixXQUFXO1lBQ1gsWUFBWSxFQUFFLE1BQU07WUFDcEIsZUFBZSxFQUFFLFNBQVM7U0FDM0IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDO0lBRUY7Ozs7T0FJRztJQUNILG1CQUFtQixHQUFHLEtBQUssRUFDekIsWUFBc0IsRUFDWSxFQUFFO1FBQ3BDLE9BQU8sTUFBTSxJQUFJLENBQUMseUJBQXlCLENBQUMsTUFBTSxDQUFDO1lBQ2pELFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ3RCLFdBQVcsRUFBRSxFQUFFLENBQUMsWUFBWSxDQUFDO1NBQzlCLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQztDQUNIIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWJzdHJhY3RMb2dnZXIsIER1bW15TG9nZ2VyIH0gZnJvbSAnQHJvc2VuLWJyaWRnZS9hYnN0cmFjdC1sb2dnZXInO1xuaW1wb3J0IHtcbiAgRGF0YVNvdXJjZSxcbiAgRGVsZXRlUmVzdWx0LFxuICBNb3JlVGhhbk9yRXF1YWwsXG4gIFJlcG9zaXRvcnksXG4gIEluLFxufSBmcm9tICdAcm9zZW4tYnJpZGdlL2V4dGVuZGVkLXR5cGVvcm0nO1xuaW1wb3J0IHsgQmxvY2sgfSBmcm9tICdAcm9zZW4tYnJpZGdlL3NjYW5uZXItaW50ZXJmYWNlcyc7XG5cbmltcG9ydCB7IEJsb2NrRW50aXR5LCBQUk9DRUVELCBQUk9DRVNTSU5HIH0gZnJvbSAnLi4vZW50aXRpZXMvYmxvY2tFbnRpdHknO1xuaW1wb3J0IHsgRXh0cmFjdG9yU3RhdHVzRW50aXR5IH0gZnJvbSAnLi4vZW50aXRpZXMvZXh0cmFjdG9yU3RhdHVzRW50aXR5JztcblxuZXhwb3J0IGNsYXNzIEJsb2NrRGJBY3Rpb24ge1xuICByZWFkb25seSBibG9ja1JlcG9zaXRvcnk6IFJlcG9zaXRvcnk8QmxvY2tFbnRpdHk+O1xuICByZWFkb25seSBleHRyYWN0b3JTdGF0dXNSZXBvc2l0b3J5OiBSZXBvc2l0b3J5PEV4dHJhY3RvclN0YXR1c0VudGl0eT47XG4gIHJlYWRvbmx5IGRhdGFTb3VyY2U6IERhdGFTb3VyY2U7XG4gIHJlYWRvbmx5IHNjYW5uZXJOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGxvZ2dlcjogQWJzdHJhY3RMb2dnZXI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgZGF0YVNvdXJjZTogRGF0YVNvdXJjZSxcbiAgICBzY2FubmVyTmFtZTogc3RyaW5nLFxuICAgIGxvZ2dlcj86IEFic3RyYWN0TG9nZ2VyLFxuICApIHtcbiAgICB0aGlzLmJsb2NrUmVwb3NpdG9yeSA9IGRhdGFTb3VyY2UuZ2V0UmVwb3NpdG9yeShCbG9ja0VudGl0eSk7XG4gICAgdGhpcy5leHRyYWN0b3JTdGF0dXNSZXBvc2l0b3J5ID0gZGF0YVNvdXJjZS5nZXRSZXBvc2l0b3J5KFxuICAgICAgRXh0cmFjdG9yU3RhdHVzRW50aXR5LFxuICAgICk7XG4gICAgdGhpcy5kYXRhU291cmNlID0gZGF0YVNvdXJjZTtcbiAgICB0aGlzLnNjYW5uZXJOYW1lID0gc2Nhbm5lck5hbWU7XG4gICAgdGhpcy5sb2dnZXIgPSBsb2dnZXIgPyBsb2dnZXIgOiBuZXcgRHVtbXlMb2dnZXIoKTtcbiAgfVxuXG4gIHJlYWRvbmx5IG5hbWUgPSAoKSA9PiB0aGlzLnNjYW5uZXJOYW1lO1xuXG4gIC8qKlxuICAgKiBnZXQgbGFzdCBzYXZlZCBibG9ja1xuICAgKiBAcmV0dXJuIFByb21pc2U8QmxvY2tFbnRpdHkgb3IgdW5kZWZpbmVkPlxuICAgKi9cbiAgZ2V0TGFzdFNhdmVkQmxvY2sgPSBhc3luYyAoKTogUHJvbWlzZTxCbG9ja0VudGl0eSB8IHVuZGVmaW5lZD4gPT4ge1xuICAgIGNvbnN0IGxhc3RCbG9jayA9IGF3YWl0IHRoaXMuYmxvY2tSZXBvc2l0b3J5LmZpbmQoe1xuICAgICAgd2hlcmU6IHsgc3RhdHVzOiBQUk9DRUVELCBzY2FubmVyOiB0aGlzLm5hbWUoKSB9LFxuICAgICAgb3JkZXI6IHsgaGVpZ2h0OiAnREVTQycgfSxcbiAgICAgIHRha2U6IDEsXG4gICAgfSk7XG4gICAgaWYgKGxhc3RCbG9jay5sZW5ndGggIT09IDApIHtcbiAgICAgIHJldHVybiBsYXN0QmxvY2tbMF07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBnZXQgbGFzdCBuIHN0b3JlZCBibG9ja3MgaW4gZGF0YWJhc2VcbiAgICogQHBhcmFtIHNraXBcbiAgICogQHBhcmFtIGNvdW50XG4gICAqL1xuICBnZXRMYXN0U2F2ZWRCbG9ja3MgPSBhc3luYyAoXG4gICAgc2tpcDogbnVtYmVyLFxuICAgIGNvdW50OiBudW1iZXIsXG4gICk6IFByb21pc2U8QXJyYXk8QmxvY2tFbnRpdHk+PiA9PiB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuYmxvY2tSZXBvc2l0b3J5LmZpbmQoe1xuICAgICAgd2hlcmU6IHsgc3RhdHVzOiBQUk9DRUVELCBzY2FubmVyOiB0aGlzLm5hbWUoKSB9LFxuICAgICAgb3JkZXI6IHsgaGVpZ2h0OiAnREVTQycgfSxcbiAgICAgIHNraXA6IHNraXAsXG4gICAgICB0YWtlOiBjb3VudCxcbiAgICB9KTtcbiAgfTtcblxuICAvKipcbiAgICogZ2V0IGZpcnN0IHNhdmVkIGJsb2NrXG4gICAqIEByZXR1cm4gUHJvbWlzZTxCbG9ja0VudGl0eSBvciB1bmRlZmluZWQ+XG4gICAqL1xuICBnZXRGaXJzdFNhdmVkQmxvY2sgPSBhc3luYyAoKTogUHJvbWlzZTxCbG9ja0VudGl0eSB8IHVuZGVmaW5lZD4gPT4ge1xuICAgIGNvbnN0IGxhc3RCbG9jayA9IGF3YWl0IHRoaXMuYmxvY2tSZXBvc2l0b3J5LmZpbmQoe1xuICAgICAgd2hlcmU6IHsgc3RhdHVzOiBQUk9DRUVELCBzY2FubmVyOiB0aGlzLm5hbWUoKSB9LFxuICAgICAgb3JkZXI6IHsgaGVpZ2h0OiAnQVNDJyB9LFxuICAgICAgdGFrZTogMSxcbiAgICB9KTtcbiAgICBpZiAobGFzdEJsb2NrLmxlbmd0aCAhPT0gMCkge1xuICAgICAgcmV0dXJuIGxhc3RCbG9ja1swXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIGdldCBibG9jayBoYXNoIGFuZCBoZWlnaHRcbiAgICogQHBhcmFtIGhlaWdodFxuICAgKiBAcGFyYW0gc3RhdHVzXG4gICAqIEByZXR1cm4gUHJvbWlzZTxCbG9ja0VudGl0eXx1bmRlZmluZWQ+XG4gICAqL1xuICBnZXRCbG9ja0F0SGVpZ2h0ID0gYXN5bmMgKFxuICAgIGhlaWdodDogbnVtYmVyLFxuICAgIHN0YXR1czogc3RyaW5nID0gUFJPQ0VFRCxcbiAgKTogUHJvbWlzZTxCbG9ja0VudGl0eSB8IHVuZGVmaW5lZD4gPT4ge1xuICAgIGNvbnN0IGJsb2NrID0gYXdhaXQgdGhpcy5ibG9ja1JlcG9zaXRvcnkuZmluZE9uZUJ5KHtcbiAgICAgIHN0YXR1czogc3RhdHVzLFxuICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICBzY2FubmVyOiB0aGlzLm5hbWUoKSxcbiAgICB9KTtcbiAgICBpZiAoYmxvY2sgIT09IG51bGwpIHtcbiAgICAgIHJldHVybiBibG9jaztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIGdldCBibG9jayB3aXRoIGVudGVyZWQgYmxvY2toYXNoXG4gICAqIEBwYXJhbSBoYXNoXG4gICAqIEBwYXJhbSBzdGF0dXNcbiAgICovXG4gIGdldEJsb2NrV2l0aEhhc2ggPSBhc3luYyAoaGFzaDogc3RyaW5nLCBzdGF0dXM6IHN0cmluZyA9IFBST0NFRUQpID0+IHtcbiAgICByZXR1cm4gdGhpcy5ibG9ja1JlcG9zaXRvcnkuZmluZE9uZUJ5KHtcbiAgICAgIGhhc2g6IGhhc2gsXG4gICAgICBzdGF0dXM6IHN0YXR1cyxcbiAgICAgIHNjYW5uZXI6IHRoaXMubmFtZSgpLFxuICAgIH0pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBpdCBkZWxldGVzIGV2ZXJ5IGJsb2NrIHRoYXQgbW9yZSB0aGFuIG9yIGVxdWFsIGhlaWdodFxuICAgKiBAcGFyYW0gaGVpZ2h0XG4gICAqIEByZXR1cm4gUHJvbWlzZTxEZWxldGVSZXN1bHQ+XG4gICAqL1xuICByZW1vdmVCbG9ja3NGcm9tSGVpZ2h0ID0gYXN5bmMgKGhlaWdodDogbnVtYmVyKTogUHJvbWlzZTxEZWxldGVSZXN1bHQ+ID0+IHtcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgUmVtb3ZpbmcgYmxvY2tzIGZyb20gaGVpZ2h0ICR7aGVpZ2h0fWApO1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmJsb2NrUmVwb3NpdG9yeS5kZWxldGUoe1xuICAgICAgaGVpZ2h0OiBNb3JlVGhhbk9yRXF1YWwoaGVpZ2h0KSxcbiAgICAgIHNjYW5uZXI6IHRoaXMubmFtZSgpLFxuICAgIH0pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBzdG9yZSBhIGJsb2NrIGludG8gZGF0YWJhc2UuXG4gICAqIEBwYXJhbSBibG9ja1xuICAgKi9cbiAgc2F2ZUJsb2NrID0gYXN5bmMgKGJsb2NrOiBCbG9jayk6IFByb21pc2U8QmxvY2tFbnRpdHkgfCBib29sZWFuPiA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgdGhpcy5ibG9ja1JlcG9zaXRvcnkuZmluZE9uZUJ5KHtcbiAgICAgICAgaGVpZ2h0OiBibG9jay5oZWlnaHQsXG4gICAgICAgIHNjYW5uZXI6IHRoaXMubmFtZSgpLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoYmxvY2sudGltZXN0YW1wICogMTAwMCk7XG4gICAgICBjb25zdCBibG9ja0luZm8gPSB7XG4gICAgICAgIGhlaWdodDogYmxvY2suaGVpZ2h0LFxuICAgICAgICBoYXNoOiBibG9jay5oYXNoLFxuICAgICAgICBwYXJlbnRIYXNoOiBibG9jay5wYXJlbnRIYXNoLFxuICAgICAgICBzdGF0dXM6IFBST0NFU1NJTkcsXG4gICAgICAgIHNjYW5uZXI6IHRoaXMubmFtZSgpLFxuICAgICAgICBleHRyYTogYmxvY2suZXh0cmEsXG4gICAgICAgIHRpbWVzdGFtcDogYmxvY2sudGltZXN0YW1wLFxuICAgICAgICB5ZWFyOiBkYXRlLmdldEZ1bGxZZWFyKCksXG4gICAgICAgIG1vbnRoOiBkYXRlLmdldE1vbnRoKCkgKyAxLFxuICAgICAgICBkYXk6IGRhdGUuZ2V0RGF0ZSgpLFxuICAgICAgfTtcbiAgICAgIGlmICghaW5zdGFuY2UpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICAgICAgYEluc2VydGluZyBibG9jayB3aXRoIGluZm86ICR7SlNPTi5zdHJpbmdpZnkoYmxvY2tJbmZvKX1gLFxuICAgICAgICApO1xuICAgICAgICBhd2FpdCB0aGlzLmJsb2NrUmVwb3NpdG9yeS5pbnNlcnQoYmxvY2tJbmZvKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgICAgIGBVcGRhdGluZyBibG9jayB3aXRoIGluZm86ICR7SlNPTi5zdHJpbmdpZnkoYmxvY2tJbmZvKX1gLFxuICAgICAgICApO1xuICAgICAgICBhd2FpdCB0aGlzLmJsb2NrUmVwb3NpdG9yeS51cGRhdGUoXG4gICAgICAgICAgeyBoZWlnaHQ6IGJsb2NrLmhlaWdodCwgc2Nhbm5lcjogdGhpcy5uYW1lKCkgfSxcbiAgICAgICAgICBibG9ja0luZm8sXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLmJsb2NrUmVwb3NpdG9yeS5maW5kT25lQnkoe1xuICAgICAgICBoZWlnaHQ6IGJsb2NrLmhlaWdodCxcbiAgICAgICAgc2Nhbm5lcjogdGhpcy5uYW1lKCksXG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXMgPyByZXMgOiBmYWxzZTtcbiAgICB9IGNhdGNoIChleHApIHtcbiAgICAgIHRoaXMubG9nZ2VyLmVycm9yKGBBbiBlcnJvciBvY2N1cnJlZCBkdXJpbmcgc2F2ZSBuZXcgYmxvY2s6ICR7ZXhwfWApO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogVXBkYXRlIHN0YXR1cyBvZiBhIGJsb2NrIHRvIHByb2NlZWRcbiAgICogQHBhcmFtIGhlaWdodDogaGVpZ2h0IG9mIGV4cGVjdGVkIGJsb2NrXG4gICAqL1xuICB1cGRhdGVCbG9ja1N0YXR1cyA9IGFzeW5jIChcbiAgICBoZWlnaHQ6IG51bWJlcixcbiAgICBibG9ja0hhc2g6IHN0cmluZyxcbiAgICBleHRyYWN0b3JJZHM6IHN0cmluZ1tdLFxuICApOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgICBsZXQgc3VjY2VzcyA9IHRydWU7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICBgQmxvY2sgYXQgaGVpZ2h0ICR7aGVpZ2h0fSBoYXMgYmVlbiBwcm9jZWVkIGluIHNjYW5uZXIgJHt0aGlzLm5hbWUoKX0sIHVwZGF0aW5nIHN0YXR1c2AsXG4gICAgKTtcbiAgICBjb25zdCBydW5uZXIgPSB0aGlzLmRhdGFTb3VyY2UuY3JlYXRlUXVlcnlSdW5uZXIoKTtcbiAgICBhd2FpdCBydW5uZXIuY29ubmVjdCgpO1xuICAgIGF3YWl0IHJ1bm5lci5zdGFydFRyYW5zYWN0aW9uKCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHJ1bm5lci5tYW5hZ2VyLmdldFJlcG9zaXRvcnkoQmxvY2tFbnRpdHkpLnVwZGF0ZShcbiAgICAgICAge1xuICAgICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgICAgIHN0YXR1czogUFJPQ0VTU0lORyxcbiAgICAgICAgICBzY2FubmVyOiB0aGlzLm5hbWUoKSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHN0YXR1czogUFJPQ0VFRCxcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKCdVcGRhdGluZyBleHRyYWN0b3JzIHN0YXR1cycsIHtcbiAgICAgICAgZXh0cmFjdG9ySWRzLFxuICAgICAgfSk7XG4gICAgICBhd2FpdCBydW5uZXIubWFuYWdlclxuICAgICAgICAuZ2V0UmVwb3NpdG9yeShFeHRyYWN0b3JTdGF0dXNFbnRpdHkpXG4gICAgICAgIC51cGRhdGUoXG4gICAgICAgICAgeyBleHRyYWN0b3JJZDogSW4oZXh0cmFjdG9ySWRzKSwgc2Nhbm5lcklkOiB0aGlzLm5hbWUoKSB9LFxuICAgICAgICAgIHsgdXBkYXRlSGVpZ2h0OiBoZWlnaHQsIHVwZGF0ZUJsb2NrSGFzaDogYmxvY2tIYXNoIH0sXG4gICAgICAgICk7XG4gICAgICBhd2FpdCBydW5uZXIuY29tbWl0VHJhbnNhY3Rpb24oKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGF3YWl0IHJ1bm5lci5yb2xsYmFja1RyYW5zYWN0aW9uKCk7XG4gICAgICBzdWNjZXNzID0gZmFsc2U7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGF3YWl0IHJ1bm5lci5yZWxlYXNlKCk7XG4gICAgfVxuICAgIHJldHVybiBzdWNjZXNzO1xuICB9O1xuXG4gIC8qKlxuICAgKiBVcGRhdGUgc3RhdHVzIG9mIGEgYmxvY2sgdG8gcHJvY2Vzc2luZyBpbiBjYXNlIG9mIGZvcmtcbiAgICogQHBhcmFtIGhlaWdodDogaGVpZ2h0IG9mIGV4cGVjdGVkIGJsb2NrXG4gICAqL1xuICByZXZlcnRCbG9ja1N0YXR1cyA9IGFzeW5jIChcbiAgICBoZWlnaHQ6IG51bWJlcixcbiAgICBwYXJlbnRIYXNoOiBzdHJpbmcsXG4gICAgZXh0cmFjdG9ySWRzOiBzdHJpbmdbXSxcbiAgKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gICAgbGV0IHN1Y2Nlc3MgPSB0cnVlO1xuICAgIGNvbnN0IHJ1bm5lciA9IHRoaXMuZGF0YVNvdXJjZS5jcmVhdGVRdWVyeVJ1bm5lcigpO1xuICAgIGF3YWl0IHJ1bm5lci5jb25uZWN0KCk7XG4gICAgYXdhaXQgcnVubmVyLnN0YXJ0VHJhbnNhY3Rpb24oKTtcbiAgICB0cnkge1xuICAgICAgdGhpcy5sb2dnZXIuZGVidWcoYFJldmVydGluZyBibG9jayBzdGF0dXMgYXQgaGVpZ2h0ICR7aGVpZ2h0fWApO1xuICAgICAgYXdhaXQgcnVubmVyLm1hbmFnZXIuZ2V0UmVwb3NpdG9yeShCbG9ja0VudGl0eSkudXBkYXRlKFxuICAgICAgICB7XG4gICAgICAgICAgaGVpZ2h0OiBoZWlnaHQsXG4gICAgICAgICAgc3RhdHVzOiBQUk9DRUVELFxuICAgICAgICAgIHNjYW5uZXI6IHRoaXMubmFtZSgpLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgc3RhdHVzOiBQUk9DRVNTSU5HLFxuICAgICAgICB9LFxuICAgICAgKTtcblxuICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXG4gICAgICAgIGBSZXZlcnRpbmcgZXh0cmFjdG9ycyB1cGRhdGUgaGVpZ2h0IHRvIHByZXZpb3VzIGJsb2NrIGF0IGhlaWdodCAke1xuICAgICAgICAgIGhlaWdodCAtIDFcbiAgICAgICAgfWAsXG4gICAgICApO1xuICAgICAgYXdhaXQgcnVubmVyLm1hbmFnZXJcbiAgICAgICAgLmdldFJlcG9zaXRvcnkoRXh0cmFjdG9yU3RhdHVzRW50aXR5KVxuICAgICAgICAudXBkYXRlKFxuICAgICAgICAgIHsgZXh0cmFjdG9ySWQ6IEluKGV4dHJhY3RvcklkcyksIHNjYW5uZXJJZDogdGhpcy5uYW1lKCkgfSxcbiAgICAgICAgICB7IHVwZGF0ZUhlaWdodDogaGVpZ2h0IC0gMSwgdXBkYXRlQmxvY2tIYXNoOiBwYXJlbnRIYXNoIH0sXG4gICAgICAgICk7XG4gICAgICBhd2FpdCBydW5uZXIuY29tbWl0VHJhbnNhY3Rpb24oKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLmxvZ2dlci53YXJuKGBBbiBFcnJvciBvY2N1cnJlZCB3aGlsZSByZXZlcnRpbmcgYmxvY2sgc3RhdHVzOiAke2V9YCk7XG4gICAgICBhd2FpdCBydW5uZXIucm9sbGJhY2tUcmFuc2FjdGlvbigpO1xuICAgICAgc3VjY2VzcyA9IGZhbHNlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBydW5uZXIucmVsZWFzZSgpO1xuICAgIH1cbiAgICByZXR1cm4gc3VjY2VzcztcbiAgfTtcblxuICAvKipcbiAgICogSW5zZXJ0IGEgbmV3bHkgaW5pdGlhbGl6ZWQgZXh0cmFjdG9yIG9yIHVwZGF0ZSBhbiBleGlzdGluZyBleHRyYWN0b3Igc3RhdHVzXG4gICAqIEBwYXJhbSBleHRyYWN0b3JJZFxuICAgKiBAcGFyYW0gaGVpZ2h0XG4gICAqIEByZXR1cm5zXG4gICAqL1xuICB1cGRhdGVPckluc2VydEV4dHJhY3RvclN0YXR1cyA9IGFzeW5jIChcbiAgICBleHRyYWN0b3JJZDogc3RyaW5nLFxuICAgIGhlaWdodDogbnVtYmVyLFxuICAgIGJsb2NrSGFzaDogc3RyaW5nLFxuICApID0+IHtcbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhcbiAgICAgICdJbnNlcnRpbmcgbmV3IGV4dHJhY3RvciBzdGF0dXMgb3IgVXBkYXRpbmcgZXhpc3RpbmcgcmVzeW5jZWQgZXh0cmFjdG9yIHN0YXR1cycsXG4gICAgICB7XG4gICAgICAgIGV4dHJhY3RvcklkLFxuICAgICAgICBoZWlnaHQsXG4gICAgICAgIGJsb2NrSGFzaCxcbiAgICAgIH0sXG4gICAgKTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5leHRyYWN0b3JTdGF0dXNSZXBvc2l0b3J5LnNhdmUoe1xuICAgICAgc2Nhbm5lcklkOiB0aGlzLm5hbWUoKSxcbiAgICAgIGV4dHJhY3RvcklkLFxuICAgICAgdXBkYXRlSGVpZ2h0OiBoZWlnaHQsXG4gICAgICB1cGRhdGVCbG9ja0hhc2g6IGJsb2NrSGFzaCxcbiAgICB9KTtcbiAgfTtcblxuICAvKipcbiAgICogUmV0dXJuIGV4dHJhY3RvcnNgIHN0YXR1cyBzcGVjaWZpZWQgYnkgaWRcbiAgICogQHBhcmFtIGV4dHJhY3Rvcklkc1xuICAgKiBAcmV0dXJucyBleHRyYWN0b3JzYCBzdGF0dXNcbiAgICovXG4gIGdldEV4dHJhY3RvcnNTdGF0dXMgPSBhc3luYyAoXG4gICAgZXh0cmFjdG9ySWRzOiBzdHJpbmdbXSxcbiAgKTogUHJvbWlzZTxFeHRyYWN0b3JTdGF0dXNFbnRpdHlbXT4gPT4ge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmV4dHJhY3RvclN0YXR1c1JlcG9zaXRvcnkuZmluZEJ5KHtcbiAgICAgIHNjYW5uZXJJZDogdGhpcy5uYW1lKCksXG4gICAgICBleHRyYWN0b3JJZDogSW4oZXh0cmFjdG9ySWRzKSxcbiAgICB9KTtcbiAgfTtcbn1cbiJdfQ==
@@ -0,0 +1,13 @@
1
+ import { AbstractLogger } from '@rosen-bridge/abstract-logger';
2
+ import { DataSource } from '@rosen-bridge/extended-typeorm';
3
+ import { AbstractNetworkConnector } from '@rosen-bridge/scanner-interfaces';
4
+ export interface ScannerConfig<TransactionType> {
5
+ dataSource: DataSource;
6
+ initialHeight: number;
7
+ network: AbstractNetworkConnector<TransactionType>;
8
+ blockRetrieveGap?: number;
9
+ suffix?: string;
10
+ heightGap?: number;
11
+ logger?: AbstractLogger;
12
+ }
13
+ //# sourceMappingURL=interfaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../lib/scanner/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,MAAM,WAAW,aAAa,CAAC,eAAe;IAC5C,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,wBAAwB,CAAC,eAAe,CAAC,CAAC;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9zY2FubmVyL2ludGVyZmFjZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFic3RyYWN0TG9nZ2VyIH0gZnJvbSAnQHJvc2VuLWJyaWRnZS9hYnN0cmFjdC1sb2dnZXInO1xuaW1wb3J0IHsgRGF0YVNvdXJjZSB9IGZyb20gJ0Byb3Nlbi1icmlkZ2UvZXh0ZW5kZWQtdHlwZW9ybSc7XG5pbXBvcnQgeyBBYnN0cmFjdE5ldHdvcmtDb25uZWN0b3IgfSBmcm9tICdAcm9zZW4tYnJpZGdlL3NjYW5uZXItaW50ZXJmYWNlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2Nhbm5lckNvbmZpZzxUcmFuc2FjdGlvblR5cGU+IHtcbiAgZGF0YVNvdXJjZTogRGF0YVNvdXJjZTtcbiAgaW5pdGlhbEhlaWdodDogbnVtYmVyO1xuICBuZXR3b3JrOiBBYnN0cmFjdE5ldHdvcmtDb25uZWN0b3I8VHJhbnNhY3Rpb25UeXBlPjtcbiAgYmxvY2tSZXRyaWV2ZUdhcD86IG51bWJlcjtcbiAgc3VmZml4Pzogc3RyaW5nO1xuICBoZWlnaHRHYXA/OiBudW1iZXI7XG4gIGxvZ2dlcj86IEFic3RyYWN0TG9nZ2VyO1xufVxuIl19
@@ -0,0 +1,27 @@
1
+ import { AbstractNetworkConnector } from '@rosen-bridge/scanner-interfaces';
2
+ /**
3
+ * Interface for connector selection strategies
4
+ */
5
+ export interface ConnectorSelectionStrategy<TransactionType> {
6
+ /**
7
+ * Select the next connector to use
8
+ * @param connectors Array of available connectors
9
+ * @param currentIndex Current connector index
10
+ * @param lastError Error from the last operation, if any
11
+ * @returns The index of the next connector to use
12
+ */
13
+ selectNextConnector(connectors: Array<AbstractNetworkConnector<TransactionType>>, currentIndex: number, lastError?: Error): number;
14
+ }
15
+ /**
16
+ * Failover strategy - switches to next connector only on failure
17
+ */
18
+ export declare class FailoverStrategy<TransactionType> implements ConnectorSelectionStrategy<TransactionType> {
19
+ selectNextConnector(connectors: Array<AbstractNetworkConnector<TransactionType>>, currentIndex: number, lastError?: Error): number;
20
+ }
21
+ /**
22
+ * Round-robin strategy - switches to next connector after each operation
23
+ */
24
+ export declare class RoundRobinStrategy<TransactionType> implements ConnectorSelectionStrategy<TransactionType> {
25
+ selectNextConnector(connectors: Array<AbstractNetworkConnector<TransactionType>>, currentIndex: number): number;
26
+ }
27
+ //# sourceMappingURL=connectorSelectionStrategies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connectorSelectionStrategies.d.ts","sourceRoot":"","sources":["../../../lib/scanner/network/connectorSelectionStrategies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E;;GAEG;AACH,MAAM,WAAW,0BAA0B,CAAC,eAAe;IACzD;;;;;;OAMG;IACH,mBAAmB,CACjB,UAAU,EAAE,KAAK,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC,EAC5D,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,KAAK,GAChB,MAAM,CAAC;CACX;AAED;;GAEG;AACH,qBAAa,gBAAgB,CAAC,eAAe,CAC3C,YAAW,0BAA0B,CAAC,eAAe,CAAC;IAEtD,mBAAmB,CACjB,UAAU,EAAE,KAAK,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC,EAC5D,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,KAAK,GAChB,MAAM;CAQV;AAED;;GAEG;AACH,qBAAa,kBAAkB,CAAC,eAAe,CAC7C,YAAW,0BAA0B,CAAC,eAAe,CAAC;IAEtD,mBAAmB,CACjB,UAAU,EAAE,KAAK,CAAC,wBAAwB,CAAC,eAAe,CAAC,CAAC,EAC5D,YAAY,EAAE,MAAM,GACnB,MAAM;CAGV"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Failover strategy - switches to next connector only on failure
3
+ */
4
+ export class FailoverStrategy {
5
+ selectNextConnector(connectors, currentIndex, lastError) {
6
+ // If there was an error, try the next connector
7
+ if (lastError) {
8
+ return (currentIndex + 1) % connectors.length;
9
+ }
10
+ // Otherwise stay with current connector
11
+ return currentIndex;
12
+ }
13
+ }
14
+ /**
15
+ * Round-robin strategy - switches to next connector after each operation
16
+ */
17
+ export class RoundRobinStrategy {
18
+ selectNextConnector(connectors, currentIndex) {
19
+ return (currentIndex + 1) % connectors.length;
20
+ }
21
+ }
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdG9yU2VsZWN0aW9uU3RyYXRlZ2llcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9zY2FubmVyL25ldHdvcmsvY29ubmVjdG9yU2VsZWN0aW9uU3RyYXRlZ2llcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFvQkE7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBRzNCLG1CQUFtQixDQUNqQixVQUE0RCxFQUM1RCxZQUFvQixFQUNwQixTQUFpQjtRQUVqQixnREFBZ0Q7UUFDaEQsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNkLE9BQU8sQ0FBQyxZQUFZLEdBQUcsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQztRQUNoRCxDQUFDO1FBQ0Qsd0NBQXdDO1FBQ3hDLE9BQU8sWUFBWSxDQUFDO0lBQ3RCLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGtCQUFrQjtJQUc3QixtQkFBbUIsQ0FDakIsVUFBNEQsRUFDNUQsWUFBb0I7UUFFcEIsT0FBTyxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDO0lBQ2hELENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFic3RyYWN0TmV0d29ya0Nvbm5lY3RvciB9IGZyb20gJ0Byb3Nlbi1icmlkZ2Uvc2Nhbm5lci1pbnRlcmZhY2VzJztcblxuLyoqXG4gKiBJbnRlcmZhY2UgZm9yIGNvbm5lY3RvciBzZWxlY3Rpb24gc3RyYXRlZ2llc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbm5lY3RvclNlbGVjdGlvblN0cmF0ZWd5PFRyYW5zYWN0aW9uVHlwZT4ge1xuICAvKipcbiAgICogU2VsZWN0IHRoZSBuZXh0IGNvbm5lY3RvciB0byB1c2VcbiAgICogQHBhcmFtIGNvbm5lY3RvcnMgQXJyYXkgb2YgYXZhaWxhYmxlIGNvbm5lY3RvcnNcbiAgICogQHBhcmFtIGN1cnJlbnRJbmRleCBDdXJyZW50IGNvbm5lY3RvciBpbmRleFxuICAgKiBAcGFyYW0gbGFzdEVycm9yIEVycm9yIGZyb20gdGhlIGxhc3Qgb3BlcmF0aW9uLCBpZiBhbnlcbiAgICogQHJldHVybnMgVGhlIGluZGV4IG9mIHRoZSBuZXh0IGNvbm5lY3RvciB0byB1c2VcbiAgICovXG4gIHNlbGVjdE5leHRDb25uZWN0b3IoXG4gICAgY29ubmVjdG9yczogQXJyYXk8QWJzdHJhY3ROZXR3b3JrQ29ubmVjdG9yPFRyYW5zYWN0aW9uVHlwZT4+LFxuICAgIGN1cnJlbnRJbmRleDogbnVtYmVyLFxuICAgIGxhc3RFcnJvcj86IEVycm9yLFxuICApOiBudW1iZXI7XG59XG5cbi8qKlxuICogRmFpbG92ZXIgc3RyYXRlZ3kgLSBzd2l0Y2hlcyB0byBuZXh0IGNvbm5lY3RvciBvbmx5IG9uIGZhaWx1cmVcbiAqL1xuZXhwb3J0IGNsYXNzIEZhaWxvdmVyU3RyYXRlZ3k8VHJhbnNhY3Rpb25UeXBlPlxuICBpbXBsZW1lbnRzIENvbm5lY3RvclNlbGVjdGlvblN0cmF0ZWd5PFRyYW5zYWN0aW9uVHlwZT5cbntcbiAgc2VsZWN0TmV4dENvbm5lY3RvcihcbiAgICBjb25uZWN0b3JzOiBBcnJheTxBYnN0cmFjdE5ldHdvcmtDb25uZWN0b3I8VHJhbnNhY3Rpb25UeXBlPj4sXG4gICAgY3VycmVudEluZGV4OiBudW1iZXIsXG4gICAgbGFzdEVycm9yPzogRXJyb3IsXG4gICk6IG51bWJlciB7XG4gICAgLy8gSWYgdGhlcmUgd2FzIGFuIGVycm9yLCB0cnkgdGhlIG5leHQgY29ubmVjdG9yXG4gICAgaWYgKGxhc3RFcnJvcikge1xuICAgICAgcmV0dXJuIChjdXJyZW50SW5kZXggKyAxKSAlIGNvbm5lY3RvcnMubGVuZ3RoO1xuICAgIH1cbiAgICAvLyBPdGhlcndpc2Ugc3RheSB3aXRoIGN1cnJlbnQgY29ubmVjdG9yXG4gICAgcmV0dXJuIGN1cnJlbnRJbmRleDtcbiAgfVxufVxuXG4vKipcbiAqIFJvdW5kLXJvYmluIHN0cmF0ZWd5IC0gc3dpdGNoZXMgdG8gbmV4dCBjb25uZWN0b3IgYWZ0ZXIgZWFjaCBvcGVyYXRpb25cbiAqL1xuZXhwb3J0IGNsYXNzIFJvdW5kUm9iaW5TdHJhdGVneTxUcmFuc2FjdGlvblR5cGU+XG4gIGltcGxlbWVudHMgQ29ubmVjdG9yU2VsZWN0aW9uU3RyYXRlZ3k8VHJhbnNhY3Rpb25UeXBlPlxue1xuICBzZWxlY3ROZXh0Q29ubmVjdG9yKFxuICAgIGNvbm5lY3RvcnM6IEFycmF5PEFic3RyYWN0TmV0d29ya0Nvbm5lY3RvcjxUcmFuc2FjdGlvblR5cGU+PixcbiAgICBjdXJyZW50SW5kZXg6IG51bWJlcixcbiAgKTogbnVtYmVyIHtcbiAgICByZXR1cm4gKGN1cnJlbnRJbmRleCArIDEpICUgY29ubmVjdG9ycy5sZW5ndGg7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,65 @@
1
+ import { AbstractLogger } from '@rosen-bridge/abstract-logger';
2
+ import { AbstractNetworkConnector, Block } from '@rosen-bridge/scanner-interfaces';
3
+ import { ConnectorSelectionStrategy } from './connectorSelectionStrategies';
4
+ /**
5
+ * Network connector manager that can handle multiple connectors
6
+ * for a single network with pluggable selection strategy
7
+ */
8
+ export declare class NetworkConnectorManager<TransactionType> implements AbstractNetworkConnector<TransactionType> {
9
+ private strategy;
10
+ private logger;
11
+ private connectors;
12
+ private currentConnectorIndex;
13
+ constructor(strategy?: ConnectorSelectionStrategy<TransactionType>, logger?: AbstractLogger);
14
+ /**
15
+ * Add a new connector to the manager
16
+ * @param connector The network connector instance
17
+ */
18
+ addConnector(connector: AbstractNetworkConnector<TransactionType>): void;
19
+ /**
20
+ * Get the current active connector
21
+ * @returns The current network connector instance
22
+ * @throws Error if no connectors are available
23
+ */
24
+ getCurrentConnector(): AbstractNetworkConnector<TransactionType>;
25
+ /**
26
+ * Execute an operation using the configured strategy
27
+ * @param operation The operation to execute
28
+ * @returns The result of the operation
29
+ */
30
+ private executeWithStrategy;
31
+ /**
32
+ * Set the strategy to use for connector selection
33
+ * @param strategy The strategy to use
34
+ */
35
+ setStrategy(strategy: ConnectorSelectionStrategy<TransactionType>): void;
36
+ /**
37
+ * Get a block at a specific height
38
+ * @param height The height of the block to get
39
+ * @returns The block at the specified height
40
+ */
41
+ getBlockAtHeight: (height: number) => Promise<Block>;
42
+ /**
43
+ * Get the current height of the blockchain
44
+ * @returns The current height
45
+ */
46
+ getCurrentHeight: () => Promise<number>;
47
+ /**
48
+ * Get all transactions in a block
49
+ * @param blockHash The hash of the block to get transactions from
50
+ * @param height The height of the block to get transactions from
51
+ * @returns Array of transactions in the block
52
+ */
53
+ getBlockTxs: (blockHash: string, height: number) => Promise<Array<TransactionType>>;
54
+ /**
55
+ * Get the number of available connectors
56
+ * @returns The number of connectors
57
+ */
58
+ getConnectorCount(): number;
59
+ /**
60
+ * Remove a connector at the specified index
61
+ * @param index The index of the connector to remove
62
+ */
63
+ removeConnector(index: number): void;
64
+ }
65
+ //# sourceMappingURL=networkConnectorManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"networkConnectorManager.d.ts","sourceRoot":"","sources":["../../../lib/scanner/network/networkConnectorManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAe,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EACL,wBAAwB,EACxB,KAAK,EACN,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,0BAA0B,EAE3B,MAAM,gCAAgC,CAAC;AAExC;;;GAGG;AACH,qBAAa,uBAAuB,CAAC,eAAe,CAClD,YAAW,wBAAwB,CAAC,eAAe,CAAC;IAMlD,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;IALhB,OAAO,CAAC,UAAU,CAAmD;IACrE,OAAO,CAAC,qBAAqB,CAAS;gBAG5B,QAAQ,GAAE,0BAA0B,CAAC,eAAe,CAA2C,EAC/F,MAAM,GAAE,cAAkC;IAQpD;;;OAGG;IACI,YAAY,CACjB,SAAS,EAAE,wBAAwB,CAAC,eAAe,CAAC,GACnD,IAAI;IAOP;;;;OAIG;IACH,mBAAmB,IAAI,wBAAwB,CAAC,eAAe,CAAC;IAQhE;;;;OAIG;YACW,mBAAmB;IA8CjC;;;OAGG;IACI,WAAW,CAChB,QAAQ,EAAE,0BAA0B,CAAC,eAAe,CAAC,GACpD,IAAI;IAKP;;;;OAIG;IACH,gBAAgB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,KAAK,CAAC,CAIvD;IAEF;;;OAGG;IACH,gBAAgB,QAAa,OAAO,CAAC,MAAM,CAAC,CAI1C;IAEF;;;;;OAKG;IACH,WAAW,GACT,WAAW,MAAM,EACjB,QAAQ,MAAM,KACb,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAIhC;IAEF;;;OAGG;IACI,iBAAiB,IAAI,MAAM;IAMlC;;;OAGG;IACI,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAU5C"}
@@ -0,0 +1,126 @@
1
+ import { DummyLogger } from '@rosen-bridge/abstract-logger';
2
+ import { FailoverStrategy, } from './connectorSelectionStrategies';
3
+ /**
4
+ * Network connector manager that can handle multiple connectors
5
+ * for a single network with pluggable selection strategy
6
+ */
7
+ export class NetworkConnectorManager {
8
+ strategy;
9
+ logger;
10
+ connectors;
11
+ currentConnectorIndex;
12
+ constructor(strategy = new FailoverStrategy(), logger = new DummyLogger()) {
13
+ this.strategy = strategy;
14
+ this.logger = logger;
15
+ this.connectors = [];
16
+ this.currentConnectorIndex = 0;
17
+ this.strategy = strategy;
18
+ this.logger.debug('NetworkConnectorManager initialized');
19
+ }
20
+ /**
21
+ * Add a new connector to the manager
22
+ * @param connector The network connector instance
23
+ */
24
+ addConnector(connector) {
25
+ this.connectors.push(connector);
26
+ this.logger.info(`Added new connector. Total connectors: ${this.connectors.length}`);
27
+ }
28
+ /**
29
+ * Get the current active connector
30
+ * @returns The current network connector instance
31
+ * @throws Error if no connectors are available
32
+ */
33
+ getCurrentConnector() {
34
+ if (this.connectors.length === 0) {
35
+ throw new Error('No connectors available');
36
+ }
37
+ this.logger.debug(`Using connector at index ${this.currentConnectorIndex}`);
38
+ return this.connectors[this.currentConnectorIndex];
39
+ }
40
+ /**
41
+ * Execute an operation using the configured strategy
42
+ * @param operation The operation to execute
43
+ * @returns The result of the operation
44
+ */
45
+ async executeWithStrategy(operation) {
46
+ if (this.connectors.length === 0) {
47
+ throw new Error('No connectors available for operation');
48
+ }
49
+ let lastError;
50
+ let attempts = 0;
51
+ const maxAttempts = this.connectors.length;
52
+ while (attempts < maxAttempts) {
53
+ try {
54
+ const connector = this.connectors[this.currentConnectorIndex];
55
+ this.logger.debug(`Attempt ${attempts + 1}/${maxAttempts} with connector at index ${this.currentConnectorIndex}`);
56
+ const result = await operation(connector);
57
+ this.currentConnectorIndex = this.strategy.selectNextConnector(this.connectors, this.currentConnectorIndex);
58
+ this.logger.debug(`Operation successful, next connector index: ${this.currentConnectorIndex}`);
59
+ return result;
60
+ }
61
+ catch (error) {
62
+ lastError = error;
63
+ this.logger.warn(`Operation failed with connector at index ${this.currentConnectorIndex}: ${lastError.message}`);
64
+ this.currentConnectorIndex = this.strategy.selectNextConnector(this.connectors, this.currentConnectorIndex, lastError);
65
+ attempts++;
66
+ }
67
+ }
68
+ throw lastError || new Error('All connectors failed');
69
+ }
70
+ /**
71
+ * Set the strategy to use for connector selection
72
+ * @param strategy The strategy to use
73
+ */
74
+ setStrategy(strategy) {
75
+ this.logger.info('Setting new connector selection strategy');
76
+ this.strategy = strategy;
77
+ }
78
+ /**
79
+ * Get a block at a specific height
80
+ * @param height The height of the block to get
81
+ * @returns The block at the specified height
82
+ */
83
+ getBlockAtHeight = async (height) => {
84
+ return this.executeWithStrategy((connector) => connector.getBlockAtHeight(height));
85
+ };
86
+ /**
87
+ * Get the current height of the blockchain
88
+ * @returns The current height
89
+ */
90
+ getCurrentHeight = async () => {
91
+ return this.executeWithStrategy((connector) => connector.getCurrentHeight());
92
+ };
93
+ /**
94
+ * Get all transactions in a block
95
+ * @param blockHash The hash of the block to get transactions from
96
+ * @param height The height of the block to get transactions from
97
+ * @returns Array of transactions in the block
98
+ */
99
+ getBlockTxs = async (blockHash, height) => {
100
+ return this.executeWithStrategy((connector) => connector.getBlockTxs(blockHash, height));
101
+ };
102
+ /**
103
+ * Get the number of available connectors
104
+ * @returns The number of connectors
105
+ */
106
+ getConnectorCount() {
107
+ const count = this.connectors.length;
108
+ this.logger.debug(`Current connector count: ${count}`);
109
+ return count;
110
+ }
111
+ /**
112
+ * Remove a connector at the specified index
113
+ * @param index The index of the connector to remove
114
+ */
115
+ removeConnector(index) {
116
+ if (index < 0 || index >= this.connectors.length) {
117
+ throw new Error('Invalid connector index');
118
+ }
119
+ this.logger.info(`Removing connector at index ${index}`);
120
+ this.connectors.splice(index, 1);
121
+ if (this.currentConnectorIndex >= this.connectors.length) {
122
+ this.currentConnectorIndex = 0;
123
+ }
124
+ }
125
+ }
126
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29ya0Nvbm5lY3Rvck1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9saWIvc2Nhbm5lci9uZXR3b3JrL25ldHdvcmtDb25uZWN0b3JNYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBa0IsV0FBVyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFNNUUsT0FBTyxFQUVMLGdCQUFnQixHQUNqQixNQUFNLGdDQUFnQyxDQUFDO0FBRXhDOzs7R0FHRztBQUNILE1BQU0sT0FBTyx1QkFBdUI7SUFPeEI7SUFDQTtJQUxGLFVBQVUsQ0FBbUQ7SUFDN0QscUJBQXFCLENBQVM7SUFFdEMsWUFDVSxXQUF3RCxJQUFJLGdCQUFnQixFQUFtQixFQUMvRixTQUF5QixJQUFJLFdBQVcsRUFBRTtRQUQxQyxhQUFRLEdBQVIsUUFBUSxDQUF1RjtRQUMvRixXQUFNLEdBQU4sTUFBTSxDQUFvQztRQUVsRCxJQUFJLENBQUMsVUFBVSxHQUFHLEVBQUUsQ0FBQztRQUNyQixJQUFJLENBQUMscUJBQXFCLEdBQUcsQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVEOzs7T0FHRztJQUNJLFlBQVksQ0FDakIsU0FBb0Q7UUFFcEQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQ2QsMENBQTBDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQ25FLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILG1CQUFtQjtRQUNqQixJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ2pDLE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUM3QyxDQUFDO1FBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsNEJBQTRCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLENBQUM7UUFDNUUsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssS0FBSyxDQUFDLG1CQUFtQixDQUMvQixTQUVlO1FBRWYsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNqQyxNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7UUFDM0QsQ0FBQztRQUVELElBQUksU0FBNEIsQ0FBQztRQUNqQyxJQUFJLFFBQVEsR0FBRyxDQUFDLENBQUM7UUFDakIsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7UUFFM0MsT0FBTyxRQUFRLEdBQUcsV0FBVyxFQUFFLENBQUM7WUFDOUIsSUFBSSxDQUFDO2dCQUNILE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUM7Z0JBQzlELElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUNmLFdBQVcsUUFBUSxHQUFHLENBQUMsSUFBSSxXQUFXLDRCQUNwQyxJQUFJLENBQUMscUJBQ1AsRUFBRSxDQUNILENBQUM7Z0JBQ0YsTUFBTSxNQUFNLEdBQUcsTUFBTSxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQzFDLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUM1RCxJQUFJLENBQUMsVUFBVSxFQUNmLElBQUksQ0FBQyxxQkFBcUIsQ0FDM0IsQ0FBQztnQkFDRixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDZiwrQ0FBK0MsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQzVFLENBQUM7Z0JBQ0YsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsU0FBUyxHQUFHLEtBQWMsQ0FBQztnQkFDM0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQ2QsNENBQTRDLElBQUksQ0FBQyxxQkFBcUIsS0FBSyxTQUFTLENBQUMsT0FBTyxFQUFFLENBQy9GLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsbUJBQW1CLENBQzVELElBQUksQ0FBQyxVQUFVLEVBQ2YsSUFBSSxDQUFDLHFCQUFxQixFQUMxQixTQUFTLENBQ1YsQ0FBQztnQkFDRixRQUFRLEVBQUUsQ0FBQztZQUNiLENBQUM7UUFDSCxDQUFDO1FBQ0QsTUFBTSxTQUFTLElBQUksSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztJQUN4RCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ksV0FBVyxDQUNoQixRQUFxRDtRQUVyRCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO0lBQzNCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsZ0JBQWdCLEdBQUcsS0FBSyxFQUFFLE1BQWMsRUFBa0IsRUFBRTtRQUMxRCxPQUFPLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQzVDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FDbkMsQ0FBQztJQUNKLENBQUMsQ0FBQztJQUVGOzs7T0FHRztJQUNILGdCQUFnQixHQUFHLEtBQUssSUFBcUIsRUFBRTtRQUM3QyxPQUFPLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQzVDLFNBQVMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUM3QixDQUFDO0lBQ0osQ0FBQyxDQUFDO0lBRUY7Ozs7O09BS0c7SUFDSCxXQUFXLEdBQUcsS0FBSyxFQUNqQixTQUFpQixFQUNqQixNQUFjLEVBQ21CLEVBQUU7UUFDbkMsT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUM1QyxTQUFTLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FDekMsQ0FBQztJQUNKLENBQUMsQ0FBQztJQUVGOzs7T0FHRztJQUNJLGlCQUFpQjtRQUN0QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQztRQUNyQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyw0QkFBNEIsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUN2RCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7O09BR0c7SUFDSSxlQUFlLENBQUMsS0FBYTtRQUNsQyxJQUFJLEtBQUssR0FBRyxDQUFDLElBQUksS0FBSyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDakQsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQywrQkFBK0IsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUN6RCxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDakMsSUFBSSxJQUFJLENBQUMscUJBQXFCLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN6RCxJQUFJLENBQUMscUJBQXFCLEdBQUcsQ0FBQyxDQUFDO1FBQ2pDLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBYnN0cmFjdExvZ2dlciwgRHVtbXlMb2dnZXIgfSBmcm9tICdAcm9zZW4tYnJpZGdlL2Fic3RyYWN0LWxvZ2dlcic7XG5pbXBvcnQge1xuICBBYnN0cmFjdE5ldHdvcmtDb25uZWN0b3IsXG4gIEJsb2NrLFxufSBmcm9tICdAcm9zZW4tYnJpZGdlL3NjYW5uZXItaW50ZXJmYWNlcyc7XG5cbmltcG9ydCB7XG4gIENvbm5lY3RvclNlbGVjdGlvblN0cmF0ZWd5LFxuICBGYWlsb3ZlclN0cmF0ZWd5LFxufSBmcm9tICcuL2Nvbm5lY3RvclNlbGVjdGlvblN0cmF0ZWdpZXMnO1xuXG4vKipcbiAqIE5ldHdvcmsgY29ubmVjdG9yIG1hbmFnZXIgdGhhdCBjYW4gaGFuZGxlIG11bHRpcGxlIGNvbm5lY3RvcnNcbiAqIGZvciBhIHNpbmdsZSBuZXR3b3JrIHdpdGggcGx1Z2dhYmxlIHNlbGVjdGlvbiBzdHJhdGVneVxuICovXG5leHBvcnQgY2xhc3MgTmV0d29ya0Nvbm5lY3Rvck1hbmFnZXI8VHJhbnNhY3Rpb25UeXBlPlxuICBpbXBsZW1lbnRzIEFic3RyYWN0TmV0d29ya0Nvbm5lY3RvcjxUcmFuc2FjdGlvblR5cGU+XG57XG4gIHByaXZhdGUgY29ubmVjdG9yczogQXJyYXk8QWJzdHJhY3ROZXR3b3JrQ29ubmVjdG9yPFRyYW5zYWN0aW9uVHlwZT4+O1xuICBwcml2YXRlIGN1cnJlbnRDb25uZWN0b3JJbmRleDogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgc3RyYXRlZ3k6IENvbm5lY3RvclNlbGVjdGlvblN0cmF0ZWd5PFRyYW5zYWN0aW9uVHlwZT4gPSBuZXcgRmFpbG92ZXJTdHJhdGVneTxUcmFuc2FjdGlvblR5cGU+KCksXG4gICAgcHJpdmF0ZSBsb2dnZXI6IEFic3RyYWN0TG9nZ2VyID0gbmV3IER1bW15TG9nZ2VyKCksXG4gICkge1xuICAgIHRoaXMuY29ubmVjdG9ycyA9IFtdO1xuICAgIHRoaXMuY3VycmVudENvbm5lY3RvckluZGV4ID0gMDtcbiAgICB0aGlzLnN0cmF0ZWd5ID0gc3RyYXRlZ3k7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoJ05ldHdvcmtDb25uZWN0b3JNYW5hZ2VyIGluaXRpYWxpemVkJyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgbmV3IGNvbm5lY3RvciB0byB0aGUgbWFuYWdlclxuICAgKiBAcGFyYW0gY29ubmVjdG9yIFRoZSBuZXR3b3JrIGNvbm5lY3RvciBpbnN0YW5jZVxuICAgKi9cbiAgcHVibGljIGFkZENvbm5lY3RvcihcbiAgICBjb25uZWN0b3I6IEFic3RyYWN0TmV0d29ya0Nvbm5lY3RvcjxUcmFuc2FjdGlvblR5cGU+LFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmNvbm5lY3RvcnMucHVzaChjb25uZWN0b3IpO1xuICAgIHRoaXMubG9nZ2VyLmluZm8oXG4gICAgICBgQWRkZWQgbmV3IGNvbm5lY3Rvci4gVG90YWwgY29ubmVjdG9yczogJHt0aGlzLmNvbm5lY3RvcnMubGVuZ3RofWAsXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGN1cnJlbnQgYWN0aXZlIGNvbm5lY3RvclxuICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCBuZXR3b3JrIGNvbm5lY3RvciBpbnN0YW5jZVxuICAgKiBAdGhyb3dzIEVycm9yIGlmIG5vIGNvbm5lY3RvcnMgYXJlIGF2YWlsYWJsZVxuICAgKi9cbiAgZ2V0Q3VycmVudENvbm5lY3RvcigpOiBBYnN0cmFjdE5ldHdvcmtDb25uZWN0b3I8VHJhbnNhY3Rpb25UeXBlPiB7XG4gICAgaWYgKHRoaXMuY29ubmVjdG9ycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gY29ubmVjdG9ycyBhdmFpbGFibGUnKTtcbiAgICB9XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoYFVzaW5nIGNvbm5lY3RvciBhdCBpbmRleCAke3RoaXMuY3VycmVudENvbm5lY3RvckluZGV4fWApO1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3RvcnNbdGhpcy5jdXJyZW50Q29ubmVjdG9ySW5kZXhdO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGUgYW4gb3BlcmF0aW9uIHVzaW5nIHRoZSBjb25maWd1cmVkIHN0cmF0ZWd5XG4gICAqIEBwYXJhbSBvcGVyYXRpb24gVGhlIG9wZXJhdGlvbiB0byBleGVjdXRlXG4gICAqIEByZXR1cm5zIFRoZSByZXN1bHQgb2YgdGhlIG9wZXJhdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBleGVjdXRlV2l0aFN0cmF0ZWd5PFQ+KFxuICAgIG9wZXJhdGlvbjogKFxuICAgICAgY29ubmVjdG9yOiBBYnN0cmFjdE5ldHdvcmtDb25uZWN0b3I8VHJhbnNhY3Rpb25UeXBlPixcbiAgICApID0+IFByb21pc2U8VD4sXG4gICk6IFByb21pc2U8VD4ge1xuICAgIGlmICh0aGlzLmNvbm5lY3RvcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNvbm5lY3RvcnMgYXZhaWxhYmxlIGZvciBvcGVyYXRpb24nKTtcbiAgICB9XG5cbiAgICBsZXQgbGFzdEVycm9yOiBFcnJvciB8IHVuZGVmaW5lZDtcbiAgICBsZXQgYXR0ZW1wdHMgPSAwO1xuICAgIGNvbnN0IG1heEF0dGVtcHRzID0gdGhpcy5jb25uZWN0b3JzLmxlbmd0aDtcblxuICAgIHdoaWxlIChhdHRlbXB0cyA8IG1heEF0dGVtcHRzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBjb25uZWN0b3IgPSB0aGlzLmNvbm5lY3RvcnNbdGhpcy5jdXJyZW50Q29ubmVjdG9ySW5kZXhdO1xuICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICBgQXR0ZW1wdCAke2F0dGVtcHRzICsgMX0vJHttYXhBdHRlbXB0c30gd2l0aCBjb25uZWN0b3IgYXQgaW5kZXggJHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudENvbm5lY3RvckluZGV4XG4gICAgICAgICAgfWAsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG9wZXJhdGlvbihjb25uZWN0b3IpO1xuICAgICAgICB0aGlzLmN1cnJlbnRDb25uZWN0b3JJbmRleCA9IHRoaXMuc3RyYXRlZ3kuc2VsZWN0TmV4dENvbm5lY3RvcihcbiAgICAgICAgICB0aGlzLmNvbm5lY3RvcnMsXG4gICAgICAgICAgdGhpcy5jdXJyZW50Q29ubmVjdG9ySW5kZXgsXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgICAgIGBPcGVyYXRpb24gc3VjY2Vzc2Z1bCwgbmV4dCBjb25uZWN0b3IgaW5kZXg6ICR7dGhpcy5jdXJyZW50Q29ubmVjdG9ySW5kZXh9YCxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGxhc3RFcnJvciA9IGVycm9yIGFzIEVycm9yO1xuICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFxuICAgICAgICAgIGBPcGVyYXRpb24gZmFpbGVkIHdpdGggY29ubmVjdG9yIGF0IGluZGV4ICR7dGhpcy5jdXJyZW50Q29ubmVjdG9ySW5kZXh9OiAke2xhc3RFcnJvci5tZXNzYWdlfWAsXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuY3VycmVudENvbm5lY3RvckluZGV4ID0gdGhpcy5zdHJhdGVneS5zZWxlY3ROZXh0Q29ubmVjdG9yKFxuICAgICAgICAgIHRoaXMuY29ubmVjdG9ycyxcbiAgICAgICAgICB0aGlzLmN1cnJlbnRDb25uZWN0b3JJbmRleCxcbiAgICAgICAgICBsYXN0RXJyb3IsXG4gICAgICAgICk7XG4gICAgICAgIGF0dGVtcHRzKys7XG4gICAgICB9XG4gICAgfVxuICAgIHRocm93IGxhc3RFcnJvciB8fCBuZXcgRXJyb3IoJ0FsbCBjb25uZWN0b3JzIGZhaWxlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgc3RyYXRlZ3kgdG8gdXNlIGZvciBjb25uZWN0b3Igc2VsZWN0aW9uXG4gICAqIEBwYXJhbSBzdHJhdGVneSBUaGUgc3RyYXRlZ3kgdG8gdXNlXG4gICAqL1xuICBwdWJsaWMgc2V0U3RyYXRlZ3koXG4gICAgc3RyYXRlZ3k6IENvbm5lY3RvclNlbGVjdGlvblN0cmF0ZWd5PFRyYW5zYWN0aW9uVHlwZT4sXG4gICk6IHZvaWQge1xuICAgIHRoaXMubG9nZ2VyLmluZm8oJ1NldHRpbmcgbmV3IGNvbm5lY3RvciBzZWxlY3Rpb24gc3RyYXRlZ3knKTtcbiAgICB0aGlzLnN0cmF0ZWd5ID0gc3RyYXRlZ3k7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGEgYmxvY2sgYXQgYSBzcGVjaWZpYyBoZWlnaHRcbiAgICogQHBhcmFtIGhlaWdodCBUaGUgaGVpZ2h0IG9mIHRoZSBibG9jayB0byBnZXRcbiAgICogQHJldHVybnMgVGhlIGJsb2NrIGF0IHRoZSBzcGVjaWZpZWQgaGVpZ2h0XG4gICAqL1xuICBnZXRCbG9ja0F0SGVpZ2h0ID0gYXN5bmMgKGhlaWdodDogbnVtYmVyKTogUHJvbWlzZTxCbG9jaz4gPT4ge1xuICAgIHJldHVybiB0aGlzLmV4ZWN1dGVXaXRoU3RyYXRlZ3koKGNvbm5lY3RvcikgPT5cbiAgICAgIGNvbm5lY3Rvci5nZXRCbG9ja0F0SGVpZ2h0KGhlaWdodCksXG4gICAgKTtcbiAgfTtcblxuICAvKipcbiAgICogR2V0IHRoZSBjdXJyZW50IGhlaWdodCBvZiB0aGUgYmxvY2tjaGFpblxuICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCBoZWlnaHRcbiAgICovXG4gIGdldEN1cnJlbnRIZWlnaHQgPSBhc3luYyAoKTogUHJvbWlzZTxudW1iZXI+ID0+IHtcbiAgICByZXR1cm4gdGhpcy5leGVjdXRlV2l0aFN0cmF0ZWd5KChjb25uZWN0b3IpID0+XG4gICAgICBjb25uZWN0b3IuZ2V0Q3VycmVudEhlaWdodCgpLFxuICAgICk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCBhbGwgdHJhbnNhY3Rpb25zIGluIGEgYmxvY2tcbiAgICogQHBhcmFtIGJsb2NrSGFzaCBUaGUgaGFzaCBvZiB0aGUgYmxvY2sgdG8gZ2V0IHRyYW5zYWN0aW9ucyBmcm9tXG4gICAqIEBwYXJhbSBoZWlnaHQgVGhlIGhlaWdodCBvZiB0aGUgYmxvY2sgdG8gZ2V0IHRyYW5zYWN0aW9ucyBmcm9tXG4gICAqIEByZXR1cm5zIEFycmF5IG9mIHRyYW5zYWN0aW9ucyBpbiB0aGUgYmxvY2tcbiAgICovXG4gIGdldEJsb2NrVHhzID0gYXN5bmMgKFxuICAgIGJsb2NrSGFzaDogc3RyaW5nLFxuICAgIGhlaWdodDogbnVtYmVyLFxuICApOiBQcm9taXNlPEFycmF5PFRyYW5zYWN0aW9uVHlwZT4+ID0+IHtcbiAgICByZXR1cm4gdGhpcy5leGVjdXRlV2l0aFN0cmF0ZWd5KChjb25uZWN0b3IpID0+XG4gICAgICBjb25uZWN0b3IuZ2V0QmxvY2tUeHMoYmxvY2tIYXNoLCBoZWlnaHQpLFxuICAgICk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbnVtYmVyIG9mIGF2YWlsYWJsZSBjb25uZWN0b3JzXG4gICAqIEByZXR1cm5zIFRoZSBudW1iZXIgb2YgY29ubmVjdG9yc1xuICAgKi9cbiAgcHVibGljIGdldENvbm5lY3RvckNvdW50KCk6IG51bWJlciB7XG4gICAgY29uc3QgY291bnQgPSB0aGlzLmNvbm5lY3RvcnMubGVuZ3RoO1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGBDdXJyZW50IGNvbm5lY3RvciBjb3VudDogJHtjb3VudH1gKTtcbiAgICByZXR1cm4gY291bnQ7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGEgY29ubmVjdG9yIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXhcbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgY29ubmVjdG9yIHRvIHJlbW92ZVxuICAgKi9cbiAgcHVibGljIHJlbW92ZUNvbm5lY3RvcihpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKGluZGV4IDwgMCB8fCBpbmRleCA+PSB0aGlzLmNvbm5lY3RvcnMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29ubmVjdG9yIGluZGV4Jyk7XG4gICAgfVxuICAgIHRoaXMubG9nZ2VyLmluZm8oYFJlbW92aW5nIGNvbm5lY3RvciBhdCBpbmRleCAke2luZGV4fWApO1xuICAgIHRoaXMuY29ubmVjdG9ycy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIGlmICh0aGlzLmN1cnJlbnRDb25uZWN0b3JJbmRleCA+PSB0aGlzLmNvbm5lY3RvcnMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmN1cnJlbnRDb25uZWN0b3JJbmRleCA9IDA7XG4gICAgfVxuICB9XG59XG4iXX0=