Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a transports crate & initial Network abstraction #2

Merged
merged 53 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
83a5c8a
feature: transports crate
prestwich Jul 10, 2023
0203bad
review: address comments
prestwich Jul 12, 2023
7528c5e
refactor: RpcObject trait
prestwich Jul 12, 2023
fe6142d
refactor: RpcResult type
prestwich Jul 12, 2023
b2e3705
refactor: small code quality
prestwich Jul 12, 2023
f1010c6
deps: bump Cargo.toml
prestwich Jul 12, 2023
04f3c49
chore: delete unused src
prestwich Jul 12, 2023
366a5ac
refactor: more stuff
prestwich Jul 12, 2023
4de4a8e
refactor: remove Params type from RpcCall
prestwich Jul 12, 2023
27a6c0f
fix: remove extra to_json_raw_value
prestwich Jul 12, 2023
e2703df
refactor: minor legibility
prestwich Jul 12, 2023
53128fd
feat: unwrap variants
prestwich Jul 12, 2023
76bef7f
fix: add debug bounds
prestwich Jul 12, 2023
d654407
feature: some cool combinators on rpccall
prestwich Jul 12, 2023
1d691ec
fix: hide __ENFORCE_ZST
prestwich Jul 12, 2023
0073a12
feature: DummyNetwork compile check
prestwich Jul 12, 2023
9d736b5
test: dummynet compile checks
prestwich Jul 13, 2023
268412b
doc: fix comment
prestwich Jul 13, 2023
3cf3f2d
wip: mware and combinator stuff
prestwich Jul 14, 2023
5c53aa8
fuck jsonrpsee
prestwich Jul 16, 2023
efb5cdc
feature: blanket
prestwich Jul 16, 2023
cf00429
test: http impls transport
prestwich Jul 16, 2023
ed0a5e8
feature: send batch request
prestwich Jul 16, 2023
1e9e873
feature: separate rpc type crate
prestwich Jul 16, 2023
21fda6e
feat: RpcObject
prestwich Jul 17, 2023
12f78fa
refactor: transport future aliases
prestwich Jul 22, 2023
2be245a
refactor: transport requires type-erased futures. improved batch ergo
prestwich Jul 25, 2023
38a63ab
wip: some middleware noodling
prestwich Jul 30, 2023
dcdb4cf
feature: manual future for json rpc to avoid higher-ranked lifetime
prestwich Aug 1, 2023
d45a19d
cleanup: some clippy and stuff
prestwich Aug 2, 2023
b8dbb9a
feature: client builder
prestwich Aug 2, 2023
763a5c6
refactor: move is_local to transport
prestwich Aug 2, 2023
9d1f491
chore: clippy
prestwich Aug 2, 2023
0f3fb8f
feature: generic request
prestwich Aug 2, 2023
843009b
feature: allow type-erased rpc client
prestwich Aug 7, 2023
2b83171
chore: cleanup in transports mod
prestwich Aug 7, 2023
562e539
chore: misc cleanup
prestwich Aug 7, 2023
ceda9f7
refactor: more crate
prestwich Aug 9, 2023
b7a8d1e
chore: clippy cleanup
prestwich Aug 9, 2023
36513b2
fix: lifetimes for rpc calls
prestwich Aug 9, 2023
e204269
feature: lifetime on rpccall
prestwich Aug 9, 2023
7a9726e
feature: BoxTransport
prestwich Aug 12, 2023
ba8fd02
chore: clippy
prestwich Aug 12, 2023
5cd4826
refactor: cow for jsonrpc params
prestwich Aug 14, 2023
7f8923b
fix: lint
prestwich Aug 19, 2023
047ba1d
refactor: rename to boxed
prestwich Aug 19, 2023
c5ce15b
docs and misc convenience
prestwich Aug 21, 2023
b7fbff4
refactor: docs and cleanup
prestwich Aug 21, 2023
7173fcc
docs: more of em
prestwich Aug 21, 2023
ee69008
refactor: seal transport
prestwich Aug 21, 2023
5770e67
feature: seal transport
prestwich Aug 21, 2023
0c6b2c9
rename middleware to provider
prestwich Aug 21, 2023
8a6a838
chore: remove dead code
prestwich Aug 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,32 @@ edition = "2021"
rust-version = "1.65"
authors = ["Alloy Contributors"]
license = "MIT OR Apache-2.0"
homepage = "https://github.com/ethers-rs/next"
repository = "https://github.com/ethers-rs/next"
homepage = "https://github.com/alloy-rs/next"
repository = "https://github.com/alloy-rs/next"
exclude = ["benches/", "tests/"]

[workspace.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[workspace.dependencies]
[workspace.dependencies]

alloy-transports = { path = "crates/transports" }
alloy-network = { path = "crates/network" }

alloy-primitives = { version = "0.2.0", features = ["serde"] }
alloy-rlp = "0.3.0"

# futures
futures-channel = "0.3"
futures-util = "0.3"

# jsonrpsee-types
jsonrpsee-types = "0.16"

# serde
serde = { version = "1.0", default-features = false, features = ["alloc"] }
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }

# thiserror
thiserror = "1.0"
16 changes: 16 additions & 0 deletions crates/network/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "network"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
alloy-primitives.workspace = true
alloy-rlp.workspace = true

alloy-transports.workspace = true

serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
236 changes: 236 additions & 0 deletions crates/network/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
use std::{future::Future, pin::Pin};

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;
}

pub trait Network: Sized + Send + Sync + 'static {
#[doc(hidden)]
const __ENFORCE_ZST: () = assert!(
// This ensures that the network is a zero-sized type
std::mem::size_of::<Self>() == 0,
"Network must be a zero-sized type"
);

// argument for `eth_sendTransaction`
type Transaction: Transaction + RpcParam;

// return for `eth_getTransaction`
type TransactionRespose: RpcResp;

// return for `eth_getTransactionReceipt`
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>
prestwich marked this conversation as resolved.
Show resolved Hide resolved
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;

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())
}
}
9 changes: 9 additions & 0 deletions crates/transports/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,12 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
base64 = "0.21.0"
reqwest = { version = "0.11.18", features = ["serde_json", "json"] }

futures-channel.workspace = true
jsonrpsee-types.workspace = true
serde.workspace = true
serde_json = { workspace = true, features = ["raw_value"] }
thiserror.workspace = true

Loading