@@ -149,6 +149,8 @@ pub enum MuxKeysLoader {
149149pub enum NORegistry {
150150 #[ serde( alias = "lido" ) ]
151151 Lido ,
152+ #[ serde( alias = "ssv" ) ]
153+ SSV ,
152154}
153155
154156impl MuxKeysLoader {
@@ -176,6 +178,9 @@ impl MuxKeysLoader {
176178
177179 fetch_lido_registry_keys ( rpc_url, chain, U256 :: from ( * node_operator_id) ) . await
178180 }
181+ NORegistry :: SSV => {
182+ fetch_ssv_registry_keys ( chain, U256 :: from ( * node_operator_id) ) . await
183+ }
179184 } ,
180185 }
181186 }
@@ -266,6 +271,71 @@ async fn fetch_lido_registry_keys(
266271 Ok ( keys)
267272}
268273
274+ async fn fetch_ssv_registry_keys (
275+ chain : Chain ,
276+ node_operator_id : U256 ,
277+ ) -> eyre:: Result < Vec < BlsPublicKey > > {
278+ const MAX_PER_PAGE : usize = 100 ;
279+
280+ let chain_name = match chain {
281+ Chain :: Mainnet => "mainnet" ,
282+ Chain :: Holesky => "holesky" ,
283+ _ => bail ! ( "SSV network is not supported for chain: {chain:?}" ) ,
284+ } ;
285+
286+ let client = reqwest:: Client :: new ( ) ;
287+ let mut pubkeys: Vec < BlsPublicKey > = vec ! [ ] ;
288+ let mut page = 1 ;
289+
290+ loop {
291+ let response = client
292+ . get ( format ! (
293+ "https://api.ssv.network/api/v4/{}/validators/in_operator/{}?perPage={}&page={}" ,
294+ chain_name, node_operator_id, MAX_PER_PAGE , page
295+ ) )
296+ . send ( )
297+ . await
298+ . map_err ( |e| eyre:: eyre!( "Error sending request to SSV network: {e}" ) ) ?
299+ . json :: < SSVResponse > ( )
300+ . await ?;
301+
302+ pubkeys. extend ( response. validators . iter ( ) . map ( |v| v. pubkey ) . collect :: < Vec < BlsPublicKey > > ( ) ) ;
303+ page += 1 ;
304+
305+ if response. validators . is_empty ( ) || response. validators . len ( ) < MAX_PER_PAGE {
306+ ensure ! (
307+ pubkeys. len( ) == response. pagination. total,
308+ "expected {} keys, got {}" ,
309+ response. pagination. total,
310+ pubkeys. len( )
311+ ) ;
312+ break ;
313+ }
314+ }
315+
316+ let unique = pubkeys. iter ( ) . collect :: < HashSet < _ > > ( ) ;
317+ ensure ! ( unique. len( ) == pubkeys. len( ) , "found duplicate keys in registry" ) ;
318+
319+ Ok ( pubkeys)
320+ }
321+
322+ #[ derive( Deserialize ) ]
323+ struct SSVResponse {
324+ validators : Vec < SSVValidator > ,
325+ pagination : SSVPagination ,
326+ }
327+
328+ #[ derive( Deserialize ) ]
329+ struct SSVValidator {
330+ #[ serde( rename = "public_key" ) ]
331+ pubkey : BlsPublicKey ,
332+ }
333+
334+ #[ derive( Deserialize ) ]
335+ struct SSVPagination {
336+ total : usize ,
337+ }
338+
269339#[ cfg( test) ]
270340mod tests {
271341 use alloy:: { primitives:: U256 , providers:: ProviderBuilder } ;
0 commit comments