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