@@ -9,8 +9,9 @@ mod migrations;
99mod network;
1010mod query;
1111
12- use anyhow:: { anyhow, Result } ;
12+ use anyhow:: { anyhow, bail , Result } ;
1313use ceramic_core:: ssi:: caip2:: ChainId ;
14+ use ceramic_event_svc:: { eth_rpc:: HttpEthRpc , ChainInclusionProvider } ;
1415use ceramic_metrics:: config:: Config as MetricsConfig ;
1516use ceramic_sql:: sqlite:: { SqliteOpts , SqlitePool } ;
1617use clap:: { Args , Parser , Subcommand , ValueEnum } ;
@@ -22,8 +23,7 @@ use multihash_codetable::Code;
2223use multihash_derive:: Hasher ;
2324use shutdown:: Shutdown ;
2425use signal_hook_tokio:: Signals ;
25- use std:: str:: FromStr ;
26- use std:: { env, path:: PathBuf } ;
26+ use std:: { env, path:: PathBuf , str:: FromStr , sync:: Arc } ;
2727use tokio:: io:: AsyncReadExt ;
2828use tracing:: { debug, error, info, warn} ;
2929
@@ -121,7 +121,7 @@ impl Network {
121121 }
122122
123123 /// Return the default ethereum rpc providers for each network.
124- pub fn default_rpc_urls ( & self ) -> Result < Vec < String > > {
124+ fn default_rpc_urls ( & self ) -> Result < Vec < String > > {
125125 match self {
126126 Network :: Mainnet => {
127127 anyhow:: bail!( "no Ethereum RPC URLs specified for Mainnet" )
@@ -151,7 +151,7 @@ impl Network {
151151 }
152152
153153 /// return the allowed chain ids for this network. or None for any
154- pub fn supported_chain_ids ( & self ) -> Option < Vec < ChainId > > {
154+ fn supported_chain_ids ( & self ) -> Option < Vec < ChainId > > {
155155 match self {
156156 Network :: Mainnet => Some ( vec ! [
157157 ChainId :: from_str( "eip155:1" ) . expect( "eip155:1 is a valid chain" )
@@ -168,7 +168,7 @@ impl Network {
168168 }
169169
170170 /// Get the network as a unique name.
171- pub fn name ( & self ) -> String {
171+ fn name ( & self ) -> String {
172172 match self {
173173 Network :: Mainnet => "mainnet" . to_owned ( ) ,
174174 Network :: TestnetClay => "testnet-clay" . to_owned ( ) ,
@@ -177,6 +177,56 @@ impl Network {
177177 Network :: InMemory => "inmemory" . to_owned ( ) ,
178178 }
179179 }
180+
181+ pub async fn get_eth_rpc_providers (
182+ & self ,
183+ ethereum_rpc_urls : Vec < String > ,
184+ ) -> Result < Vec < ChainInclusionProvider > > {
185+ let ethereum_rpc_urls = if ethereum_rpc_urls. is_empty ( ) {
186+ self . default_rpc_urls ( ) ?
187+ } else {
188+ ethereum_rpc_urls
189+ } ;
190+
191+ let mut providers = Vec :: new ( ) ;
192+ for url in ethereum_rpc_urls {
193+ match HttpEthRpc :: try_new ( & url) . await {
194+ Ok ( provider) => {
195+ let provider_chain = provider. chain_id ( ) ;
196+ if self
197+ . supported_chain_ids ( )
198+ . is_none_or ( |ids| ids. contains ( provider_chain) )
199+ {
200+ info ! (
201+ "Using ethereum rpc provider for chain: {} with url: {}" ,
202+ provider. chain_id( ) ,
203+ provider. url( )
204+ ) ;
205+ let provider: ChainInclusionProvider = Arc :: new ( provider) ;
206+ providers. push ( provider) ;
207+ } else {
208+ warn ! ( "Eth RPC provider {} uses chainid {} which isn't supported by Ceramic network {:?}" , url, provider_chain, self ) ;
209+ }
210+ }
211+ Err ( err) => {
212+ warn ! ( "failed to create RPC client with url: '{url}': {:?}" , err) ;
213+ }
214+ }
215+ }
216+
217+ if providers. is_empty ( ) {
218+ if * self == Network :: Local || * self == Network :: InMemory {
219+ warn ! ( "No usable ethereum RPC provided for network {}. All TimeEvent validation will fail" , self . name( ) ) ;
220+ } else {
221+ bail ! (
222+ "No usable ethereum RPC configured for network {}" ,
223+ self . name( )
224+ ) ;
225+ }
226+ }
227+
228+ Ok ( providers)
229+ }
180230}
181231
182232/// The default storage directory to use if none is provided. In order:
0 commit comments