Skip to content

Commit

Permalink
wip: mware and combinator stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
prestwich committed Jul 14, 2023
1 parent 268412b commit 3cf3f2d
Show file tree
Hide file tree
Showing 8 changed files with 296 additions and 215 deletions.
1 change: 1 addition & 0 deletions crates/network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ alloy-transports.workspace = true
serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
tower = "0.4.13"
220 changes: 5 additions & 215 deletions crates/network/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,7 @@
use std::{future::Future, pin::Pin};
use alloy_transports::{RpcParam, RpcResp};

use alloy_primitives::{TxHash, U256};
use alloy_rlp::{Decodable, Encodable};
use alloy_transports::{Connection, RpcCall, RpcParam, RpcResp, RpcResult, TransportError};

type MwareCall<'a, M, N, Resp> =
RpcCall<&'a <M as Middleware<N>>::Connection, <M as Middleware<N>>::Connection, Resp>;

type MwareFut<'a, M, N, T> =
Pin<Box<dyn Future<Output = RpcResult<T, <M as Middleware<N>>::Error>> + Send + 'a>>;

pub trait Transaction: Encodable + Decodable {
// VALUE
fn get_value(&self) -> U256;
fn set_value(&mut self, value: U256);
fn value(self, value: U256) -> Self;

// GAS PRICE
fn get_gas_price(&self) -> U256;
// set and builder are omitted due to eip1559 interaction.

// GAS AMOUNT
fn get_gas(&self) -> U256;
fn set_gas(&mut self, gas: U256);
fn gas(self, gas: U256) -> Self;

// DATA
fn get_data(&self) -> &[u8];
fn set_data(&mut self, data: Vec<u8>);
fn data(self, data: Vec<u8>) -> Self;

// TO
fn get_to(&self) -> Option<&[u8]>;
fn set_to(&mut self, to: Option<Vec<u8>>);
fn to(self, to: Option<Vec<u8>>) -> Self;
}

pub trait Eip1559Transaction: Transaction {
// MAX FEE PER GAS
fn get_max_fee_per_gas(&self) -> U256;
fn set_max_fee_per_gas(&mut self, max_fee_per_gas: U256);
fn max_fee_per_gas(self, max_fee_per_gas: U256) -> Self;

// MAX PRIORITY FEE PER GAS
fn get_max_priority_fee_per_gas(&self) -> U256;
fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: U256);
fn max_priority_fee_per_gas(self, max_priority_fee_per_gas: U256) -> Self;
}
mod transaction;
pub use transaction::{Eip1559Transaction, Transaction};

pub trait Network: Sized + Send + Sync + 'static {
#[doc(hidden)]
Expand All @@ -66,171 +21,6 @@ pub trait Network: Sized + Send + Sync + 'static {
type Receipt: RpcResp;
}

// TODO: replace these with things that aren't Box<dyn Future>
pub trait Middleware<N>: Send + Sync + std::fmt::Debug
where
N: Network,
{
type Connection: Connection;
type Inner: Middleware<N, Connection = Self::Connection>;
type Error: std::error::Error + From<TransportError> + Send + Sync + 'static; // TODO

fn inner(&self) -> &Self::Inner;

fn connection(&self) -> &Self::Connection {
self.inner().connection()
}

fn get_transaction(&self, tx_hash: TxHash) -> MwareCall<Self, N, N::TransactionRespose> {
self.inner().get_transaction(tx_hash)
}

fn estimate_gas<'a, 'b>(&'a self, tx: &'b N::Transaction) -> MwareCall<Self, N, U256>
where
'a: 'b,
{
self.inner().estimate_gas(tx)
}

fn populate_gas<'a, 'b>(&'a self, tx: &'b mut N::Transaction) -> MwareFut<'b, Self, N, ()>
where
'a: 'b,
{
Box::pin(async move {
self.estimate_gas(tx)
.await
.map(|gas| tx.set_gas(gas))
.convert_err()
})
}
}

impl<N, T> Middleware<N> for T
where
T: Connection,
N: Network,
{
type Connection = Self;
type Inner = Self;
type Error = TransportError;

fn inner(&self) -> &Self::Inner {
self
}

fn connection(&self) -> &Self::Connection {
self
}

fn get_transaction(
&self,
tx_hash: TxHash,
) -> MwareCall<Self, N, <N as Network>::TransactionRespose> {
self.request("eth_getTransactionByHash", tx_hash)
}

fn estimate_gas<'a, 'b>(&'a self, tx: &'b N::Transaction) -> MwareCall<Self, N, U256>
where
'a: 'b,
{
self.request("eth_estimateGas", tx)
}
}

#[cfg(test)]
mod tests {
use std::str::FromStr;
mod mware1;

use alloy_primitives::U256;
use alloy_transports::Http;

use super::*;

struct DummyNet;

impl Transaction for u8 {
fn get_value(&self) -> alloy_primitives::U256 {
todo!()
}

fn set_value(&mut self, _value: alloy_primitives::U256) {
todo!()
}

fn value(self, _value: alloy_primitives::U256) -> Self {
todo!()
}

fn get_gas_price(&self) -> alloy_primitives::U256 {
todo!()
}

fn get_gas(&self) -> alloy_primitives::U256 {
todo!()
}

fn set_gas(&mut self, _gas: alloy_primitives::U256) {
todo!()
}

fn gas(self, _gas: alloy_primitives::U256) -> Self {
todo!()
}

fn get_data(&self) -> &[u8] {
todo!()
}

fn set_data(&mut self, _data: Vec<u8>) {
todo!()
}

fn data(self, _data: Vec<u8>) -> Self {
todo!()
}

fn get_to(&self) -> Option<&[u8]> {
todo!()
}

fn set_to(&mut self, _to: Option<Vec<u8>>) {
todo!()
}

fn to(self, _to: Option<Vec<u8>>) -> Self {
todo!()
}
}

impl super::Network for DummyNet {
type Transaction = u8;
type TransactionRespose = u8;
type Receipt = u8;
}

type DummyCall<'a, M, Resp> = MwareCall<'a, M, DummyNet, Resp>;

trait DummyMiddleware: Middleware<DummyNet> {
fn estimate_gas(&self, tx: &u8) -> DummyCall<Self, U256> {
Middleware::<DummyNet>::estimate_gas(self, tx)
}
}

impl<T> DummyMiddleware for T where T: Middleware<DummyNet> {}

fn __compile_check_dyn_mware<N: Network>(
) -> Box<dyn Middleware<N, Connection = Http, Inner = Http, Error = TransportError>> {
Box::new(Http::from_str("http://localhost:8545").unwrap())
}

#[test]
fn __compile_check_use_dyn() {
let provider = __compile_check_dyn_mware::<DummyNet>();
let _call: DummyCall<Http, U256> = provider.estimate_gas(&0u8);
}

fn __compile_check_subtype_mware(
) -> Box<dyn DummyMiddleware<Connection = Http, Error = TransportError, Inner = Http>> {
Box::new(Http::from_str("http://localhost:8545").unwrap())
}
}
mod mware2;
87 changes: 87 additions & 0 deletions crates/network/src/mware1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use crate::{Network, Transaction};

use alloy_primitives::{TxHash, U256};
use alloy_transports::{CallWithPost, Connection, TransportError};

pub(crate) type MwareCall<'a, 'process, 'transform, M, N, Resp, T = Resp> = CallWithPost<
'process,
'transform,
&'a <M as Middleware<N>>::Connection,
<M as Middleware<N>>::Connection,
Resp,
T,
>;

// TODO: replace these with things that aren't Box<dyn Future>
pub trait Middleware<N>: Send + Sync + std::fmt::Debug
where
N: Network,
{
type Connection: Connection;
type Inner: Middleware<N, Connection = Self::Connection>;
type Error: std::error::Error + From<TransportError> + Send + Sync + 'static; // TODO

fn inner(&self) -> &Self::Inner;

fn connection(&self) -> &Self::Connection {
self.inner().connection()
}

fn get_transaction(&self, tx_hash: TxHash) -> MwareCall<Self, N, N::TransactionRespose> {
self.inner().get_transaction(tx_hash)
}

fn estimate_gas<'a, 'b>(&'a self, tx: &'b N::Transaction) -> MwareCall<Self, N, U256>
where
'a: 'b,
{
self.inner().estimate_gas(tx)
}

fn populate_gas<'a, 'b>(
&'a self,
tx: &'b mut N::Transaction,
) -> MwareCall<'a, 'b, 'b, Self, N, U256, ()>
where
'a: 'b,
{
self.estimate_gas(tx)
.and(|gas| {
tx.set_gas(gas);
gas
})
.and_transform(|_| ())
}
}

impl<N, T> Middleware<N> for T
where
T: Connection,
N: Network,
{
type Connection = Self;
type Inner = Self;
type Error = TransportError;

fn inner(&self) -> &Self::Inner {
self
}

fn connection(&self) -> &Self::Connection {
self
}

fn get_transaction(
&self,
tx_hash: TxHash,
) -> MwareCall<Self, N, <N as Network>::TransactionRespose> {
self.request("eth_getTransactionByHash", tx_hash).into()
}

fn estimate_gas<'a, 'b>(&'a self, tx: &'b N::Transaction) -> MwareCall<Self, N, U256>
where
'a: 'b,
{
self.request("eth_estimateGas", tx).into()
}
}
6 changes: 6 additions & 0 deletions crates/network/src/mware2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use alloy_transports::{RpcParam, RpcResp};

trait RpcMethod<N>: RpcParam {
const METHOD: &'static str;
type Output: RpcResp;
}
41 changes: 41 additions & 0 deletions crates/network/src/transaction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use alloy_primitives::U256;

use alloy_rlp::{Decodable, Encodable};

pub trait Transaction: Encodable + Decodable {
// VALUE
fn get_value(&self) -> U256;
fn set_value(&mut self, value: U256);
fn value(self, value: U256) -> Self;

// GAS PRICE
fn get_gas_price(&self) -> U256;
// set and builder are omitted due to eip1559 interaction.

// GAS AMOUNT
fn get_gas(&self) -> U256;
fn set_gas(&mut self, gas: U256);
fn gas(self, gas: U256) -> Self;

// DATA
fn get_data(&self) -> &[u8];
fn set_data(&mut self, data: Vec<u8>);
fn data(self, data: Vec<u8>) -> Self;

// TO
fn get_to(&self) -> Option<&[u8]>;
fn set_to(&mut self, to: Option<Vec<u8>>);
fn to(self, to: Option<Vec<u8>>) -> Self;
}

pub trait Eip1559Transaction: Transaction {
// MAX FEE PER GAS
fn get_max_fee_per_gas(&self) -> U256;
fn set_max_fee_per_gas(&mut self, max_fee_per_gas: U256);
fn max_fee_per_gas(self, max_fee_per_gas: U256) -> Self;

// MAX PRIORITY FEE PER GAS
fn get_max_priority_fee_per_gas(&self) -> U256;
fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: U256);
fn max_priority_fee_per_gas(self, max_priority_fee_per_gas: U256) -> Self;
}
1 change: 1 addition & 0 deletions crates/transports/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ where

/// The result of a JSON-RPC request. Either a success response, an error
/// response, or another error.
#[must_use = "Results must be handled."]
#[derive(Error, Debug)]
pub enum RpcResult<T, E> {
Ok(T),
Expand Down
3 changes: 3 additions & 0 deletions crates/transports/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ pub use connection::{Connection, PubSubConnection, RpcParam, RpcResp};

pub mod transports;
pub use transports::Http;

mod post;
pub use post::CallWithPost;
Loading

0 comments on commit 3cf3f2d

Please sign in to comment.