From aa74c384165e46eeafec1c6aa0a6571a5369411c Mon Sep 17 00:00:00 2001 From: Eddort Date: Mon, 28 Oct 2024 16:01:43 +0100 Subject: [PATCH 01/11] feat: add cache to keysAPI service --- src/guardian/guardian.service.ts | 2 +- src/keys-api/keys-api.service.ts | 52 ++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/guardian/guardian.service.ts b/src/guardian/guardian.service.ts index 727e9121..74607b54 100644 --- a/src/guardian/guardian.service.ts +++ b/src/guardian/guardian.service.ts @@ -177,7 +177,7 @@ export class GuardianService implements OnModuleInit { // fetch all lido keys const { data: lidoKeys, meta: secondRequestMeta } = - await this.keysApiService.getKeys(); + await this.keysApiService.getKeys(firstRequestMeta); endTimerKeysReq(); diff --git a/src/keys-api/keys-api.service.ts b/src/keys-api/keys-api.service.ts index 5e23af7c..01d2f628 100644 --- a/src/keys-api/keys-api.service.ts +++ b/src/keys-api/keys-api.service.ts @@ -8,9 +8,11 @@ import { Configuration } from 'common/config'; import { GroupedByModuleOperatorListResponse } from './interfaces/GroupedByModuleOperatorListResponse'; import { InconsistentLastChangedBlockHash } from 'common/custom-errors'; import { SRModuleListResponse } from './interfaces/SRModuleListResponse'; +import { ELBlockSnapshot } from './interfaces/ELBlockSnapshot'; @Injectable() export class KeysApiService { + private cachedKeys?: KeyListResponse; constructor( @Inject(WINSTON_MODULE_NEST_PROVIDER) protected logger: LoggerService, protected readonly config: Configuration, @@ -85,10 +87,56 @@ export class KeysApiService { } /** - * The /v1/keys endpoint returns full list of keys + * Retrieves keys, using cache if valid. + * @param elBlockSnapshot ELBlockSnapshot with the current block hash for cache validation. + * @returns Cached or newly fetched keys. */ - public async getKeys() { + public async getKeys(elBlockSnapshot: ELBlockSnapshot) { + if (!this.cachedKeys) { + return this.updateCachedKeys(elBlockSnapshot); + } + + const { lastChangedBlockHash: cachedHash } = + this.cachedKeys.meta.elBlockSnapshot; + const { lastChangedBlockHash: currentHash } = elBlockSnapshot; + + if (cachedHash !== currentHash) { + return this.updateCachedKeys(elBlockSnapshot); + } + + this.logger.debug?.( + 'Keys are obtained from cache, no data update required', + { + elBlockSnapshot, + cachedELBlockSnapshot: this.cachedKeys.meta.elBlockSnapshot, + }, + ); + return this.cachedKeys; + } + + /** + * Fetches new keys from the /v1/keys endpoint and updates cache. + * @returns The newly fetched keys. + */ + private async updateCachedKeys(elBlockSnapshot: ELBlockSnapshot) { + this.logger.log('Updating keys from KeysAPI', { + elBlockSnapshot, + previousELBlockSnapshot: this.cachedKeys?.meta.elBlockSnapshot, + }); + const result = await this.fetch(`/v1/keys`); + + this.logger.log('Keys successfully updated from KeysAPI', { + elBlockSnapshot, + newELBlockSnapshot: result.meta.elBlockSnapshot, + }); + + this.verifyMetaDataConsistency( + elBlockSnapshot.lastChangedBlockHash, + result.meta.elBlockSnapshot.lastChangedBlockHash, + ); + + this.cachedKeys = result; return result; } From 0429aab1ee96f712d68ef887899c66787720e739 Mon Sep 17 00:00:00 2001 From: Eddort Date: Mon, 28 Oct 2024 16:22:43 +0100 Subject: [PATCH 02/11] feat: immutable keys list --- src/common/ts-utils.ts | 4 ++++ .../duplicates/keys-duplication-checker.service.ts | 7 +++++-- src/guardian/guardian.service.ts | 13 ++++--------- src/keys-api/keys-api.service.ts | 4 +++- .../staking-module-data-collector.service.ts | 7 ++++--- 5 files changed, 20 insertions(+), 15 deletions(-) create mode 100644 src/common/ts-utils.ts diff --git a/src/common/ts-utils.ts b/src/common/ts-utils.ts new file mode 100644 index 00000000..2cc77dc7 --- /dev/null +++ b/src/common/ts-utils.ts @@ -0,0 +1,4 @@ +/* eslint-disable @typescript-eslint/ban-types */ +export type DeepReadonly = { + readonly [P in keyof T]: T[P] extends Function ? T[P] : DeepReadonly; +}; diff --git a/src/guardian/duplicates/keys-duplication-checker.service.ts b/src/guardian/duplicates/keys-duplication-checker.service.ts index a909b850..29d7dc2f 100644 --- a/src/guardian/duplicates/keys-duplication-checker.service.ts +++ b/src/guardian/duplicates/keys-duplication-checker.service.ts @@ -1,4 +1,5 @@ import { Inject, Injectable, LoggerService } from '@nestjs/common'; +import { DeepReadonly } from 'common/ts-utils'; import { SigningKeyEvent, SigningKeyEventsGroupWithStakingModules, @@ -37,7 +38,7 @@ export class KeysDuplicationCheckerService { * - `unresolved`: An array of `RegistryKey` objects for which no corresponding events were found. */ public async getDuplicatedKeys( - keys: RegistryKey[], + keys: DeepReadonly, blockData: BlockData, ): Promise<{ duplicates: RegistryKey[]; unresolved: RegistryKey[] }> { if (keys.length === 0) { @@ -79,7 +80,9 @@ export class KeysDuplicationCheckerService { * @returns An array of tuples where each tuple contains a pubkey string and an array of * `RegistryKey` objects that share that pubkey. Only keys with duplicates are included. */ - public getDuplicateKeyGroups(keys: RegistryKey[]): [string, RegistryKey[]][] { + public getDuplicateKeyGroups( + keys: DeepReadonly, + ): [string, RegistryKey[]][] { const keyMap = keys.reduce((acc, key) => { const duplicateKeys = acc.get(key.key) || []; duplicateKeys.push(key); diff --git a/src/guardian/guardian.service.ts b/src/guardian/guardian.service.ts index 74607b54..f0866634 100644 --- a/src/guardian/guardian.service.ts +++ b/src/guardian/guardian.service.ts @@ -39,6 +39,7 @@ import { SigningKeysRegistryService } from 'contracts/signing-keys-registry'; import { InjectMetric } from '@willsoto/nestjs-prometheus'; import { METRIC_JOB_DURATION } from 'common/prometheus'; import { Histogram } from 'prom-client'; +import { DeepReadonly } from 'common/ts-utils'; @Injectable() export class GuardianService implements OnModuleInit { @@ -181,12 +182,6 @@ export class GuardianService implements OnModuleInit { endTimerKeysReq(); - // check that there were no updates in Keys Api between two requests - this.keysApiService.verifyMetaDataConsistency( - firstRequestMeta.lastChangedBlockHash, - secondRequestMeta.elBlockSnapshot.lastChangedBlockHash, - ); - // contracts initialization await this.repositoryService.initCachedContracts({ blockHash }); @@ -230,7 +225,7 @@ export class GuardianService implements OnModuleInit { private async collectData( stakingModules: SRModule[], meta: ELBlockSnapshot, - lidoKeys: RegistryKey[], + lidoKeys: DeepReadonly, ) { const { blockHash, blockNumber } = meta; @@ -265,7 +260,7 @@ export class GuardianService implements OnModuleInit { private async handleKeys( stakingModulesData: StakingModuleData[], blockData: BlockData, - lidoKeys: RegistryKey[], + lidoKeys: DeepReadonly, ) { // check lido keys await this.checkKeys(stakingModulesData, blockData, lidoKeys); @@ -299,7 +294,7 @@ export class GuardianService implements OnModuleInit { private async checkKeys( stakingModulesData: StakingModuleData[], blockData: BlockData, - lidoKeys: RegistryKey[], + lidoKeys: DeepReadonly, ) { const stakingRouterModuleAddresses = stakingModulesData.map( (stakingModule) => stakingModule.stakingModuleAddress, diff --git a/src/keys-api/keys-api.service.ts b/src/keys-api/keys-api.service.ts index 01d2f628..9928179a 100644 --- a/src/keys-api/keys-api.service.ts +++ b/src/keys-api/keys-api.service.ts @@ -9,10 +9,11 @@ import { GroupedByModuleOperatorListResponse } from './interfaces/GroupedByModul import { InconsistentLastChangedBlockHash } from 'common/custom-errors'; import { SRModuleListResponse } from './interfaces/SRModuleListResponse'; import { ELBlockSnapshot } from './interfaces/ELBlockSnapshot'; +import { DeepReadonly } from 'common/ts-utils'; @Injectable() export class KeysApiService { - private cachedKeys?: KeyListResponse; + private cachedKeys?: DeepReadonly; constructor( @Inject(WINSTON_MODULE_NEST_PROVIDER) protected logger: LoggerService, protected readonly config: Configuration, @@ -131,6 +132,7 @@ export class KeysApiService { newELBlockSnapshot: result.meta.elBlockSnapshot, }); + // check that there were no updates in Keys Api between two requests this.verifyMetaDataConsistency( elBlockSnapshot.lastChangedBlockHash, result.meta.elBlockSnapshot.lastChangedBlockHash, diff --git a/src/staking-module-data-collector/staking-module-data-collector.service.ts b/src/staking-module-data-collector/staking-module-data-collector.service.ts index 85de4ccd..afd1ee38 100644 --- a/src/staking-module-data-collector/staking-module-data-collector.service.ts +++ b/src/staking-module-data-collector/staking-module-data-collector.service.ts @@ -11,11 +11,12 @@ import { ELBlockSnapshot } from 'keys-api/interfaces/ELBlockSnapshot'; import { METRIC_JOB_DURATION } from 'common/prometheus'; import { InjectMetric } from '@willsoto/nestjs-prometheus'; import { Histogram } from 'prom-client'; +import { DeepReadonly } from 'common/ts-utils'; type State = { stakingModules: SRModule[]; meta: ELBlockSnapshot; - lidoKeys: RegistryKey[]; + lidoKeys: DeepReadonly; }; @Injectable() @@ -71,7 +72,7 @@ export class StakingModuleDataCollectorService { */ public async checkKeys( stakingModulesData: StakingModuleData[], - lidoKeys: RegistryKey[], + lidoKeys: DeepReadonly, blockData: BlockData, ): Promise { const endTimerDuplicates = this.jobDurationMetric @@ -203,7 +204,7 @@ export class StakingModuleDataCollectorService { private getModuleVettedUnusedKeys( stakingModuleAddress: string, - lidoKeys: RegistryKey[], + lidoKeys: DeepReadonly, ) { const vettedUnusedKeys = lidoKeys.filter( (key) => From 5534b2e56cf3e7a75421706448d67e3eb7098457 Mon Sep 17 00:00:00 2001 From: Eddort Date: Mon, 28 Oct 2024 16:45:23 +0100 Subject: [PATCH 03/11] fix: code review --- src/keys-api/keys-api.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/keys-api/keys-api.service.ts b/src/keys-api/keys-api.service.ts index 9928179a..a90aaad1 100644 --- a/src/keys-api/keys-api.service.ts +++ b/src/keys-api/keys-api.service.ts @@ -122,12 +122,12 @@ export class KeysApiService { private async updateCachedKeys(elBlockSnapshot: ELBlockSnapshot) { this.logger.log('Updating keys from KeysAPI', { elBlockSnapshot, - previousELBlockSnapshot: this.cachedKeys?.meta.elBlockSnapshot, + cachedELBlockSnapshot: this.cachedKeys?.meta.elBlockSnapshot, }); const result = await this.fetch(`/v1/keys`); - this.logger.log('Keys successfully updated from KeysAPI', { + this.logger.log('Keys successfully updated in cache from KeysAPI', { elBlockSnapshot, newELBlockSnapshot: result.meta.elBlockSnapshot, }); From 159ab96590a4239fe5b35445a163c3322dc1cda8 Mon Sep 17 00:00:00 2001 From: Eddort Date: Mon, 28 Oct 2024 16:51:02 +0100 Subject: [PATCH 04/11] fix: eslint --- src/guardian/guardian.service.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/guardian/guardian.service.ts b/src/guardian/guardian.service.ts index f0866634..7ecaec57 100644 --- a/src/guardian/guardian.service.ts +++ b/src/guardian/guardian.service.ts @@ -177,8 +177,9 @@ export class GuardianService implements OnModuleInit { .startTimer(); // fetch all lido keys - const { data: lidoKeys, meta: secondRequestMeta } = - await this.keysApiService.getKeys(firstRequestMeta); + const { data: lidoKeys } = await this.keysApiService.getKeys( + firstRequestMeta, + ); endTimerKeysReq(); From c1536797c028cf7a4798ea51613a06254e1f2f69 Mon Sep 17 00:00:00 2001 From: Eddort Date: Tue, 29 Oct 2024 11:53:18 +0100 Subject: [PATCH 05/11] refactor: add comments to keys-api-service --- src/keys-api/keys-api.service.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/keys-api/keys-api.service.ts b/src/keys-api/keys-api.service.ts index a90aaad1..1d6af82e 100644 --- a/src/keys-api/keys-api.service.ts +++ b/src/keys-api/keys-api.service.ts @@ -13,6 +13,8 @@ import { DeepReadonly } from 'common/ts-utils'; @Injectable() export class KeysApiService { + // Do not use this value in a straightforward manner + // It can be used in parallel at the moment in `getKeys` private cachedKeys?: DeepReadonly; constructor( @Inject(WINSTON_MODULE_NEST_PROVIDER) protected logger: LoggerService, @@ -125,6 +127,9 @@ export class KeysApiService { cachedELBlockSnapshot: this.cachedKeys?.meta.elBlockSnapshot, }); + // delete old cache to optimize memory performance + this.cachedKeys = undefined; + const result = await this.fetch(`/v1/keys`); this.logger.log('Keys successfully updated in cache from KeysAPI', { @@ -139,6 +144,7 @@ export class KeysApiService { ); this.cachedKeys = result; + // return exactly `result` because this function can be used in parallel return result; } From c88cae2b6203a9b5d7ef7e19111b347a70b8ed2e Mon Sep 17 00:00:00 2001 From: Eddort Date: Tue, 29 Oct 2024 13:06:27 +0100 Subject: [PATCH 06/11] refactor: add strict types --- src/keys-api/keys-api.service.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/keys-api/keys-api.service.ts b/src/keys-api/keys-api.service.ts index 1d6af82e..538d3d50 100644 --- a/src/keys-api/keys-api.service.ts +++ b/src/keys-api/keys-api.service.ts @@ -94,7 +94,9 @@ export class KeysApiService { * @param elBlockSnapshot ELBlockSnapshot with the current block hash for cache validation. * @returns Cached or newly fetched keys. */ - public async getKeys(elBlockSnapshot: ELBlockSnapshot) { + public async getKeys( + elBlockSnapshot: ELBlockSnapshot, + ): Promise> { if (!this.cachedKeys) { return this.updateCachedKeys(elBlockSnapshot); } @@ -121,7 +123,9 @@ export class KeysApiService { * Fetches new keys from the /v1/keys endpoint and updates cache. * @returns The newly fetched keys. */ - private async updateCachedKeys(elBlockSnapshot: ELBlockSnapshot) { + private async updateCachedKeys( + elBlockSnapshot: ELBlockSnapshot, + ): Promise> { this.logger.log('Updating keys from KeysAPI', { elBlockSnapshot, cachedELBlockSnapshot: this.cachedKeys?.meta.elBlockSnapshot, @@ -130,7 +134,7 @@ export class KeysApiService { // delete old cache to optimize memory performance this.cachedKeys = undefined; - const result = await this.fetch(`/v1/keys`); + const result = await this.fetch>(`/v1/keys`); this.logger.log('Keys successfully updated in cache from KeysAPI', { elBlockSnapshot, From c4e860dc2e2a9ae72511e37dd9a64eaed97056c9 Mon Sep 17 00:00:00 2001 From: Eddort Date: Tue, 29 Oct 2024 13:43:18 +0100 Subject: [PATCH 07/11] refactor: updating the comment for handleKeys --- src/guardian/guardian.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/guardian/guardian.service.ts b/src/guardian/guardian.service.ts index 7ecaec57..a44f5cb2 100644 --- a/src/guardian/guardian.service.ts +++ b/src/guardian/guardian.service.ts @@ -211,9 +211,9 @@ export class GuardianService implements OnModuleInit { return; } - // To avoid blocking the pause, run the following tasks asynchronously: - // updating the SigningKeyAdded events cache, checking keys, handling the unvetting of keys, - // and sending deposit messages to the queue. + // To avoid blocking the pause due to a potentially lengthy SigningKeyAdded + // events cache update, which can occur when the modules list changes: + // run key checks and send deposit messages to the queue without waiting. this.handleKeys(stakingModulesData, blockData, lidoKeys) .catch(this.logger.error) .finally(() => endTimer()); From 3339e7d86352952dabdd03f4b6aaa630e2be8eb9 Mon Sep 17 00:00:00 2001 From: Eddort Date: Thu, 31 Oct 2024 11:36:41 +0100 Subject: [PATCH 08/11] refactor: rename monitorGuardianDataBusBalance for better logging --- src/contracts/data-bus/data-bus.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/contracts/data-bus/data-bus.service.ts b/src/contracts/data-bus/data-bus.service.ts index 9408163e..9ebd5b82 100644 --- a/src/contracts/data-bus/data-bus.service.ts +++ b/src/contracts/data-bus/data-bus.service.ts @@ -53,7 +53,7 @@ export class DataBusService { const dataBusClient = new DataBusClient(this.dataBusAddress, this.wallet); this.dsmMessageSender = new DSMMessageSender(dataBusClient); - await this.monitorGuardianBalance(); + await this.monitorGuardianDataBusBalance(); this.subscribeToEVMChainUpdates(); } @@ -64,7 +64,7 @@ export class DataBusService { const provider = this.provider; provider.on('block', async (blockNumber) => { if (blockNumber % DATA_BUS_BALANCE_UPDATE_BLOCK_RATE !== 0) return; - await this.monitorGuardianBalance().catch((error) => + await this.monitorGuardianDataBusBalance().catch((error) => this.logger.error(error), ); }); @@ -77,7 +77,7 @@ export class DataBusService { * Updates the account balance metric. */ @OneAtTime() - public async monitorGuardianBalance() { + public async monitorGuardianDataBusBalance() { const balanceWei = await this.getAccountBalance(); const balanceETH = formatEther(balanceWei); const { chainId } = await this.provider.getNetwork(); From 8e90483dade8418154e83cc3cc1da653ee75c267 Mon Sep 17 00:00:00 2001 From: Eddort Date: Thu, 31 Oct 2024 11:37:45 +0100 Subject: [PATCH 09/11] feat: replace cronJob by setInterval --- src/guardian/guardian.constants.ts | 2 +- src/guardian/guardian.service.ts | 31 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/guardian/guardian.constants.ts b/src/guardian/guardian.constants.ts index 0b70b707..76f69b91 100644 --- a/src/guardian/guardian.constants.ts +++ b/src/guardian/guardian.constants.ts @@ -2,6 +2,6 @@ import { CronExpression } from '@nestjs/schedule'; export const GUARDIAN_DEPOSIT_RESIGNING_BLOCKS = 10; export const GUARDIAN_DEPOSIT_JOB_NAME = 'guardian-deposit-job'; -export const GUARDIAN_DEPOSIT_JOB_DURATION = CronExpression.EVERY_5_SECONDS; +export const GUARDIAN_DEPOSIT_JOB_DURATION_MS = 5000; export const MIN_KAPI_VERSION = '2.2.0'; export const GUARDIAN_PING_BLOCKS_PERIOD = 300; diff --git a/src/guardian/guardian.service.ts b/src/guardian/guardian.service.ts index a44f5cb2..9d388b6f 100644 --- a/src/guardian/guardian.service.ts +++ b/src/guardian/guardian.service.ts @@ -7,12 +7,11 @@ import { import { compare } from 'compare-versions'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { SchedulerRegistry } from '@nestjs/schedule'; -import { CronJob } from 'cron'; import { DepositRegistryService } from 'contracts/deposits-registry'; import { SecurityService } from 'contracts/security'; import { RepositoryService } from 'contracts/repository'; import { - GUARDIAN_DEPOSIT_JOB_DURATION, + GUARDIAN_DEPOSIT_JOB_DURATION_MS, GUARDIAN_DEPOSIT_JOB_NAME, } from './guardian.constants'; import { OneAtTime } from 'common/decorators'; @@ -127,17 +126,14 @@ export class GuardianService implements OnModuleInit { * Subscribes to the staking router modules updates */ public subscribeToModulesUpdates() { - const cron = new CronJob(GUARDIAN_DEPOSIT_JOB_DURATION, () => { - this.handleNewBlock().catch((error) => { - this.logger.error(error); - }); - }); - - this.logger.log('GuardianService subscribed to Ethereum events'); + const interval = setInterval( + () => this.handleNewBlock().catch((error) => this.logger.error(error)), + GUARDIAN_DEPOSIT_JOB_DURATION_MS, + ); - cron.start(); + this.schedulerRegistry.addInterval(GUARDIAN_DEPOSIT_JOB_NAME, interval); - this.schedulerRegistry.addCronJob(GUARDIAN_DEPOSIT_JOB_NAME, cron); + this.logger.log('GuardianService subscribed to Ethereum events'); } /** @@ -145,7 +141,7 @@ export class GuardianService implements OnModuleInit { */ @OneAtTime() public async handleNewBlock(): Promise { - this.logger.log('New staking router state cycle start'); + this.logger.log('Beginning of the processing of the new Guardian cycle'); try { const endTimer = this.jobDurationMetric @@ -216,10 +212,15 @@ export class GuardianService implements OnModuleInit { // run key checks and send deposit messages to the queue without waiting. this.handleKeys(stakingModulesData, blockData, lidoKeys) .catch(this.logger.error) - .finally(() => endTimer()); + .finally(() => { + this.logger.log('End of unvetting and deposits processing by Guardian'); + endTimer() + }); } catch (error) { - this.logger.error('Staking router state update error'); + this.logger.error('Guardian cycle processing error'); this.logger.error(error); + } finally { + this.logger.log('End of pause processing by Guardian'); } } @@ -288,8 +289,6 @@ export class GuardianService implements OnModuleInit { blockHash, blockNumber, }); - - this.logger.log('New staking router state cycle end'); } private async checkKeys( From e9029165f078954998e0a65f69193f331c62e6d3 Mon Sep 17 00:00:00 2001 From: Eddort Date: Thu, 31 Oct 2024 11:38:38 +0100 Subject: [PATCH 10/11] version: bump package json version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 32d17327..0592193e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lido-council-daemon", - "version": "3.2.0", + "version": "3.3.0", "description": "Lido Council Daemon", "author": "Lido team", "private": true, From 18d21cbc8c6bde3910a09e9708cb2173d275000b Mon Sep 17 00:00:00 2001 From: Eddort Date: Thu, 31 Oct 2024 12:20:25 +0100 Subject: [PATCH 11/11] fix: remove unused vars --- src/guardian/guardian.constants.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/guardian/guardian.constants.ts b/src/guardian/guardian.constants.ts index 76f69b91..189260cf 100644 --- a/src/guardian/guardian.constants.ts +++ b/src/guardian/guardian.constants.ts @@ -1,5 +1,3 @@ -import { CronExpression } from '@nestjs/schedule'; - export const GUARDIAN_DEPOSIT_RESIGNING_BLOCKS = 10; export const GUARDIAN_DEPOSIT_JOB_NAME = 'guardian-deposit-job'; export const GUARDIAN_DEPOSIT_JOB_DURATION_MS = 5000;