feature: try_into_replica

buddies-main-deployment
James Prestwich 4 years ago
parent f879bd73cc
commit ec87181f32
No known key found for this signature in database
GPG Key ID: 75A7F5C06D747046
  1. 17
      rust/optics-base/src/abis/mod.rs
  2. 41
      rust/optics-base/src/main.rs
  3. 86
      rust/optics-base/src/settings.rs

@ -22,6 +22,18 @@ where
slip44: u32,
}
impl<M> ReplicaContract<M>
where
M: ethers_providers::Middleware,
{
pub fn at(slip44: u32, address: Address, provider: Arc<M>) -> Self {
Self {
contract: ReplicaContractInternal::new(address, provider),
slip44,
}
}
}
#[async_trait]
impl<M> Common for ReplicaContract<M>
where
@ -108,9 +120,8 @@ where
let pending = self.contract.pending();
let confirm_at = self.contract.confirm_at();
let (pending, confirm_at) = tokio::join!(pending.call(), confirm_at.call());
let pending = pending?;
let confirm_at = confirm_at?;
let res = tokio::try_join!(pending.call(), confirm_at.call());
let (pending, confirm_at) = res?;
if confirm_at.is_zero() {
Ok(None)

@ -1,21 +1,50 @@
//! This repo contains a simple framework for building Optics agents.
//! It has common utils and tools for configuring the app, interacting with the
//! smart contracts, etc.
//!
//! Implementations of the `Home` and `Replica` traits on different chains
//! ought to live here.
//!
//! Settings parsers live here, while config toml files live with their agent.
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![warn(unused_extern_crates)]
mod abis;
mod settings;
use optics_core::traits::{Home, Replica};
use std::collections::HashMap;
/// The global app context.
///
/// We erase all type info to allow easier abstraction across chains without
/// managing insanely large type systems.
///
/// Usually this will be bundled in a larger
#[derive(Debug)]
struct App {
struct ChainConnections {
home: Box<dyn Home>,
replicas: Vec<Box<dyn Replica>>,
replicas: HashMap<String, Box<dyn Replica>>,
}
async fn _main(settings: settings::Settings) {
println!("{:?}", &settings);
let app = App {
home: settings.home.try_into_home().await.expect("!home"),
replicas: vec![],
};
let home = settings.home.try_into_home().await.expect("!home");
let mut replicas = HashMap::new();
// TODO: parallelize if this becomes expensive
for (key, value) in settings.replicas.iter() {
replicas.insert(
key.clone(),
value.try_into_replica().await.expect("!replica"),
);
}
let app = ChainConnections { home, replicas };
println!("{:?}", &app);
}

@ -4,17 +4,19 @@ use std::{collections::HashMap, convert::TryFrom, env};
use ethers_core::types::Address;
use ethers_providers::{Http, Provider, Ws};
use optics_core::traits::Home;
use optics_core::traits::{Home, Replica};
/// Ethereum connection configuration
#[derive(Debug, serde::Deserialize)]
#[serde(tag = "type")]
pub(crate) enum EthereumConf {
pub enum EthereumConf {
Http { url: String },
Ws { url: String },
}
impl EthereumConf {
async fn try_home(&self, slip44: u32, address: Address) -> Result<Box<dyn Home>, String> {
/// Try to convert this into a home contract
async fn try_into_home(&self, slip44: u32, address: Address) -> Result<Box<dyn Home>, String> {
let b: Box<dyn Home> = match self {
Self::Http { url } => {
let provider = Provider::<Http>::try_from(url.as_ref()).map_err(|_| "!url")?;
@ -36,16 +38,50 @@ impl EthereumConf {
};
Ok(b)
}
/// Try to convert this into a replica contract
pub async fn try_into_replica(
&self,
slip44: u32,
address: Address,
) -> Result<Box<dyn Replica>, String> {
let b: Box<dyn Replica> = match self {
Self::Http { url } => {
let provider = Provider::<Http>::try_from(url.as_ref()).map_err(|_| "!url")?;
Box::new(crate::abis::ReplicaContract::at(
slip44,
address,
provider.into(),
))
}
Self::Ws { url } => {
let ws = Ws::connect(url).await.map_err(|_| "!ws connect")?;
let provider = Provider::new(ws);
Box::new(crate::abis::ReplicaContract::at(
slip44,
address,
provider.into(),
))
}
};
Ok(b)
}
}
/// A connection to _some_ blockchain.
///
/// Specify the chain name (enum variant) in toml under the `chain` key
/// Specify the connection details as a toml object under the `connection` key.
#[derive(Debug, serde::Deserialize)]
#[serde(tag = "chain", content = "connection")]
pub(crate) enum ChainConnection {
pub enum ChainConnection {
Ethereum(EthereumConf),
}
/// A chain setup is a slip44 ID, an address on that chain (where the home or
/// replica is deployed) and details for connecting to the chain API.
#[derive(Debug, serde::Deserialize)]
pub(crate) struct ChainSetup {
pub struct ChainSetup {
slip44: u32,
address: String,
#[serde(flatten)]
@ -56,17 +92,49 @@ impl ChainSetup {
pub async fn try_into_home(&self) -> Result<Box<dyn Home>, String> {
match &self.connection {
ChainConnection::Ethereum(conf) => {
conf.try_home(self.slip44, self.address.parse().map_err(|_| "!address")?)
conf.try_into_home(self.slip44, self.address.parse().map_err(|_| "!address")?)
.await
}
}
}
pub async fn try_into_replica(&self) -> Result<Box<dyn Replica>, String> {
match &self.connection {
ChainConnection::Ethereum(conf) => {
conf.try_into_replica(self.slip44, self.address.parse().map_err(|_| "!address")?)
.await
}
}
}
}
/// Settings. Usually this should be treated as a base config and used as
/// follows:
///
/// ```
/// use optics_base::settings::*;
///
/// pub struct OtherSettings { /* anything */ };
///
/// #[derive(Debug, serde::Deseirialize)]
/// pub struct MySettings {
/// #[serde(flatten)]
/// base_settings: Settings,
/// #[serde(flatten)]
/// other_settings: (),
/// }
///
/// // Make sure to define MySettings::new()
/// impl MySettings {
/// fn new() -> Self {
/// unimplemented!()
/// }
/// }
/// ```
#[derive(Debug, serde::Deserialize)]
pub(crate) struct Settings {
pub(crate) home: ChainSetup,
pub(crate) replicas: HashMap<String, ChainSetup>,
pub struct Settings {
pub home: ChainSetup,
pub replicas: HashMap<String, ChainSetup>,
}
impl Settings {

Loading…
Cancel
Save