alloy_provider/ext/
net.rs

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
//! This module extends the Ethereum JSON-RPC provider with the Net namespace's RPC methods.
use crate::Provider;
use alloy_network::Network;
use alloy_transport::{Transport, TransportResult};

/// Net namespace rpc interface that provides access to network information of the node.
#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
pub trait NetApi<N, T>: Send + Sync {
    /// Returns a `bool` indicating whether or not the node is listening for network connections.
    async fn net_listening(&self) -> TransportResult<bool>;
    /// Returns the number of peers connected to the node.
    async fn net_peer_count(&self) -> TransportResult<u64>;
    /// Returns the network ID (e.g. 1 for mainnet).
    async fn net_version(&self) -> TransportResult<u64>;
}

#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
impl<N, T, P> NetApi<N, T> for P
where
    N: Network,
    T: Transport + Clone,
    P: Provider<T, N>,
{
    async fn net_listening(&self) -> TransportResult<bool> {
        self.client().request_noparams("net_listening").await
    }

    async fn net_peer_count(&self) -> TransportResult<u64> {
        self.client().request_noparams("net_peerCount").map_resp(crate::utils::convert_u64).await
    }

    async fn net_version(&self) -> TransportResult<u64> {
        self.client().request_noparams("net_version").map_resp(crate::utils::convert_u64).await
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::{ext::test::async_ci_only, ProviderBuilder};
    use alloy_node_bindings::{utils::run_with_tempdir, Geth};

    #[tokio::test]
    async fn call_net_version() {
        async_ci_only(|| async move {
            run_with_tempdir("geth-test-", |temp_dir| async move {
                let geth = Geth::new().disable_discovery().data_dir(temp_dir).spawn();
                let provider = ProviderBuilder::new().on_http(geth.endpoint_url());

                let version =
                    provider.net_version().await.expect("net_version call should succeed");
                assert_eq!(version, 1);
            })
            .await;
        })
        .await;
    }

    #[tokio::test]
    async fn call_net_peer_count() {
        async_ci_only(|| async move {
            run_with_tempdir("geth-test-", |temp_dir| async move {
                let geth = Geth::new().disable_discovery().data_dir(temp_dir).spawn();
                let provider = ProviderBuilder::new().on_http(geth.endpoint_url());

                let count =
                    provider.net_peer_count().await.expect("net_peerCount call should succeed");
                assert_eq!(count, 0);
            })
            .await;
        })
        .await;
    }

    #[tokio::test]
    async fn call_net_listening() {
        async_ci_only(|| async move {
            run_with_tempdir("geth-test-", |temp_dir| async move {
                let geth = Geth::new().disable_discovery().data_dir(temp_dir).spawn();
                let provider = ProviderBuilder::new().on_http(geth.endpoint_url());

                let listening =
                    provider.net_listening().await.expect("net_listening call should succeed");
                assert!(listening);
            })
            .await;
        })
        .await;
    }
}