@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.
- package/CHANGELOG.md +135 -0
- package/README.md +49 -0
- package/dist/entities/blockEntity.d.ts +17 -0
- package/dist/entities/blockEntity.d.ts.map +1 -0
- package/dist/entities/blockEntity.js +78 -0
- package/dist/entities/extractorStatusEntity.d.ts +7 -0
- package/dist/entities/extractorStatusEntity.d.ts.map +1 -0
- package/dist/entities/extractorStatusEntity.js +37 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/migrations/index.d.ts +7 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +31 -0
- package/dist/migrations/postgres/1688545690867-migration.d.ts +7 -0
- package/dist/migrations/postgres/1688545690867-migration.d.ts.map +1 -0
- package/dist/migrations/postgres/1688545690867-migration.js +30 -0
- package/dist/migrations/postgres/1713803486477-migration.d.ts +7 -0
- package/dist/migrations/postgres/1713803486477-migration.d.ts.map +1 -0
- package/dist/migrations/postgres/1713803486477-migration.js +20 -0
- package/dist/migrations/postgres/1718789786123-migration.d.ts +7 -0
- package/dist/migrations/postgres/1718789786123-migration.d.ts.map +1 -0
- package/dist/migrations/postgres/1718789786123-migration.js +12 -0
- package/dist/migrations/postgres/1722697954558-migration.d.ts +7 -0
- package/dist/migrations/postgres/1722697954558-migration.d.ts.map +1 -0
- package/dist/migrations/postgres/1722697954558-migration.js +52 -0
- package/dist/migrations/postgres/1746701087567-migration.d.ts +7 -0
- package/dist/migrations/postgres/1746701087567-migration.d.ts.map +1 -0
- package/dist/migrations/postgres/1746701087567-migration.js +32 -0
- package/dist/migrations/postgres/1747657653564-migration.d.ts +7 -0
- package/dist/migrations/postgres/1747657653564-migration.d.ts.map +1 -0
- package/dist/migrations/postgres/1747657653564-migration.js +134 -0
- package/dist/migrations/sqlite/1688555497475-migration.d.ts +7 -0
- package/dist/migrations/sqlite/1688555497475-migration.d.ts.map +1 -0
- package/dist/migrations/sqlite/1688555497475-migration.js +29 -0
- package/dist/migrations/sqlite/1713786682123-migration.d.ts +7 -0
- package/dist/migrations/sqlite/1713786682123-migration.d.ts.map +1 -0
- package/dist/migrations/sqlite/1713786682123-migration.js +20 -0
- package/dist/migrations/sqlite/1718789744123-migration.d.ts +7 -0
- package/dist/migrations/sqlite/1718789744123-migration.d.ts.map +1 -0
- package/dist/migrations/sqlite/1718789744123-migration.js +12 -0
- package/dist/migrations/sqlite/1722697111974-migration.d.ts +7 -0
- package/dist/migrations/sqlite/1722697111974-migration.d.ts.map +1 -0
- package/dist/migrations/sqlite/1722697111974-migration.js +112 -0
- package/dist/migrations/sqlite/1746701087234-migration.d.ts +7 -0
- package/dist/migrations/sqlite/1746701087234-migration.d.ts.map +1 -0
- package/dist/migrations/sqlite/1746701087234-migration.js +32 -0
- package/dist/migrations/sqlite/1747655941239-migration.d.ts +7 -0
- package/dist/migrations/sqlite/1747655941239-migration.d.ts.map +1 -0
- package/dist/migrations/sqlite/1747655941239-migration.js +134 -0
- package/dist/scanner/abstract/generalScanner.d.ts +78 -0
- package/dist/scanner/abstract/generalScanner.d.ts.map +1 -0
- package/dist/scanner/abstract/generalScanner.js +210 -0
- package/dist/scanner/abstract/scanner.d.ts +49 -0
- package/dist/scanner/abstract/scanner.d.ts.map +1 -0
- package/dist/scanner/abstract/scanner.js +142 -0
- package/dist/scanner/abstract/webSocketScanner.d.ts +29 -0
- package/dist/scanner/abstract/webSocketScanner.d.ts.map +1 -0
- package/dist/scanner/abstract/webSocketScanner.js +90 -0
- package/dist/scanner/action.d.ts +83 -0
- package/dist/scanner/action.d.ts.map +1 -0
- package/dist/scanner/action.js +251 -0
- package/dist/scanner/interfaces.d.ts +13 -0
- package/dist/scanner/interfaces.d.ts.map +1 -0
- package/dist/scanner/interfaces.js +2 -0
- package/dist/scanner/network/connectorSelectionStrategies.d.ts +27 -0
- package/dist/scanner/network/connectorSelectionStrategies.d.ts.map +1 -0
- package/dist/scanner/network/connectorSelectionStrategies.js +22 -0
- package/dist/scanner/network/networkConnectorManager.d.ts +65 -0
- package/dist/scanner/network/networkConnectorManager.d.ts.map +1 -0
- package/dist/scanner/network/networkConnectorManager.js +126 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { difference, remove } from 'lodash-es';
|
|
2
|
+
import { DummyLogger } from '@rosen-bridge/abstract-logger';
|
|
3
|
+
import { Mutex } from '@rosen-bridge/semaphore';
|
|
4
|
+
export class AbstractScanner {
|
|
5
|
+
action;
|
|
6
|
+
extractors;
|
|
7
|
+
newExtractors;
|
|
8
|
+
logger;
|
|
9
|
+
initializeMutex;
|
|
10
|
+
constructor(logger) {
|
|
11
|
+
this.extractors = [];
|
|
12
|
+
this.newExtractors = [];
|
|
13
|
+
this.logger = logger ? logger : new DummyLogger();
|
|
14
|
+
this.initializeMutex = new Mutex();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* fork blocks from specific height from scanner.
|
|
18
|
+
* @param height: selected height
|
|
19
|
+
*/
|
|
20
|
+
forkBlock = async (height) => {
|
|
21
|
+
let lastBlock = await this.action.getLastSavedBlock();
|
|
22
|
+
while (lastBlock && lastBlock.height >= height) {
|
|
23
|
+
this.logger.debug(`Reverting block ${lastBlock.hash} at height ${lastBlock.height}`);
|
|
24
|
+
await this.action.revertBlockStatus(lastBlock.height, lastBlock.parentHash, this.extractors.map((e) => e.getId()));
|
|
25
|
+
for (const extractor of this.extractors) {
|
|
26
|
+
await extractor.forkBlock(lastBlock.hash);
|
|
27
|
+
}
|
|
28
|
+
await this.action.removeBlocksFromHeight(lastBlock.height);
|
|
29
|
+
lastBlock = await this.action.getBlockAtHeight(lastBlock.height - 1);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* process a block and all of its transactions. store any information into database
|
|
34
|
+
* @param block: selected block
|
|
35
|
+
* @param transactions: list of transaction for selected block
|
|
36
|
+
*/
|
|
37
|
+
processBlockTransactions = async (block, transactions) => {
|
|
38
|
+
const savedBlock = await this.action.saveBlock(block);
|
|
39
|
+
if (typeof savedBlock === 'boolean') {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
let success = true;
|
|
43
|
+
for (const extractor of this.extractors) {
|
|
44
|
+
if (!(await extractor.processTransactions(transactions, savedBlock))) {
|
|
45
|
+
success = false;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (success &&
|
|
50
|
+
(await this.action.updateBlockStatus(block.height, block.hash, this.extractors.map((e) => e.getId())))) {
|
|
51
|
+
return savedBlock;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* register a nre extractor to scanner.
|
|
57
|
+
* @param extractor
|
|
58
|
+
*/
|
|
59
|
+
registerExtractor = async (extractor) => {
|
|
60
|
+
const notRegisteredIn = (extractors) => extractors.filter((extractorItem) => extractorItem.getId() === extractor.getId()).length === 0;
|
|
61
|
+
const release = await this.initializeMutex.acquire();
|
|
62
|
+
if (notRegisteredIn(this.extractors) &&
|
|
63
|
+
notRegisteredIn(this.newExtractors)) {
|
|
64
|
+
this.newExtractors.push(extractor);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
this.logger.warn(`Extractor with id ${extractor.getId()} is already registered`);
|
|
68
|
+
}
|
|
69
|
+
release();
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* remove an extractor from scanner
|
|
73
|
+
* @param extractor
|
|
74
|
+
*/
|
|
75
|
+
removeExtractor = async (extractor) => {
|
|
76
|
+
const removeFn = (ex) => ex.getId() === extractor.getId();
|
|
77
|
+
const release = await this.initializeMutex.acquire();
|
|
78
|
+
remove(this.extractors, removeFn);
|
|
79
|
+
remove(this.newExtractors, removeFn);
|
|
80
|
+
release();
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Initialize all specified extractors and store the updated status
|
|
84
|
+
* @param extractorIds
|
|
85
|
+
* @param height
|
|
86
|
+
*/
|
|
87
|
+
initializeExtractors = async (extractorIds, block) => {
|
|
88
|
+
const allExtractors = [...this.extractors, ...this.newExtractors];
|
|
89
|
+
const initRequiredExtractors = allExtractors.filter((extractor) => extractorIds.includes(extractor.getId()));
|
|
90
|
+
for (const extractor of initRequiredExtractors) {
|
|
91
|
+
this.logger.info(`Initializing [${extractor.getId()}] boxes`);
|
|
92
|
+
await extractor.initializeData(block);
|
|
93
|
+
await this.action.updateOrInsertExtractorStatus(extractor.getId(), block.height, block.hash);
|
|
94
|
+
this.logger.debug(`Initialization finished for [${extractor.getId()}]`);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Initializes the extractors if they're not synced or not initialized yet,
|
|
99
|
+
* and update the active extractors list
|
|
100
|
+
* @param block
|
|
101
|
+
*/
|
|
102
|
+
verifyExtractorsInitialization = async (block) => {
|
|
103
|
+
const getIds = (extractors) => {
|
|
104
|
+
return extractors.map((extractor) => extractor.getId());
|
|
105
|
+
};
|
|
106
|
+
this.logger.debug(`Initializing extractors for block [${block.height}]`);
|
|
107
|
+
const release = await this.initializeMutex.acquire();
|
|
108
|
+
try {
|
|
109
|
+
const extractorsStatus = await this.action.getExtractorsStatus([
|
|
110
|
+
...getIds(this.extractors),
|
|
111
|
+
...getIds(this.newExtractors),
|
|
112
|
+
]);
|
|
113
|
+
this.logger.debug(`Stored extractors status are [${JSON.stringify(extractorsStatus)}]`);
|
|
114
|
+
// Find extractors not synced with the latest height
|
|
115
|
+
const notSyncedExtractorIds = extractorsStatus
|
|
116
|
+
.filter((es) => es.updateBlockHash != block.hash)
|
|
117
|
+
.map((es) => es.extractorId);
|
|
118
|
+
if (notSyncedExtractorIds.length > 0)
|
|
119
|
+
this.logger.debug(`Old not synced extractors are ${notSyncedExtractorIds}`);
|
|
120
|
+
// Find new extractors not available in database
|
|
121
|
+
const storedExtractorIds = extractorsStatus.map((es) => es.extractorId);
|
|
122
|
+
const newRegisteredExtractorIds = difference(getIds(this.newExtractors), storedExtractorIds);
|
|
123
|
+
if (newRegisteredExtractorIds.length > 0)
|
|
124
|
+
this.logger.debug(`New registered extractors are ${newRegisteredExtractorIds}`);
|
|
125
|
+
// Initialize required extractors
|
|
126
|
+
const initRequiredExtractors = [
|
|
127
|
+
...newRegisteredExtractorIds,
|
|
128
|
+
...notSyncedExtractorIds,
|
|
129
|
+
];
|
|
130
|
+
if (initRequiredExtractors.length > 0) {
|
|
131
|
+
this.logger.info(`Initializing ${initRequiredExtractors.length} extractor(s) for [${this.name()}]`, { initRequiredExtractors });
|
|
132
|
+
await this.initializeExtractors(initRequiredExtractors, block);
|
|
133
|
+
}
|
|
134
|
+
this.extractors.push(...this.newExtractors);
|
|
135
|
+
this.newExtractors = [];
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
release();
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Nhbm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9zY2FubmVyL2Fic3RyYWN0L3NjYW5uZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFHL0MsT0FBTyxFQUFrQixXQUFXLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUc1RSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFJaEQsTUFBTSxPQUFnQixlQUFlO0lBQ25DLE1BQU0sQ0FBZ0I7SUFDdEIsVUFBVSxDQUEyRDtJQUNyRSxhQUFhLENBQTJEO0lBQ3hFLE1BQU0sQ0FBaUI7SUFDdkIsZUFBZSxDQUFRO0lBRXZCLFlBQVksTUFBdUI7UUFDakMsSUFBSSxDQUFDLFVBQVUsR0FBRyxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLGFBQWEsR0FBRyxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxXQUFXLEVBQUUsQ0FBQztRQUNsRCxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7SUFDckMsQ0FBQztJQUlEOzs7T0FHRztJQUNPLFNBQVMsR0FBRyxLQUFLLEVBQUUsTUFBYyxFQUFFLEVBQUU7UUFDN0MsSUFBSSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDdEQsT0FBTyxTQUFTLElBQUksU0FBUyxDQUFDLE1BQU0sSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUMvQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDZixtQkFBbUIsU0FBUyxDQUFDLElBQUksY0FBYyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQ2xFLENBQUM7WUFDRixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsaUJB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QkFBcUIsRUFBRSxDQUN6RCxDQUFDO1lBQ0osZ0RBQWdEO1lBQ2hELE1BQU0sa0JBQWtCLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDeEUsTUFBTSx5QkFBeUIsR0FBRyxVQUFVLENBQzFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEVBQzFCLGtCQUFrQixDQUNuQixDQUFDO1lBQ0YsSUFBSSx5QkFBeUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQztnQkFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ2YsaUNBQWlDLHlCQUF5QixFQUFFLENBQzdELENBQUM7WUFDSixpQ0FBaUM7WUFDakMsTUFBTSxzQkFBc0IsR0FBRztnQkFDN0IsR0FBRyx5QkFBeUI7Z0JBQzVCLEdBQUcscUJBQXFCO2FBQ3pCLENBQUM7WUFDRixJQUFJLHNCQUFzQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQ2QsZ0JBQ0Usc0JBQXNCLENBQUMsTUFDekIsc0JBQXNCLElBQUksQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUNwQyxFQUFFLHNCQUFzQixFQUFFLENBQzNCLENBQUM7Z0JBQ0YsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsc0JBQXNCLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDakUsQ0FBQztZQUNELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQzVDLElBQUksQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDO1FBQzFCLENBQUM7Z0JBQVMsQ0FBQztZQUNULE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztJQUNILENBQUMsQ0FBQztDQUNIIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZGlmZmVyZW5jZSwgcmVtb3ZlIH0gZnJvbSAnbG9kYXNoLWVzJztcblxuaW1wb3J0IHsgQWJzdHJhY3RFeHRyYWN0b3IgfSBmcm9tICdAcm9zZW4tYnJpZGdlL2Fic3RyYWN0LWV4dHJhY3Rvcic7XG5pbXBvcnQgeyBBYnN0cmFjdExvZ2dlciwgRHVtbXlMb2dnZXIgfSBmcm9tICdAcm9zZW4tYnJpZGdlL2Fic3RyYWN0LWxvZ2dlcic7XG5pbXBvcnQgeyBPYmplY3RMaXRlcmFsIH0gZnJvbSAnQHJvc2VuLWJyaWRnZS9leHRlbmRlZC10eXBlb3JtJztcbmltcG9ydCB7IEJsb2NrLCBCbG9ja0luZm8gfSBmcm9tICdAcm9zZW4tYnJpZGdlL3NjYW5uZXItaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBNdXRleCB9IGZyb20gJ0Byb3Nlbi1icmlkZ2Uvc2VtYXBob3JlJztcblxuaW1wb3J0IHsgQmxvY2tEYkFjdGlvbiB9IGZyb20gJy4uL2FjdGlvbic7XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBBYnN0cmFjdFNjYW5uZXI8VHJhbnNhY3Rpb25UeXBlPiB7XG4gIGFjdGlvbjogQmxvY2tEYkFjdGlvbjtcbiAgZXh0cmFjdG9yczogQXJyYXk8QWJzdHJhY3RFeHRyYWN0b3I8VHJhbnNhY3Rpb25UeXBlLCBPYmplY3RMaXRlcmFsPj47XG4gIG5ld0V4dHJhY3RvcnM6IEFycmF5PEFic3RyYWN0RXh0cmFjdG9yPFRyYW5zYWN0aW9uVHlwZSwgT2JqZWN0TGl0ZXJhbD4+O1xuICBsb2dnZXI6IEFic3RyYWN0TG9nZ2VyO1xuICBpbml0aWFsaXplTXV0ZXg6IE11dGV4O1xuXG4gIGNvbnN0cnVjdG9yKGxvZ2dlcj86IEFic3RyYWN0TG9nZ2VyKSB7XG4gICAgdGhpcy5leHRyYWN0b3JzID0gW107XG4gICAgdGhpcy5uZXdFeHRyYWN0b3JzID0gW107XG4gICAgdGhpcy5sb2dnZXIgPSBsb2dnZXIgPyBsb2dnZXIgOiBuZXcgRHVtbXlMb2dnZXIoKTtcbiAgICB0aGlzLmluaXRpYWxpemVNdXRleCA9IG5ldyBNdXRleCgpO1xuICB9XG5cbiAgYWJzdHJhY3QgbmFtZTogKCkgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBmb3JrIGJsb2NrcyBmcm9tIHNwZWNpZmljIGhlaWdodCBmcm9tIHNjYW5uZXIuXG4gICAqIEBwYXJhbSBoZWlnaHQ6IHNlbGVjdGVkIGhlaWdodFxuICAgKi9cbiAgcHJvdGVjdGVkIGZvcmtCbG9jayA9IGFzeW5jIChoZWlnaHQ6IG51bWJlcikgPT4ge1xuICAgIGxldCBsYXN0QmxvY2sgPSBhd2FpdCB0aGlzLmFjdGlvbi5nZXRMYXN0U2F2ZWRCbG9jaygpO1xuICAgIHdoaWxlIChsYXN0QmxvY2sgJiYgbGFzdEJsb2NrLmhlaWdodCA+PSBoZWlnaHQpIHtcbiAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgICBgUmV2ZXJ0aW5nIGJsb2NrICR7bGFzdEJsb2NrLmhhc2h9IGF0IGhlaWdodCAke2xhc3RCbG9jay5oZWlnaHR9YCxcbiAgICAgICk7XG4gICAgICBhd2FpdCB0aGlzLmFjdGlvbi5yZXZlcnRCbG9ja1N0YXR1cyhcbiAgICAgICAgbGFzdEJsb2NrLmhlaWdodCxcbiAgICAgICAgbGFzdEJsb2NrLnBhcmVudEhhc2gsXG4gICAgICAgIHRoaXMuZXh0cmFjdG9ycy5tYXAoKGUpID0+IGUuZ2V0SWQoKSksXG4gICAgICApO1xuICAgICAgZm9yIChjb25zdCBleHRyYWN0b3Igb2YgdGhpcy5leHRyYWN0b3JzKSB7XG4gICAgICAgIGF3YWl0IGV4dHJhY3Rvci5mb3JrQmxvY2sobGFzdEJsb2NrLmhhc2gpO1xuICAgICAgfVxuICAgICAgYXdhaXQgdGhpcy5hY3Rpb24ucmVtb3ZlQmxvY2tzRnJvbUhlaWdodChsYXN0QmxvY2suaGVpZ2h0KTtcbiAgICAgIGxhc3RCbG9jayA9IGF3YWl0IHRoaXMuYWN0aW9uLmdldEJsb2NrQXRIZWlnaHQobGFzdEJsb2NrLmhlaWdodCAtIDEpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogcHJvY2VzcyBhIGJsb2NrIGFuZCBhbGwgb2YgaXRzIHRyYW5zYWN0aW9ucy4gc3RvcmUgYW55IGluZm9ybWF0aW9uIGludG8gZGF0YWJhc2VcbiAgICogQHBhcmFtIGJsb2NrOiBzZWxlY3RlZCBibG9ja1xuICAgKiBAcGFyYW0gdHJhbnNhY3Rpb25zOiBsaXN0IG9mIHRyYW5zYWN0aW9uIGZvciBzZWxlY3RlZCBibG9ja1xuICAgKi9cbiAgcHJvdGVjdGVkIHByb2Nlc3NCbG9ja1RyYW5zYWN0aW9ucyA9IGFzeW5jIChcbiAgICBibG9jazogQmxvY2ssXG4gICAgdHJhbnNhY3Rpb25zOiBBcnJheTxUcmFuc2FjdGlvblR5cGU+LFxuICApID0+IHtcbiAgICBjb25zdCBzYXZlZEJsb2NrID0gYXdhaXQgdGhpcy5hY3Rpb24uc2F2ZUJsb2NrKGJsb2NrKTtcbiAgICBpZiAodHlwZW9mIHNhdmVkQmxvY2sgPT09ICdib29sZWFuJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBsZXQgc3VjY2VzcyA9IHRydWU7XG4gICAgZm9yIChjb25zdCBleHRyYWN0b3Igb2YgdGhpcy5leHRyYWN0b3JzKSB7XG4gICAgICBpZiAoIShhd2FpdCBleHRyYWN0b3IucHJvY2Vzc1RyYW5zYWN0aW9ucyh0cmFuc2FjdGlvbnMsIHNhdmVkQmxvY2spKSkge1xuICAgICAgICBzdWNjZXNzID0gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChcbiAgICAgIHN1Y2Nlc3MgJiZcbiAgICAgIChhd2FpdCB0aGlzLmFjdGlvbi51cGRhdGVCbG9ja1N0YXR1cyhcbiAgICAgICAgYmxvY2suaGVpZ2h0LFxuICAgICAgICBibG9jay5oYXNoLFxuICAgICAgICB0aGlzLmV4dHJhY3RvcnMubWFwKChlKSA9PiBlLmdldElkKCkpLFxuICAgICAgKSlcbiAgICApIHtcbiAgICAgIHJldHVybiBzYXZlZEJsb2NrO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG5cbiAgLyoqXG4gICAqIHJlZ2lzdGVyIGEgbnJlIGV4dHJhY3RvciB0byBzY2FubmVyLlxuICAgKiBAcGFyYW0gZXh0cmFjdG9yXG4gICAqL1xuICByZWdpc3RlckV4dHJhY3RvciA9IGFzeW5jIChcbiAgICBleHRyYWN0b3I6IEFic3RyYWN0RXh0cmFjdG9yPFRyYW5zYWN0aW9uVHlwZSwgT2JqZWN0TGl0ZXJhbD4sXG4gICk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGNvbnN0IG5vdFJlZ2lzdGVyZWRJbiA9IChcbiAgICAgIGV4dHJhY3RvcnM6IEFycmF5PEFic3RyYWN0RXh0cmFjdG9yPFRyYW5zYWN0aW9uVHlwZSwgT2JqZWN0TGl0ZXJhbD4+LFxuICAgICkgPT5cbiAgICAgIGV4dHJhY3RvcnMuZmlsdGVyKFxuICAgICAgICAoZXh0cmFjdG9ySXRlbSkgPT4gZXh0cmFjdG9ySXRlbS5nZXRJZCgpID09PSBleHRyYWN0b3IuZ2V0SWQoKSxcbiAgICAgICkubGVuZ3RoID09PSAwO1xuICAgIGNvbnN0IHJlbGVhc2UgPSBhd2FpdCB0aGlzLmluaXRpYWxpemVNdXRleC5hY3F1aXJlKCk7XG4gICAgaWYgKFxuICAgICAgbm90UmVnaXN0ZXJlZEluKHRoaXMuZXh0cmFjdG9ycykgJiZcbiAgICAgIG5vdFJlZ2lzdGVyZWRJbih0aGlzLm5ld0V4dHJhY3RvcnMpXG4gICAgKSB7XG4gICAgICB0aGlzLm5ld0V4dHJhY3RvcnMucHVzaChleHRyYWN0b3IpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxvZ2dlci53YXJuKFxuICAgICAgICBgRXh0cmFjdG9yIHdpdGggaWQgJHtleHRyYWN0b3IuZ2V0SWQoKX0gaXMgYWxyZWFkeSByZWdpc3RlcmVkYCxcbiAgICAgICk7XG4gICAgfVxuICAgIHJlbGVhc2UoKTtcbiAgfTtcblxuICAvKipcbiAgICogcmVtb3ZlIGFuIGV4dHJhY3RvciBmcm9tIHNjYW5uZXJcbiAgICogQHBhcmFtIGV4dHJhY3RvclxuICAgKi9cbiAgcmVtb3ZlRXh0cmFjdG9yID0gYXN5bmMgKFxuICAgIGV4dHJhY3RvcjogQWJzdHJhY3RFeHRyYWN0b3I8VHJhbnNhY3Rpb25UeXBlLCBPYmplY3RMaXRlcmFsPixcbiAgKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgY29uc3QgcmVtb3ZlRm4gPSAoZXg6IEFic3RyYWN0RXh0cmFjdG9yPFRyYW5zYWN0aW9uVHlwZSwgT2JqZWN0TGl0ZXJhbD4pID0+XG4gICAgICBleC5nZXRJZCgpID09PSBleHRyYWN0b3IuZ2V0SWQoKTtcblxuICAgIGNvbnN0IHJlbGVhc2UgPSBhd2FpdCB0aGlzLmluaXRpYWxpemVNdXRleC5hY3F1aXJlKCk7XG4gICAgcmVtb3ZlKHRoaXMuZXh0cmFjdG9ycywgcmVtb3ZlRm4pO1xuICAgIHJlbW92ZSh0aGlzLm5ld0V4dHJhY3RvcnMsIHJlbW92ZUZuKTtcbiAgICByZWxlYXNlKCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemUgYWxsIHNwZWNpZmllZCBleHRyYWN0b3JzIGFuZCBzdG9yZSB0aGUgdXBkYXRlZCBzdGF0dXNcbiAgICogQHBhcmFtIGV4dHJhY3Rvcklkc1xuICAgKiBAcGFyYW0gaGVpZ2h0XG4gICAqL1xuICBwcml2YXRlIGluaXRpYWxpemVFeHRyYWN0b3JzID0gYXN5bmMgKFxuICAgIGV4dHJhY3Rvcklkczogc3RyaW5nW10sXG4gICAgYmxvY2s6IEJsb2NrSW5mbyxcbiAgKSA9PiB7XG4gICAgY29uc3QgYWxsRXh0cmFjdG9ycyA9IFsuLi50aGlzLmV4dHJhY3RvcnMsIC4uLnRoaXMubmV3RXh0cmFjdG9yc107XG4gICAgY29uc3QgaW5pdFJlcXVpcmVkRXh0cmFjdG9ycyA9IGFsbEV4dHJhY3RvcnMuZmlsdGVyKChleHRyYWN0b3IpID0+XG4gICAgICBleHRyYWN0b3JJZHMuaW5jbHVkZXMoZXh0cmFjdG9yLmdldElkKCkpLFxuICAgICk7XG4gICAgZm9yIChjb25zdCBleHRyYWN0b3Igb2YgaW5pdFJlcXVpcmVkRXh0cmFjdG9ycykge1xuICAgICAgdGhpcy5sb2dnZXIuaW5mbyhgSW5pdGlhbGl6aW5nIFske2V4dHJhY3Rvci5nZXRJZCgpfV0gYm94ZXNgKTtcbiAgICAgIGF3YWl0IGV4dHJhY3Rvci5pbml0aWFsaXplRGF0YShibG9jayk7XG4gICAgICBhd2FpdCB0aGlzLmFjdGlvbi51cGRhdGVPckluc2VydEV4dHJhY3RvclN0YXR1cyhcbiAgICAgICAgZXh0cmFjdG9yLmdldElkKCksXG4gICAgICAgIGJsb2NrLmhlaWdodCxcbiAgICAgICAgYmxvY2suaGFzaCxcbiAgICAgICk7XG4gICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgSW5pdGlhbGl6YXRpb24gZmluaXNoZWQgZm9yIFske2V4dHJhY3Rvci5nZXRJZCgpfV1gKTtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIHRoZSBleHRyYWN0b3JzIGlmIHRoZXkncmUgbm90IHN5bmNlZCBvciBub3QgaW5pdGlhbGl6ZWQgeWV0LFxuICAgKiBhbmQgdXBkYXRlIHRoZSBhY3RpdmUgZXh0cmFjdG9ycyBsaXN0XG4gICAqIEBwYXJhbSBibG9ja1xuICAgKi9cbiAgcHJvdGVjdGVkIHZlcmlmeUV4dHJhY3RvcnNJbml0aWFsaXphdGlvbiA9IGFzeW5jIChibG9jazogQmxvY2tJbmZvKSA9PiB7XG4gICAgY29uc3QgZ2V0SWRzID0gKFxuICAgICAgZXh0cmFjdG9yczogQXJyYXk8QWJzdHJhY3RFeHRyYWN0b3I8VHJhbnNhY3Rpb25UeXBlLCBPYmplY3RMaXRlcmFsPj4sXG4gICAgKSA9PiB7XG4gICAgICByZXR1cm4gZXh0cmFjdG9ycy5tYXAoKGV4dHJhY3RvcikgPT4gZXh0cmFjdG9yLmdldElkKCkpO1xuICAgIH07XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoYEluaXRpYWxpemluZyBleHRyYWN0b3JzIGZvciBibG9jayBbJHtibG9jay5oZWlnaHR9XWApO1xuICAgIGNvbnN0IHJlbGVhc2UgPSBhd2FpdCB0aGlzLmluaXRpYWxpemVNdXRleC5hY3F1aXJlKCk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGV4dHJhY3RvcnNTdGF0dXMgPSBhd2FpdCB0aGlzLmFjdGlvbi5nZXRFeHRyYWN0b3JzU3RhdHVzKFtcbiAgICAgICAgLi4uZ2V0SWRzKHRoaXMuZXh0cmFjdG9ycyksXG4gICAgICAgIC4uLmdldElkcyh0aGlzLm5ld0V4dHJhY3RvcnMpLFxuICAgICAgXSk7XG4gICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgYFN0b3JlZCBleHRyYWN0b3JzIHN0YXR1cyBhcmUgWyR7SlNPTi5zdHJpbmdpZnkoZXh0cmFjdG9yc1N0YXR1cyl9XWAsXG4gICAgICApO1xuICAgICAgLy8gRmluZCBleHRyYWN0b3JzIG5vdCBzeW5jZWQgd2l0aCB0aGUgbGF0ZXN0IGhlaWdodFxuICAgICAgY29uc3Qgbm90U3luY2VkRXh0cmFjdG9ySWRzID0gZXh0cmFjdG9yc1N0YXR1c1xuICAgICAgICAuZmlsdGVyKChlcykgPT4gZXMudXBkYXRlQmxvY2tIYXNoICE9IGJsb2NrLmhhc2gpXG4gICAgICAgIC5tYXAoKGVzKSA9PiBlcy5leHRyYWN0b3JJZCk7XG4gICAgICBpZiAobm90U3luY2VkRXh0cmFjdG9ySWRzLmxlbmd0aCA+IDApXG4gICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgICAgIGBPbGQgbm90IHN5bmNlZCBleHRyYWN0b3JzIGFyZSAke25vdFN5bmNlZEV4dHJhY3Rvcklkc31gLFxuICAgICAgICApO1xuICAgICAgLy8gRmluZCBuZXcgZXh0cmFjdG9ycyBub3QgYXZhaWxhYmxlIGluIGRhdGFiYXNlXG4gICAgICBjb25zdCBzdG9yZWRFeHRyYWN0b3JJZHMgPSBleHRyYWN0b3JzU3RhdHVzLm1hcCgoZXMpID0+IGVzLmV4dHJhY3RvcklkKTtcbiAgICAgIGNvbnN0IG5ld1JlZ2lzdGVyZWRFeHRyYWN0b3JJZHMgPSBkaWZmZXJlbmNlKFxuICAgICAgICBnZXRJZHModGhpcy5uZXdFeHRyYWN0b3JzKSxcbiAgICAgICAgc3RvcmVkRXh0cmFjdG9ySWRzLFxuICAgICAgKTtcbiAgICAgIGlmIChuZXdSZWdpc3RlcmVkRXh0cmFjdG9ySWRzLmxlbmd0aCA+IDApXG4gICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKFxuICAgICAgICAgIGBOZXcgcmVnaXN0ZXJlZCBleHRyYWN0b3JzIGFyZSAke25ld1JlZ2lzdGVyZWRFeHRyYWN0b3JJZHN9YCxcbiAgICAgICAgKTtcbiAgICAgIC8vIEluaXRpYWxpemUgcmVxdWlyZWQgZXh0cmFjdG9yc1xuICAgICAgY29uc3QgaW5pdFJlcXVpcmVkRXh0cmFjdG9ycyA9IFtcbiAgICAgICAgLi4ubmV3UmVnaXN0ZXJlZEV4dHJhY3RvcklkcyxcbiAgICAgICAgLi4ubm90U3luY2VkRXh0cmFjdG9ySWRzLFxuICAgICAgXTtcbiAgICAgIGlmIChpbml0UmVxdWlyZWRFeHRyYWN0b3JzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuaW5mbyhcbiAgICAgICAgICBgSW5pdGlhbGl6aW5nICR7XG4gICAgICAgICAgICBpbml0UmVxdWlyZWRFeHRyYWN0b3JzLmxlbmd0aFxuICAgICAgICAgIH0gZXh0cmFjdG9yKHMpIGZvciBbJHt0aGlzLm5hbWUoKX1dYCxcbiAgICAgICAgICB7IGluaXRSZXF1aXJlZEV4dHJhY3RvcnMgfSxcbiAgICAgICAgKTtcbiAgICAgICAgYXdhaXQgdGhpcy5pbml0aWFsaXplRXh0cmFjdG9ycyhpbml0UmVxdWlyZWRFeHRyYWN0b3JzLCBibG9jayk7XG4gICAgICB9XG4gICAgICB0aGlzLmV4dHJhY3RvcnMucHVzaCguLi50aGlzLm5ld0V4dHJhY3RvcnMpO1xuICAgICAgdGhpcy5uZXdFeHRyYWN0b3JzID0gW107XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHJlbGVhc2UoKTtcbiAgICB9XG4gIH07XG59XG4iXX0=
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { AbstractLogger } from '@rosen-bridge/abstract-logger';
|
|
2
|
+
import { Block } from '@rosen-bridge/scanner-interfaces';
|
|
3
|
+
import { Mutex } from '@rosen-bridge/semaphore';
|
|
4
|
+
import { AbstractScanner } from './scanner';
|
|
5
|
+
declare abstract class WebSocketScanner<TransactionType> extends AbstractScanner<TransactionType> {
|
|
6
|
+
protected scannerName: string;
|
|
7
|
+
protected suffix?: string | undefined;
|
|
8
|
+
readonly maxTryBlock: number;
|
|
9
|
+
protected mutex: Mutex;
|
|
10
|
+
protected constructor(scannerName: string, logger?: AbstractLogger, maxTryBlock?: number, suffix?: string | undefined);
|
|
11
|
+
name: () => string;
|
|
12
|
+
abstract start: () => Promise<void>;
|
|
13
|
+
abstract stop: () => Promise<void>;
|
|
14
|
+
protected tryRunningFunction: (fn: () => Promise<boolean>, msg: string, releaseMutex: () => void) => Promise<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* Handle new block arrived.
|
|
17
|
+
* save block and its transactions.
|
|
18
|
+
* @param block
|
|
19
|
+
* @param transactions
|
|
20
|
+
*/
|
|
21
|
+
protected stepForward: (block: Block, transactions: Array<TransactionType>) => Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Handle forking a block
|
|
24
|
+
* @param block
|
|
25
|
+
*/
|
|
26
|
+
protected stepBackward: (block: Block) => Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
export { WebSocketScanner };
|
|
29
|
+
//# sourceMappingURL=webSocketScanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webSocketScanner.d.ts","sourceRoot":"","sources":["../../../lib/scanner/abstract/webSocketScanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,MAAM,kCAAkC,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAI5C,uBAAe,gBAAgB,CAC7B,eAAe,CACf,SAAQ,eAAe,CAAC,eAAe,CAAC;IAMtC,SAAS,CAAC,WAAW,EAAE,MAAM;IAG7B,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM;IAR3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,SAAS,CAAC,KAAK,QAAe;IAE9B,SAAS,aACG,WAAW,EAAE,MAAM,EAC7B,MAAM,CAAC,EAAE,cAAc,EACvB,WAAW,GAAE,MAA8B,EACjC,MAAM,CAAC,EAAE,MAAM,YAAA;IAK3B,IAAI,eAAmE;IAEvE,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC,SAAS,CAAC,kBAAkB,GAC1B,IAAI,MAAM,OAAO,CAAC,OAAO,CAAC,EAC1B,KAAK,MAAM,EACX,cAAc,MAAM,IAAI,KACvB,OAAO,CAAC,OAAO,CAAC,CAWjB;IAEF;;;;;OAKG;IACH,SAAS,CAAC,WAAW,GACnB,OAAO,KAAK,EACZ,cAAc,KAAK,CAAC,eAAe,CAAC,mBAyCpC;IAEF;;;OAGG;IACH,SAAS,CAAC,YAAY,GAAU,OAAO,KAAK,mBAmB1C;CACH;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Mutex } from '@rosen-bridge/semaphore';
|
|
2
|
+
import { AbstractScanner } from './scanner';
|
|
3
|
+
const DEFAULT_MAX_TRY_BLOCK = 10;
|
|
4
|
+
class WebSocketScanner extends AbstractScanner {
|
|
5
|
+
scannerName;
|
|
6
|
+
suffix;
|
|
7
|
+
maxTryBlock;
|
|
8
|
+
mutex = new Mutex();
|
|
9
|
+
constructor(scannerName, logger, maxTryBlock = DEFAULT_MAX_TRY_BLOCK, suffix) {
|
|
10
|
+
super(logger);
|
|
11
|
+
this.scannerName = scannerName;
|
|
12
|
+
this.suffix = suffix;
|
|
13
|
+
this.maxTryBlock = maxTryBlock;
|
|
14
|
+
}
|
|
15
|
+
name = () => this.scannerName + (this.suffix ? `-${this.suffix}` : '');
|
|
16
|
+
tryRunningFunction = async (fn, msg, releaseMutex) => {
|
|
17
|
+
for (let tryRound = 1; tryRound <= this.maxTryBlock; tryRound++) {
|
|
18
|
+
if (await fn())
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
releaseMutex();
|
|
22
|
+
this.logger.error(`${msg} can not be proceed in ${this.maxTryBlock} try. scanner restarted automatically`);
|
|
23
|
+
await this.stop();
|
|
24
|
+
await this.start();
|
|
25
|
+
return false;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Handle new block arrived.
|
|
29
|
+
* save block and its transactions.
|
|
30
|
+
* @param block
|
|
31
|
+
* @param transactions
|
|
32
|
+
*/
|
|
33
|
+
stepForward = async (block, transactions) => {
|
|
34
|
+
const release = await this.mutex.acquire();
|
|
35
|
+
await this.tryRunningFunction(async () => {
|
|
36
|
+
try {
|
|
37
|
+
await this.forkBlock(block.height);
|
|
38
|
+
const lastSavedBlock = await this.action.getLastSavedBlock();
|
|
39
|
+
if (lastSavedBlock && block.parentHash !== lastSavedBlock.hash) {
|
|
40
|
+
this.logger.error('It seems saved block is not valid in scanner.');
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
await this.verifyExtractorsInitialization({
|
|
45
|
+
height: block.height - 1,
|
|
46
|
+
hash: block.parentHash,
|
|
47
|
+
});
|
|
48
|
+
const res = await this.processBlockTransactions(block, transactions);
|
|
49
|
+
if (res === false) {
|
|
50
|
+
this.logger.error(`Can not process block at height ${block.height}`);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
this.logger.warn(`unknown error occurred ${e}`);
|
|
59
|
+
if (e instanceof Error && e.stack) {
|
|
60
|
+
this.logger.warn(e.stack);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}, `Block at height ${block.height}`, release);
|
|
65
|
+
release();
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Handle forking a block
|
|
69
|
+
* @param block
|
|
70
|
+
*/
|
|
71
|
+
stepBackward = async (block) => {
|
|
72
|
+
const release = await this.mutex.acquire();
|
|
73
|
+
await this.tryRunningFunction(async () => {
|
|
74
|
+
try {
|
|
75
|
+
await this.forkBlock(block.height + 1);
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
this.logger.error(`unknown error occurred ${e}`);
|
|
80
|
+
if (e instanceof Error && e.stack) {
|
|
81
|
+
this.logger.warn(e.stack);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}, `Forking block at height ${block.height}`, release);
|
|
86
|
+
release();
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
export { WebSocketScanner };
|
|
90
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViU29ja2V0U2Nhbm5lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9zY2FubmVyL2Fic3RyYWN0L3dlYlNvY2tldFNjYW5uZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRWhELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFNUMsTUFBTSxxQkFBcUIsR0FBRyxFQUFFLENBQUM7QUFFakMsTUFBZSxnQkFFYixTQUFRLGVBQWdDO0lBTTVCO0lBR0E7SUFSSCxXQUFXLENBQVM7SUFFbkIsS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7SUFFOUIsWUFDWSxXQUFtQixFQUM3QixNQUF1QixFQUN2QixjQUFzQixxQkFBcUIsRUFDakMsTUFBZTtRQUV6QixLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7UUFMSixnQkFBVyxHQUFYLFdBQVcsQ0FBUTtRQUduQixXQUFNLEdBQU4sTUFBTSxDQUFTO1FBR3pCLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBQ2pDLENBQUM7SUFDRCxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUs3RCxrQkFBa0IsR0FBRyxLQUFLLEVBQ2xDLEVBQTBCLEVBQzFCLEdBQVcsRUFDWCxZQUF3QixFQUNOLEVBQUU7UUFDcEIsS0FBSyxJQUFJLFFBQVEsR0FBRyxDQUFDLEVBQUUsUUFBUSxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQztZQUNoRSxJQUFJLE1BQU0sRUFBRSxFQUFFO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1FBQzlCLENBQUM7UUFDRCxZQUFZ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SUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQ2xDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDNUIsQ0FBQztZQUNILENBQUM7WUFDRCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUMsRUFDRCwyQkFBMkIsS0FBSyxDQUFDLE1BQU0sRUFBRSxFQUN6QyxPQUFPLENBQ1IsQ0FBQztRQUNGLE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQyxDQUFDO0NBQ0g7QUFFRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFic3RyYWN0TG9nZ2VyIH0gZnJvbSAnQHJvc2VuLWJyaWRnZS9hYnN0cmFjdC1sb2dnZXInO1xuaW1wb3J0IHsgQmxvY2sgfSBmcm9tICdAcm9zZW4tYnJpZGdlL3NjYW5uZXItaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBNdXRleCB9IGZyb20gJ0Byb3Nlbi1icmlkZ2Uvc2VtYXBob3JlJztcblxuaW1wb3J0IHsgQWJzdHJhY3RTY2FubmVyIH0gZnJvbSAnLi9zY2FubmVyJztcblxuY29uc3QgREVGQVVMVF9NQVhfVFJZX0JMT0NLID0gMTA7XG5cbmFic3RyYWN0IGNsYXNzIFdlYlNvY2tldFNjYW5uZXI8XG4gIFRyYW5zYWN0aW9uVHlwZSxcbj4gZXh0ZW5kcyBBYnN0cmFjdFNjYW5uZXI8VHJhbnNhY3Rpb25UeXBlPiB7XG4gIHJlYWRvbmx5IG1heFRyeUJsb2NrOiBudW1iZXI7XG5cbiAgcHJvdGVjdGVkIG11dGV4ID0gbmV3IE11dGV4KCk7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBzY2FubmVyTmFtZTogc3RyaW5nLFxuICAgIGxvZ2dlcj86IEFic3RyYWN0TG9nZ2VyLFxuICAgIG1heFRyeUJsb2NrOiBudW1iZXIgPSBERUZBVUxUX01BWF9UUllfQkxPQ0ssXG4gICAgcHJvdGVjdGVkIHN1ZmZpeD86IHN0cmluZyxcbiAgKSB7XG4gICAgc3VwZXIobG9nZ2VyKTtcbiAgICB0aGlzLm1heFRyeUJsb2NrID0gbWF4VHJ5QmxvY2s7XG4gIH1cbiAgbmFtZSA9ICgpID0+IHRoaXMuc2Nhbm5lck5hbWUgKyAodGhpcy5zdWZmaXggPyBgLSR7dGhpcy5zdWZmaXh9YCA6ICcnKTtcblxuICBhYnN0cmFjdCBzdGFydDogKCkgPT4gUHJvbWlzZTx2b2lkPjtcbiAgYWJzdHJhY3Qgc3RvcDogKCkgPT4gUHJvbWlzZTx2b2lkPjtcblxuICBwcm90ZWN0ZWQgdHJ5UnVubmluZ0Z1bmN0aW9uID0gYXN5bmMgKFxuICAgIGZuOiAoKSA9PiBQcm9taXNlPGJvb2xlYW4+LFxuICAgIG1zZzogc3RyaW5nLFxuICAgIHJlbGVhc2VNdXRleDogKCkgPT4gdm9pZCxcbiAgKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gICAgZm9yIChsZXQgdHJ5Um91bmQgPSAxOyB0cnlSb3VuZCA8PSB0aGlzLm1heFRyeUJsb2NrOyB0cnlSb3VuZCsrKSB7XG4gICAgICBpZiAoYXdhaXQgZm4oKSkgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJlbGVhc2VNdXRleCgpO1xuICAgIHRoaXMubG9nZ2VyLmVycm9yKFxuICAgICAgYCR7bXNnfSBjYW4gbm90IGJlIHByb2NlZWQgaW4gJHt0aGlzLm1heFRyeUJsb2NrfSB0cnkuIHNjYW5uZXIgcmVzdGFydGVkIGF1dG9tYXRpY2FsbHlgLFxuICAgICk7XG4gICAgYXdhaXQgdGhpcy5zdG9wKCk7XG4gICAgYXdhaXQgdGhpcy5zdGFydCgpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcblxuICAvKipcbiAgICogSGFuZGxlIG5ldyBibG9jayBhcnJpdmVkLlxuICAgKiBzYXZlIGJsb2NrIGFuZCBpdHMgdHJhbnNhY3Rpb25zLlxuICAgKiBAcGFyYW0gYmxvY2tcbiAgICogQHBhcmFtIHRyYW5zYWN0aW9uc1xuICAgKi9cbiAgcHJvdGVjdGVkIHN0ZXBGb3J3YXJkID0gYXN5bmMgKFxuICAgIGJsb2NrOiBCbG9jayxcbiAgICB0cmFuc2FjdGlvbnM6IEFycmF5PFRyYW5zYWN0aW9uVHlwZT4sXG4gICkgPT4ge1xuICAgIGNvbnN0IHJlbGVhc2UgPSBhd2FpdCB0aGlzLm11dGV4LmFjcXVpcmUoKTtcbiAgICBhd2FpdCB0aGlzLnRyeVJ1bm5pbmdGdW5jdGlvbihcbiAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmZvcmtCbG9jayhibG9jay5oZWlnaHQpO1xuXG4gICAgICAgICAgY29uc3QgbGFzdFNhdmVkQmxvY2sgPSBhd2FpdCB0aGlzLmFjdGlvbi5nZXRMYXN0U2F2ZWRCbG9jaygpO1xuICAgICAgICAgIGlmIChsYXN0U2F2ZWRCbG9jayAmJiBibG9jay5wYXJlbnRIYXNoICE9PSBsYXN0U2F2ZWRCbG9jay5oYXNoKSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcignSXQgc2VlbXMgc2F2ZWQgYmxvY2sgaXMgbm90IHZhbGlkIGluIHNjYW5uZXIuJyk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMudmVyaWZ5RXh0cmFjdG9yc0luaXRpYWxpemF0aW9uKHtcbiAgICAgICAgICAgICAgaGVpZ2h0OiBibG9jay5oZWlnaHQgLSAxLFxuICAgICAgICAgICAgICBoYXNoOiBibG9jay5wYXJlbnRIYXNoLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLnByb2Nlc3NCbG9ja1RyYW5zYWN0aW9ucyhcbiAgICAgICAgICAgICAgYmxvY2ssXG4gICAgICAgICAgICAgIHRyYW5zYWN0aW9ucyxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAocmVzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgICBgQ2FuIG5vdCBwcm9jZXNzIGJsb2NrIGF0IGhlaWdodCAke2Jsb2NrLmhlaWdodH1gLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIud2FybihgdW5rbm93biBlcnJvciBvY2N1cnJlZCAke2V9YCk7XG4gICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBFcnJvciAmJiBlLnN0YWNrKSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKGUuc3RhY2spO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9LFxuICAgICAgYEJsb2NrIGF0IGhlaWdodCAke2Jsb2NrLmhlaWdodH1gLFxuICAgICAgcmVsZWFzZSxcbiAgICApO1xuICAgIHJlbGVhc2UoKTtcbiAgfTtcblxuICAvKipcbiAgICogSGFuZGxlIGZvcmtpbmcgYSBibG9ja1xuICAgKiBAcGFyYW0gYmxvY2tcbiAgICovXG4gIHByb3RlY3RlZCBzdGVwQmFja3dhcmQgPSBhc3luYyAoYmxvY2s6IEJsb2NrKSA9PiB7XG4gICAgY29uc3QgcmVsZWFzZSA9IGF3YWl0IHRoaXMubXV0ZXguYWNxdWlyZSgpO1xuICAgIGF3YWl0IHRoaXMudHJ5UnVubmluZ0Z1bmN0aW9uKFxuICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuZm9ya0Jsb2NrKGJsb2NrLmhlaWdodCArIDEpO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoYHVua25vd24gZXJyb3Igb2NjdXJyZWQgJHtlfWApO1xuICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgRXJyb3IgJiYgZS5zdGFjaykge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIud2FybihlLnN0YWNrKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSxcbiAgICAgIGBGb3JraW5nIGJsb2NrIGF0IGhlaWdodCAke2Jsb2NrLmhlaWdodH1gLFxuICAgICAgcmVsZWFzZSxcbiAgICApO1xuICAgIHJlbGVhc2UoKTtcbiAgfTtcbn1cblxuZXhwb3J0IHsgV2ViU29ja2V0U2Nhbm5lciB9O1xuIl19
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { AbstractLogger } from '@rosen-bridge/abstract-logger';
|
|
2
|
+
import { DataSource, DeleteResult, Repository } from '@rosen-bridge/extended-typeorm';
|
|
3
|
+
import { Block } from '@rosen-bridge/scanner-interfaces';
|
|
4
|
+
import { BlockEntity } from '../entities/blockEntity';
|
|
5
|
+
import { ExtractorStatusEntity } from '../entities/extractorStatusEntity';
|
|
6
|
+
export declare class BlockDbAction {
|
|
7
|
+
readonly blockRepository: Repository<BlockEntity>;
|
|
8
|
+
readonly extractorStatusRepository: Repository<ExtractorStatusEntity>;
|
|
9
|
+
readonly dataSource: DataSource;
|
|
10
|
+
readonly scannerName: string;
|
|
11
|
+
readonly logger: AbstractLogger;
|
|
12
|
+
constructor(dataSource: DataSource, scannerName: string, logger?: AbstractLogger);
|
|
13
|
+
readonly name: () => string;
|
|
14
|
+
/**
|
|
15
|
+
* get last saved block
|
|
16
|
+
* @return Promise<BlockEntity or undefined>
|
|
17
|
+
*/
|
|
18
|
+
getLastSavedBlock: () => Promise<BlockEntity | undefined>;
|
|
19
|
+
/**
|
|
20
|
+
* get last n stored blocks in database
|
|
21
|
+
* @param skip
|
|
22
|
+
* @param count
|
|
23
|
+
*/
|
|
24
|
+
getLastSavedBlocks: (skip: number, count: number) => Promise<Array<BlockEntity>>;
|
|
25
|
+
/**
|
|
26
|
+
* get first saved block
|
|
27
|
+
* @return Promise<BlockEntity or undefined>
|
|
28
|
+
*/
|
|
29
|
+
getFirstSavedBlock: () => Promise<BlockEntity | undefined>;
|
|
30
|
+
/**
|
|
31
|
+
* get block hash and height
|
|
32
|
+
* @param height
|
|
33
|
+
* @param status
|
|
34
|
+
* @return Promise<BlockEntity|undefined>
|
|
35
|
+
*/
|
|
36
|
+
getBlockAtHeight: (height: number, status?: string) => Promise<BlockEntity | undefined>;
|
|
37
|
+
/**
|
|
38
|
+
* get block with entered blockhash
|
|
39
|
+
* @param hash
|
|
40
|
+
* @param status
|
|
41
|
+
*/
|
|
42
|
+
getBlockWithHash: (hash: string, status?: string) => Promise<BlockEntity | null>;
|
|
43
|
+
/**
|
|
44
|
+
* it deletes every block that more than or equal height
|
|
45
|
+
* @param height
|
|
46
|
+
* @return Promise<DeleteResult>
|
|
47
|
+
*/
|
|
48
|
+
removeBlocksFromHeight: (height: number) => Promise<DeleteResult>;
|
|
49
|
+
/**
|
|
50
|
+
* store a block into database.
|
|
51
|
+
* @param block
|
|
52
|
+
*/
|
|
53
|
+
saveBlock: (block: Block) => Promise<BlockEntity | boolean>;
|
|
54
|
+
/**
|
|
55
|
+
* Update status of a block to proceed
|
|
56
|
+
* @param height: height of expected block
|
|
57
|
+
*/
|
|
58
|
+
updateBlockStatus: (height: number, blockHash: string, extractorIds: string[]) => Promise<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Update status of a block to processing in case of fork
|
|
61
|
+
* @param height: height of expected block
|
|
62
|
+
*/
|
|
63
|
+
revertBlockStatus: (height: number, parentHash: string, extractorIds: string[]) => Promise<boolean>;
|
|
64
|
+
/**
|
|
65
|
+
* Insert a newly initialized extractor or update an existing extractor status
|
|
66
|
+
* @param extractorId
|
|
67
|
+
* @param height
|
|
68
|
+
* @returns
|
|
69
|
+
*/
|
|
70
|
+
updateOrInsertExtractorStatus: (extractorId: string, height: number, blockHash: string) => Promise<{
|
|
71
|
+
scannerId: string;
|
|
72
|
+
extractorId: string;
|
|
73
|
+
updateHeight: number;
|
|
74
|
+
updateBlockHash: string;
|
|
75
|
+
} & ExtractorStatusEntity>;
|
|
76
|
+
/**
|
|
77
|
+
* Return extractors` status specified by id
|
|
78
|
+
* @param extractorIds
|
|
79
|
+
* @returns extractors` status
|
|
80
|
+
*/
|
|
81
|
+
getExtractorsStatus: (extractorIds: string[]) => Promise<ExtractorStatusEntity[]>;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=action.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../lib/scanner/action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAe,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EACL,UAAU,EACV,YAAY,EAEZ,UAAU,EAEX,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,kCAAkC,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAuB,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE1E,qBAAa,aAAa;IACxB,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IAClD,QAAQ,CAAC,yBAAyB,EAAE,UAAU,CAAC,qBAAqB,CAAC,CAAC;IACtE,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;gBAG9B,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,cAAc;IAWzB,QAAQ,CAAC,IAAI,eAA0B;IAEvC;;;OAGG;IACH,iBAAiB,QAAa,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAW5D;IAEF;;;;OAIG;IACH,kBAAkB,GAChB,MAAM,MAAM,EACZ,OAAO,MAAM,KACZ,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAO5B;IAEF;;;OAGG;IACH,kBAAkB,QAAa,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAW7D;IAEF;;;;;OAKG;IACH,gBAAgB,GACd,QAAQ,MAAM,EACd,SAAQ,MAAgB,KACvB,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAWjC;IAEF;;;;OAIG;IACH,gBAAgB,GAAU,MAAM,MAAM,EAAE,SAAQ,MAAgB,iCAM9D;IAEF;;;;OAIG;IACH,sBAAsB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,YAAY,CAAC,CAMpE;IAEF;;;OAGG;IACH,SAAS,GAAU,OAAO,KAAK,KAAG,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC,CA0C9D;IAEF;;;OAGG;IACH,iBAAiB,GACf,QAAQ,MAAM,EACd,WAAW,MAAM,EACjB,cAAc,MAAM,EAAE,KACrB,OAAO,CAAC,OAAO,CAAC,CAqCjB;IAEF;;;OAGG;IACH,iBAAiB,GACf,QAAQ,MAAM,EACd,YAAY,MAAM,EAClB,cAAc,MAAM,EAAE,KACrB,OAAO,CAAC,OAAO,CAAC,CAsCjB;IAEF;;;;;OAKG;IACH,6BAA6B,GAC3B,aAAa,MAAM,EACnB,QAAQ,MAAM,EACd,WAAW,MAAM;;;;;+BAgBjB;IAEF;;;;OAIG;IACH,mBAAmB,GACjB,cAAc,MAAM,EAAE,KACrB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAKjC;CACH"}
|