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