tovarish-relayer/lib/services/events.js

740 lines
27 KiB
JavaScript
Raw Permalink Normal View History

2024-11-13 04:42:13 +03:00
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
2024-11-19 13:22:27 +03:00
exports.NodeRevenueService = exports.NodeRegistryService = exports.NodeGovernanceService = exports.NodeEncryptedNotesService = exports.NodeEchoService = exports.NodeMultiTornadoService = exports.NodeTornadoService = exports.NodeTransactionsService = exports.NodeBlocksService = exports.NodeEventsService = void 0;
2024-11-13 04:42:13 +03:00
const path_1 = __importDefault(require("path"));
const promises_1 = require("fs/promises");
const core_1 = require("@tornado/core");
2024-11-19 13:22:27 +03:00
const contracts_1 = require("@tornado/contracts");
2024-11-13 04:42:13 +03:00
const data_1 = require("./data");
class NodeEventsService extends core_1.BatchEventsService {
netId;
logger;
getInstanceName;
constructor(serviceConstructor) {
super(serviceConstructor);
this.netId = serviceConstructor.netId;
this.logger = serviceConstructor.logger;
this.getInstanceName = serviceConstructor.getInstanceName;
}
}
exports.NodeEventsService = NodeEventsService;
2024-11-19 13:22:27 +03:00
class NodeBlocksService extends core_1.BatchBlockService {
netId;
logger;
getInstanceName;
constructor(serviceConstructor) {
super(serviceConstructor);
this.netId = serviceConstructor.netId;
this.logger = serviceConstructor.logger;
this.getInstanceName = serviceConstructor.getInstanceName;
}
}
exports.NodeBlocksService = NodeBlocksService;
class NodeTransactionsService extends core_1.BatchTransactionService {
netId;
logger;
getInstanceName;
constructor(serviceConstructor) {
super(serviceConstructor);
this.netId = serviceConstructor.netId;
this.logger = serviceConstructor.logger;
this.getInstanceName = serviceConstructor.getInstanceName;
}
}
exports.NodeTransactionsService = NodeTransactionsService;
2024-11-13 04:42:13 +03:00
class NodeTornadoService extends core_1.BaseTornadoService {
cacheDirectory;
userDirectory;
nativeCurrency;
logger;
treeCache;
constructor(serviceConstructor) {
super(serviceConstructor);
const { netId, provider, Tornado, type, amount, currency, cacheDirectory, userDirectory, nativeCurrency, logger, treeCache, } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
this.nativeCurrency = nativeCurrency;
this.logger = logger;
this.batchEventsService = new NodeEventsService({
netId,
provider,
contract: Tornado,
onProgress: this.updateEventProgress,
logger,
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
});
2024-11-19 13:22:27 +03:00
this.batchTransactionService = new NodeTransactionsService({
netId,
provider,
onProgress: this.updateTransactionProgress,
logger,
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
});
this.batchBlockService = new NodeBlocksService({
netId,
provider,
onProgress: this.updateBlockProgress,
logger,
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
});
2024-11-13 04:42:13 +03:00
this.treeCache = treeCache;
}
updateEventProgress({ fromBlock, toBlock, count }) {
if (toBlock) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
}
}
2024-11-19 13:22:27 +03:00
updateTransactionProgress({ currentIndex, totalIndex }) {
if (totalIndex) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} deposit txs of ${totalIndex}`);
}
}
updateBlockProgress({ currentIndex, totalIndex }) {
if (totalIndex) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} withdrawal blocks of ${totalIndex}`);
}
}
2024-11-13 04:42:13 +03:00
async getEventsFromDB() {
return await (0, data_1.loadSavedEvents)({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
}
async getEventsFromCache() {
return await (0, data_1.loadCachedEvents)({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
}
2024-11-19 13:22:27 +03:00
async validateEvents({ events, newEvents, lastBlock, }) {
2024-11-13 04:42:13 +03:00
const tree = await super.validateEvents({
events,
2024-11-19 13:22:27 +03:00
newEvents,
2024-11-13 04:42:13 +03:00
lastBlock,
});
if (tree && this.currency === this.nativeCurrency && this.treeCache) {
const merkleTree = tree;
2024-11-19 13:22:27 +03:00
await this.treeCache.createTree({
netId: this.netId,
amount: this.amount,
currency: this.currency,
events: events,
tree: tree,
});
2024-11-13 04:42:13 +03:00
console.log(`${this.getInstanceName()}: Updated tree cache with root ${(0, core_1.toFixedHex)(BigInt(merkleTree.root))}\n`);
}
return tree;
}
async saveEvents({ events, lastBlock }) {
await (0, data_1.saveUserFile)({
fileName: this.getInstanceName() + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
lastBlock,
});
}
async updateEvents() {
const { events, lastBlock, validateResult } = await super.updateEvents();
await (0, data_1.saveLastBlock)({
fileName: this.getInstanceName(),
userDirectory: this.userDirectory,
lastBlock,
});
return {
events,
lastBlock,
validateResult,
};
}
}
exports.NodeTornadoService = NodeTornadoService;
2024-11-19 13:22:27 +03:00
class NodeMultiTornadoService extends core_1.BaseMultiTornadoService {
cacheDirectory;
userDirectory;
nativeCurrency;
logger;
treeCache;
constructor(serviceConstructor) {
super(serviceConstructor);
const { netId, provider, cacheDirectory, userDirectory, nativeCurrency, logger, treeCache } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
this.nativeCurrency = nativeCurrency;
this.logger = logger;
this.batchEventsService = new NodeEventsService({
netId,
provider,
contract: this.contract,
address: Object.keys(this.instances),
onProgress: this.updateEventProgress,
logger,
getInstanceName: this.getInstanceName,
});
this.batchTransactionService = new NodeTransactionsService({
netId,
provider,
onProgress: this.updateTransactionProgress,
logger,
getInstanceName: this.getInstanceName,
});
this.batchBlockService = new NodeBlocksService({
netId,
provider,
onProgress: this.updateBlockProgress,
logger,
getInstanceName: this.getInstanceName,
});
this.treeCache = treeCache;
}
updateEventProgress({ fromBlock, toBlock, count }) {
if (toBlock) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
}
}
updateTransactionProgress({ currentIndex, totalIndex }) {
if (totalIndex) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} deposit txs of ${totalIndex}`);
}
}
updateBlockProgress({ currentIndex, totalIndex }) {
if (totalIndex) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} withdrawal blocks of ${totalIndex}`);
}
}
async getEventsFromDB() {
return await (0, data_1.loadSavedEvents)({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
}
async getEventsFromCache() {
return await (0, data_1.loadCachedEvents)({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
}
async validateEvents({ events, newEvents, lastBlock, }) {
const tree = await super.validateEvents({
events,
newEvents,
lastBlock,
});
if (this.merkleTreeService && this.treeCache) {
const instancesWithNewEvents = [
...new Set(newEvents.filter(({ event }) => event === 'Deposit').map(({ instanceAddress }) => instanceAddress)),
];
for (const instance of instancesWithNewEvents) {
const { amount, currency } = this.instances[instance];
// Only create cached tree for native currencies
if (currency !== this.nativeCurrency) {
continue;
}
const depositEvents = events.filter(({ instanceAddress, event }) => instanceAddress === instance && event === 'Deposit');
// Create tree cache with existing tree
if (tree && this.merkleTreeService.Tornado.target === instance) {
await this.treeCache.createTree({
netId: this.netId,
amount,
currency,
events: depositEvents,
tree: tree,
});
// Create new tree cache
}
else {
const merkleTreeService = new core_1.MerkleTreeService({
netId: this.netId,
amount,
currency,
Tornado: contracts_1.Tornado__factory.connect(instance, this.provider),
merkleWorkerPath: this.merkleTreeService.merkleWorkerPath,
});
const tree = await merkleTreeService.verifyTree(depositEvents);
await this.treeCache.createTree({
netId: this.netId,
amount,
currency,
events: depositEvents,
tree,
});
}
}
}
return tree;
}
async saveEvents({ events, newEvents, lastBlock, }) {
const instancesWithNewEvents = [...new Set(newEvents.map(({ instanceAddress }) => instanceAddress))];
for (const instance of instancesWithNewEvents) {
const { currency, amount } = this.instances[instance];
const { depositEvents, withdrawalEvents } = events.reduce((acc, curr) => {
if (curr.instanceAddress === instance) {
if (curr.event === 'Deposit') {
acc.depositEvents.push({
...curr,
event: undefined,
instanceAddress: undefined,
});
}
else if (curr.event === 'Withdrawal') {
acc.withdrawalEvents.push({
...curr,
event: undefined,
instanceAddress: undefined,
relayerAddress: undefined,
});
}
}
return acc;
}, {
depositEvents: [],
withdrawalEvents: [],
});
await (0, promises_1.writeFile)(path_1.default.join(this.userDirectory, `recent_deposits_${this.netId}_${currency}_${amount}.json`), JSON.stringify(depositEvents.slice(depositEvents.length - 10).reverse(), null, 2) + '\n');
await (0, data_1.saveUserFile)({
fileName: `deposits_${this.netId}_${currency}_${amount}.json`,
userDirectory: this.userDirectory,
dataString: JSON.stringify(depositEvents, null, 2) + '\n',
lastBlock,
});
await (0, data_1.saveUserFile)({
fileName: `withdrawals_${this.netId}_${currency}_${amount}.json`,
userDirectory: this.userDirectory,
dataString: JSON.stringify(withdrawalEvents, null, 2) + '\n',
lastBlock,
});
console.log(`\nSaved ${this.netId}_${currency}_${amount}.json event: ` +
`${depositEvents.length} deposits ${withdrawalEvents.length} withdrawals\n`);
}
await (0, data_1.saveUserFile)({
fileName: this.getInstanceName() + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
lastBlock,
});
}
async updateEvents() {
const { events, lastBlock, validateResult } = await super.updateEvents();
await (0, data_1.saveLastBlock)({
fileName: this.getInstanceName(),
userDirectory: this.userDirectory,
lastBlock,
});
return {
events,
lastBlock,
validateResult,
};
}
}
exports.NodeMultiTornadoService = NodeMultiTornadoService;
2024-11-13 04:42:13 +03:00
class NodeEchoService extends core_1.BaseEchoService {
cacheDirectory;
userDirectory;
logger;
constructor(serviceConstructor) {
super(serviceConstructor);
const { netId, provider, Echoer, cacheDirectory, userDirectory, logger } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
this.logger = logger;
this.batchEventsService = new NodeEventsService({
netId,
provider,
contract: Echoer,
onProgress: this.updateEventProgress,
logger,
getInstanceName: this.getInstanceName,
});
}
updateEventProgress({ fromBlock, toBlock, count }) {
if (toBlock) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
}
}
async getEventsFromDB() {
return await (0, data_1.loadSavedEvents)({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
}
async getEventsFromCache() {
return await (0, data_1.loadCachedEvents)({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
}
async saveEvents({ events, lastBlock }) {
const instanceName = this.getInstanceName();
await (0, data_1.saveUserFile)({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
lastBlock,
});
}
async updateEvents() {
const { events, lastBlock, validateResult } = await super.updateEvents();
await (0, data_1.saveLastBlock)({
fileName: this.getInstanceName(),
userDirectory: this.userDirectory,
lastBlock,
});
return {
events,
lastBlock,
validateResult,
};
}
}
exports.NodeEchoService = NodeEchoService;
class NodeEncryptedNotesService extends core_1.BaseEncryptedNotesService {
cacheDirectory;
userDirectory;
logger;
constructor(serviceConstructor) {
super(serviceConstructor);
const { netId, provider, Router, cacheDirectory, userDirectory, logger } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
this.logger = logger;
this.batchEventsService = new NodeEventsService({
netId,
provider,
contract: Router,
onProgress: this.updateEventProgress,
logger,
getInstanceName: this.getInstanceName,
});
}
updateEventProgress({ fromBlock, toBlock, count }) {
if (toBlock) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
}
}
async getEventsFromDB() {
return await (0, data_1.loadSavedEvents)({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
}
async getEventsFromCache() {
return await (0, data_1.loadCachedEvents)({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
}
async saveEvents({ events, lastBlock }) {
const instanceName = this.getInstanceName();
await (0, data_1.saveUserFile)({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
lastBlock,
});
}
async updateEvents() {
const { events, lastBlock, validateResult } = await super.updateEvents();
await (0, data_1.saveLastBlock)({
fileName: this.getInstanceName(),
userDirectory: this.userDirectory,
lastBlock,
});
return {
events,
lastBlock,
validateResult,
};
}
}
exports.NodeEncryptedNotesService = NodeEncryptedNotesService;
class NodeGovernanceService extends core_1.BaseGovernanceService {
cacheDirectory;
userDirectory;
logger;
constructor(serviceConstructor) {
super(serviceConstructor);
const { netId, provider, Governance, cacheDirectory, userDirectory, logger } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
this.logger = logger;
this.batchEventsService = new NodeEventsService({
netId,
provider,
contract: Governance,
onProgress: this.updateEventProgress,
logger,
getInstanceName: this.getInstanceName,
});
2024-11-19 13:22:27 +03:00
this.batchTransactionService = new NodeTransactionsService({
netId,
provider,
onProgress: this.updateTransactionProgress,
logger,
getInstanceName: this.getInstanceName,
});
2024-11-13 04:42:13 +03:00
}
updateEventProgress({ fromBlock, toBlock, count }) {
if (toBlock) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
}
}
2024-11-19 13:22:27 +03:00
updateTransactionProgress({ currentIndex, totalIndex }) {
if (totalIndex) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} governance txs of ${totalIndex}`);
}
}
2024-11-13 04:42:13 +03:00
async getEventsFromDB() {
return await (0, data_1.loadSavedEvents)({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
}
async getEventsFromCache() {
return await (0, data_1.loadCachedEvents)({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
}
async saveEvents({ events, lastBlock }) {
const instanceName = this.getInstanceName();
await (0, data_1.saveUserFile)({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
lastBlock,
});
}
async updateEvents() {
const { events, lastBlock, validateResult } = await super.updateEvents();
await (0, data_1.saveLastBlock)({
fileName: this.getInstanceName(),
userDirectory: this.userDirectory,
lastBlock,
});
return {
events,
lastBlock,
validateResult,
};
}
}
exports.NodeGovernanceService = NodeGovernanceService;
class NodeRegistryService extends core_1.BaseRegistryService {
cacheDirectory;
userDirectory;
logger;
constructor(serviceConstructor) {
super(serviceConstructor);
const { netId, provider, RelayerRegistry, cacheDirectory, userDirectory, logger } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
this.logger = logger;
this.batchEventsService = new NodeEventsService({
netId,
provider,
contract: RelayerRegistry,
onProgress: this.updateEventProgress,
logger,
getInstanceName: this.getInstanceName,
});
}
updateEventProgress({ fromBlock, toBlock, count }) {
if (toBlock) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
}
}
async getEventsFromDB() {
return await (0, data_1.loadSavedEvents)({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
}
async getEventsFromCache() {
return await (0, data_1.loadCachedEvents)({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
}
async saveEvents({ events, lastBlock }) {
const instanceName = this.getInstanceName();
await (0, data_1.saveUserFile)({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
lastBlock,
});
}
async updateEvents() {
const { events, lastBlock, validateResult } = await super.updateEvents();
await (0, data_1.saveLastBlock)({
fileName: this.getInstanceName(),
userDirectory: this.userDirectory,
lastBlock,
});
return {
events,
lastBlock,
validateResult,
};
}
async getRelayersFromDB() {
const filePath = path_1.default.join(this.userDirectory || '', 'relayers.json');
if (!this.userDirectory || !(await (0, data_1.existsAsync)(filePath))) {
return {
lastBlock: 0,
timestamp: 0,
relayers: [],
};
}
try {
const { lastBlock, timestamp, relayers } = JSON.parse(await (0, promises_1.readFile)(filePath, { encoding: 'utf8' }));
return {
lastBlock,
timestamp,
relayers,
};
}
catch (err) {
console.log('Method getRelayersFromDB has error');
console.log(err);
return {
lastBlock: 0,
timestamp: 0,
relayers: [],
};
}
}
async getRelayersFromCache() {
const filePath = path_1.default.join(this.cacheDirectory || '', 'relayers.json');
if (!this.cacheDirectory || !(await (0, data_1.existsAsync)(filePath))) {
return {
lastBlock: 0,
timestamp: 0,
relayers: [],
fromCache: true,
};
}
try {
const { lastBlock, timestamp, relayers } = JSON.parse(await (0, promises_1.readFile)(filePath, { encoding: 'utf8' }));
return {
lastBlock,
timestamp,
relayers,
fromCache: true,
};
}
catch (err) {
console.log('Method getRelayersFromDB has error');
console.log(err);
return {
lastBlock: 0,
timestamp: 0,
relayers: [],
fromCache: true,
};
}
}
async saveRelayers({ lastBlock, timestamp, relayers }) {
await (0, data_1.saveUserFile)({
fileName: 'relayers.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify({ lastBlock, timestamp, relayers }, null, 2) + '\n',
});
}
}
exports.NodeRegistryService = NodeRegistryService;
class NodeRevenueService extends core_1.BaseRevenueService {
cacheDirectory;
userDirectory;
logger;
constructor(serviceConstructor) {
super(serviceConstructor);
const { netId, provider, RelayerRegistry, cacheDirectory, userDirectory, logger } = serviceConstructor;
this.cacheDirectory = cacheDirectory;
this.userDirectory = userDirectory;
this.logger = logger;
this.batchEventsService = new NodeEventsService({
netId,
provider,
contract: RelayerRegistry,
onProgress: this.updateEventProgress,
logger,
getInstanceName: this.getInstanceName,
});
2024-11-19 13:22:27 +03:00
this.batchTransactionService = new NodeTransactionsService({
netId,
provider,
onProgress: this.updateTransactionProgress,
logger,
getInstanceName: this.getInstanceName,
});
this.batchBlockService = new NodeBlocksService({
netId,
provider,
onProgress: this.updateBlockProgress,
logger,
getInstanceName: this.getInstanceName,
});
2024-11-13 04:42:13 +03:00
}
updateEventProgress({ fromBlock, toBlock, count }) {
if (toBlock) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
}
}
2024-11-19 13:22:27 +03:00
updateTransactionProgress({ currentIndex, totalIndex }) {
if (totalIndex) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} txs of ${totalIndex}`);
}
}
updateBlockProgress({ currentIndex, totalIndex }) {
if (totalIndex) {
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} blocks of ${totalIndex}`);
}
}
2024-11-13 04:42:13 +03:00
async getEventsFromDB() {
return await (0, data_1.loadSavedEvents)({
name: this.getInstanceName(),
userDirectory: this.userDirectory,
});
}
async getEventsFromCache() {
return await (0, data_1.loadCachedEvents)({
name: this.getInstanceName(),
cacheDirectory: this.cacheDirectory,
deployedBlock: this.deployedBlock,
});
}
async saveEvents({ events, lastBlock }) {
const instanceName = this.getInstanceName();
await (0, data_1.saveUserFile)({
fileName: instanceName + '.json',
userDirectory: this.userDirectory,
dataString: JSON.stringify(events, null, 2) + '\n',
lastBlock,
});
}
async updateEvents() {
const { events, lastBlock, validateResult } = await super.updateEvents();
await (0, data_1.saveLastBlock)({
fileName: this.getInstanceName(),
userDirectory: this.userDirectory,
lastBlock,
});
return {
events,
lastBlock,
validateResult,
};
}
}
exports.NodeRevenueService = NodeRevenueService;