mod chain_id;
pub mod eip155;
pub mod solana;
pub use chain_id::*;
use crate::config::{ChainConfig, ChainsConfig};
use std::collections::HashMap;
use std::sync::Arc;
#[async_trait::async_trait]
pub trait FromConfig<TConfig>
where
Self: Sized,
{
async fn from_config(config: &TConfig) -> Result<Self, Box<dyn std::error::Error>>;
}
#[derive(Debug, Clone)]
pub enum ChainProvider {
Eip155(Arc<eip155::Eip155ChainProvider>),
Solana(Arc<solana::SolanaChainProvider>),
}
#[async_trait::async_trait]
impl FromConfig<ChainConfig> for ChainProvider {
async fn from_config(chains: &ChainConfig) -> Result<Self, Box<dyn std::error::Error>> {
let provider = match chains {
ChainConfig::Eip155(config) => {
let provider = eip155::Eip155ChainProvider::from_config(config).await?;
ChainProvider::Eip155(Arc::new(provider))
}
ChainConfig::Solana(config) => {
let provider = solana::SolanaChainProvider::from_config(config).await?;
ChainProvider::Solana(Arc::new(provider))
}
};
Ok(provider)
}
}
pub trait ChainProviderOps {
fn signer_addresses(&self) -> Vec<String>;
fn chain_id(&self) -> ChainId;
}
impl<T: ChainProviderOps> ChainProviderOps for Arc<T> {
fn signer_addresses(&self) -> Vec<String> {
(**self).signer_addresses()
}
fn chain_id(&self) -> ChainId {
(**self).chain_id()
}
}
impl ChainProviderOps for ChainProvider {
fn signer_addresses(&self) -> Vec<String> {
match self {
ChainProvider::Eip155(provider) => provider.signer_addresses(),
ChainProvider::Solana(provider) => provider.signer_addresses(),
}
}
fn chain_id(&self) -> ChainId {
match self {
ChainProvider::Eip155(provider) => provider.chain_id(),
ChainProvider::Solana(provider) => provider.chain_id(),
}
}
}
#[derive(Debug)]
pub struct ChainRegistry<P>(HashMap<ChainId, P>);
impl<P> ChainRegistry<P> {
pub fn new(providers: HashMap<ChainId, P>) -> Self {
Self(providers)
}
}
#[async_trait::async_trait]
impl FromConfig<ChainsConfig> for ChainRegistry<ChainProvider> {
async fn from_config(chains: &ChainsConfig) -> Result<Self, Box<dyn std::error::Error>> {
let mut providers = HashMap::new();
for chain in chains.iter() {
let chain_provider = ChainProvider::from_config(chain).await?;
providers.insert(chain_provider.chain_id(), chain_provider);
}
Ok(Self::new(providers))
}
}
impl<P> ChainRegistry<P> {
#[allow(dead_code)]
pub fn by_chain_id(&self, chain_id: ChainId) -> Option<&P> {
self.0.get(&chain_id)
}
pub fn by_chain_id_pattern(&self, pattern: &ChainIdPattern) -> Vec<&P> {
self.0
.iter()
.filter_map(|(chain_id, provider)| pattern.matches(chain_id).then_some(provider))
.collect()
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)] pub struct DeployedTokenAmount<TAmount, TToken> {
pub amount: TAmount,
pub token: TToken,
}