1
- import { CronJob } from 'cron' ;
1
+ import { CronJob , CronTime } from 'cron' ;
2
2
import { Inject } from '@nestjs/common' ;
3
3
import { LOGGER_PROVIDER , LoggerService } from 'common/logger' ;
4
4
import { JobService } from 'common/job' ;
@@ -43,14 +43,21 @@ export class ValidatorsService {
43
43
*/
44
44
public async initialize ( ) : Promise < void > {
45
45
await this . validatorsCacheService . initializeFromCache ( ) ;
46
- await this . updateValidators ( ) ;
47
46
48
47
const envCronTime = this . configService . get ( 'JOB_INTERVAL_VALIDATORS' ) ;
49
48
const chainId = this . configService . get ( 'CHAIN_ID' ) ;
50
49
const cronByChainId = ORACLE_REPORTS_CRON_BY_CHAIN_ID [ chainId ] ?? CronExpression . EVERY_3_HOURS ;
51
50
const cronTime = envCronTime ? envCronTime : cronByChainId ;
52
- const job = new CronJob ( cronTime , ( ) => this . updateValidators ( ) ) ;
53
- job . start ( ) ;
51
+
52
+ await this . updateValidators ( ) ;
53
+ const mainJob = new CronJob ( cronTime , ( ) => this . updateValidators ( ) ) ;
54
+ mainJob . start ( ) ;
55
+
56
+ await this . updateLidoWithdrawableValidators ( ) ;
57
+ const lidoWithdrawableJob = new CronJob ( CronExpression . EVERY_5_MINUTES , ( ) =>
58
+ this . updateLidoWithdrawableValidators ( ) ,
59
+ ) ;
60
+ lidoWithdrawableJob . start ( ) ;
54
61
55
62
this . logger . log ( 'Service initialized' , { service : ValidatorsService . SERVICE_LOG_NAME , cronTime } ) ;
56
63
}
@@ -88,40 +95,21 @@ export class ValidatorsService {
88
95
this . validatorsStorageService . setActiveValidatorsCount ( activeValidatorCount ) ;
89
96
this . validatorsStorageService . setTotalValidatorsCount ( data . length ) ;
90
97
this . validatorsStorageService . setMaxExitEpoch ( latestEpoch ) ;
91
-
92
- const frameBalances = await this . getLidoValidatorsWithdrawableBalances ( data ) ;
93
- this . validatorsStorageService . setFrameBalances ( frameBalances ) ;
98
+ await this . findAndSetLidoValidatorsWithdrawableBalances ( data ) ;
94
99
await this . validatorsCacheService . saveDataToCache ( ) ;
95
-
96
- const currentFrame = this . genesisTimeService . getFrameOfEpoch ( this . genesisTimeService . getCurrentEpoch ( ) ) ;
97
- this . logger . log ( 'End update validators' , {
98
- service : ValidatorsService . SERVICE_LOG_NAME ,
99
- activeValidatorCount,
100
- latestEpoch,
101
- frameBalances : stringifyFrameBalances ( frameBalances ) ,
102
- currentFrame,
103
- } ) ;
104
-
105
- Object . keys ( frameBalances ) . forEach ( ( frame ) => {
106
- this . prometheusService . validatorsState
107
- . labels ( {
108
- frame,
109
- balance : frameBalances [ frame ] ,
110
- } )
111
- . inc ( ) ;
112
- } ) ;
113
-
100
+ this . logAnalyticsAboutWithdrawableBalances ( activeValidatorCount , latestEpoch ) ;
114
101
this . validatorsStorageService . setLastUpdate ( Math . floor ( Date . now ( ) / 1000 ) ) ;
115
102
} ,
116
103
) ;
117
104
}
118
105
119
- protected async getLidoValidatorsWithdrawableBalances ( validators : Validator [ ] ) {
106
+ protected async findAndSetLidoValidatorsWithdrawableBalances ( validators : Validator [ ] ) {
120
107
const keysData = await this . lidoKeys . fetchLidoKeysData ( ) ;
121
108
const lidoValidators = await this . lidoKeys . getLidoValidatorsByKeys ( keysData . data , validators ) ;
122
109
const lastWithdrawalValidatorIndex = await this . getLastWithdrawalValidatorIndex ( ) ;
123
110
const frameBalances = { } ;
124
111
112
+ const withdrawableLidoValidatorIds : string [ ] = [ ] ;
125
113
for ( const item of lidoValidators ) {
126
114
if ( item . validator . withdrawable_epoch !== FAR_FUTURE_EPOCH . toString ( ) && BigNumber . from ( item . balance ) . gt ( 0 ) ) {
127
115
const withdrawalTimestamp = getValidatorWithdrawalTimestamp (
@@ -134,16 +122,78 @@ export class ValidatorsService {
134
122
const prevBalance = frameBalances [ frame ] ;
135
123
const balance = parseGweiToWei ( item . balance ) ;
136
124
frameBalances [ frame ] = prevBalance ? prevBalance . add ( balance ) : BigNumber . from ( balance ) ;
125
+ withdrawableLidoValidatorIds . push ( item . index ) ;
137
126
}
138
127
139
128
await unblock ( ) ;
140
129
}
141
130
142
- return frameBalances ;
131
+ this . validatorsStorageService . setFrameBalances ( frameBalances ) ;
132
+ this . validatorsStorageService . setWithdrawableLidoValidatorIds ( withdrawableLidoValidatorIds ) ;
133
+ }
134
+
135
+ // updates withdrawable lido validators based on previously identified IDs
136
+ @OneAtTime ( )
137
+ protected async updateLidoWithdrawableValidators ( ) {
138
+ await this . jobService . wrapJob (
139
+ { name : 'update lido withdrawable validators' , service : ValidatorsService . SERVICE_LOG_NAME } ,
140
+ async ( ) => {
141
+ this . logger . log ( 'Start update lido withdrawable validators' , { service : ValidatorsService . SERVICE_LOG_NAME } ) ;
142
+
143
+ const validatorIds = this . validatorsStorageService . getWithdrawableLidoValidatorIds ( ) ;
144
+ const lastWithdrawalValidatorIndex = await this . getLastWithdrawalValidatorIndex ( ) ;
145
+ const frameBalances = { } ;
146
+
147
+ for ( const validatorId of validatorIds ) {
148
+ const stateValidator = await this . consensusProviderService . getStateValidator ( {
149
+ stateId : 'head' ,
150
+ validatorId,
151
+ } ) ;
152
+
153
+ const withdrawalTimestamp = getValidatorWithdrawalTimestamp (
154
+ BigNumber . from ( stateValidator . data . index ) ,
155
+ lastWithdrawalValidatorIndex ,
156
+ this . validatorsStorageService . getActiveValidatorsCount ( ) ,
157
+ this . validatorsStorageService . getTotalValidatorsCount ( ) ,
158
+ ) ;
159
+ const frame = this . genesisTimeService . getFrameByTimestamp ( withdrawalTimestamp ) + 1 ;
160
+ const prevBalance = frameBalances [ frame ] ;
161
+ const balance = parseGweiToWei ( stateValidator . data . balance ) ;
162
+ frameBalances [ frame ] = prevBalance ? prevBalance . add ( balance ) : BigNumber . from ( balance ) ;
163
+ }
164
+
165
+ this . validatorsStorageService . setFrameBalances ( frameBalances ) ;
166
+ this . logger . log ( 'End update lido withdrawable validators' , {
167
+ service : ValidatorsService . SERVICE_LOG_NAME ,
168
+ frameBalances : stringifyFrameBalances ( frameBalances ) ,
169
+ } ) ;
170
+ } ,
171
+ ) ;
143
172
}
144
173
145
174
protected async getLastWithdrawalValidatorIndex ( ) {
146
175
const withdrawals = await this . executionProviderService . getLatestWithdrawals ( ) ;
147
176
return BigNumber . from ( withdrawals [ withdrawals . length - 1 ] . validatorIndex ) ;
148
177
}
178
+
179
+ protected logAnalyticsAboutWithdrawableBalances ( activeValidatorCount : number , latestEpoch : string ) {
180
+ const currentFrame = this . genesisTimeService . getFrameOfEpoch ( this . genesisTimeService . getCurrentEpoch ( ) ) ;
181
+ const frameBalances = this . validatorsStorageService . getFrameBalances ( ) ;
182
+ this . logger . log ( 'End update validators' , {
183
+ service : ValidatorsService . SERVICE_LOG_NAME ,
184
+ activeValidatorCount,
185
+ latestEpoch,
186
+ frameBalances : stringifyFrameBalances ( frameBalances ) ,
187
+ currentFrame,
188
+ } ) ;
189
+
190
+ Object . keys ( frameBalances ) . forEach ( ( frame ) => {
191
+ this . prometheusService . validatorsState
192
+ . labels ( {
193
+ frame,
194
+ balance : frameBalances [ frame ] . toString ( ) ,
195
+ } )
196
+ . inc ( ) ;
197
+ } ) ;
198
+ }
149
199
}
0 commit comments