1#![allow(
4 clippy::type_complexity,
5 clippy::wrong_self_convention,
6 clippy::single_match,
7 clippy::let_unit_value,
8 clippy::match_wild_err_arm
9)]
10#![warn(missing_docs)]
11#![recursion_limit = "256"]
13
14use jsonrpc_core as rpc;
15
16#[macro_use]
18pub extern crate futures;
19pub use futures::executor::{block_on, block_on_stream};
20
21pub use ethabi;
22
23#[macro_use]
26pub mod helpers;
27
28pub mod api;
29pub mod confirm;
30pub mod contract;
31pub mod error;
32pub mod signing;
33pub mod transports;
34pub mod types;
35
36pub use crate::{
37 api::Web3,
38 error::{Error, Result},
39};
40
41pub type RequestId = usize;
43
44pub trait Transport: std::fmt::Debug + Clone {
48 type Out: futures::Future<Output = error::Result<rpc::Value>>;
50
51 fn prepare(&self, method: &str, params: Vec<rpc::Value>) -> (RequestId, rpc::Call);
53
54 fn send(&self, id: RequestId, request: rpc::Call) -> Self::Out;
56
57 fn execute(&self, method: &str, params: Vec<rpc::Value>) -> Self::Out {
59 let (id, request) = self.prepare(method, params);
60 self.send(id, request)
61 }
62}
63
64pub trait BatchTransport: Transport {
66 type Batch: futures::Future<Output = error::Result<Vec<error::Result<rpc::Value>>>>;
68
69 fn send_batch<T>(&self, requests: T) -> Self::Batch
71 where
72 T: IntoIterator<Item = (RequestId, rpc::Call)>;
73}
74
75pub trait DuplexTransport: Transport {
77 type NotificationStream: futures::Stream<Item = rpc::Value>;
79
80 fn subscribe(&self, id: api::SubscriptionId) -> error::Result<Self::NotificationStream>;
82
83 fn unsubscribe(&self, id: api::SubscriptionId) -> error::Result<()>;
85}
86
87impl<X, T> Transport for X
88where
89 T: Transport + ?Sized,
90 X: std::ops::Deref<Target = T>,
91 X: std::fmt::Debug,
92 X: Clone,
93{
94 type Out = T::Out;
95
96 fn prepare(&self, method: &str, params: Vec<rpc::Value>) -> (RequestId, rpc::Call) {
97 (**self).prepare(method, params)
98 }
99
100 fn send(&self, id: RequestId, request: rpc::Call) -> Self::Out {
101 (**self).send(id, request)
102 }
103}
104
105impl<X, T> BatchTransport for X
106where
107 T: BatchTransport + ?Sized,
108 X: std::ops::Deref<Target = T>,
109 X: std::fmt::Debug,
110 X: Clone,
111{
112 type Batch = T::Batch;
113
114 fn send_batch<I>(&self, requests: I) -> Self::Batch
115 where
116 I: IntoIterator<Item = (RequestId, rpc::Call)>,
117 {
118 (**self).send_batch(requests)
119 }
120}
121
122impl<X, T> DuplexTransport for X
123where
124 T: DuplexTransport + ?Sized,
125 X: std::ops::Deref<Target = T>,
126 X: std::fmt::Debug,
127 X: Clone,
128{
129 type NotificationStream = T::NotificationStream;
130
131 fn subscribe(&self, id: api::SubscriptionId) -> error::Result<Self::NotificationStream> {
132 (**self).subscribe(id)
133 }
134
135 fn unsubscribe(&self, id: api::SubscriptionId) -> error::Result<()> {
136 (**self).unsubscribe(id)
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::{error, rpc, RequestId, Transport};
143
144 use crate::api::Web3;
145 use futures::future::BoxFuture;
146 use std::sync::Arc;
147
148 #[derive(Debug, Clone)]
149 struct FakeTransport;
150
151 impl Transport for FakeTransport {
152 type Out = BoxFuture<'static, error::Result<rpc::Value>>;
153
154 fn prepare(&self, _method: &str, _params: Vec<rpc::Value>) -> (RequestId, rpc::Call) {
155 unimplemented!()
156 }
157
158 fn send(&self, _id: RequestId, _request: rpc::Call) -> Self::Out {
159 unimplemented!()
160 }
161 }
162
163 #[test]
164 fn should_allow_to_use_arc_as_transport() {
165 let transport = Arc::new(FakeTransport);
166 let transport2 = transport.clone();
167
168 let _web3_1 = Web3::new(transport);
169 let _web3_2 = Web3::new(transport2);
170 }
171}