Skip to main content

alloy_provider/layers/
block_id.rs

1use crate::{EthCall, Provider, ProviderLayer, RootProvider, RpcWithBlock};
2use alloy_eips::BlockId;
3use alloy_network::Network;
4use alloy_primitives::{Address, Bytes, StorageKey, StorageValue, U256, U64};
5use alloy_rpc_types_eth::{
6    simulate::{SimulatePayload, SimulatedBlock},
7    AccessListResult, EIP1186AccountProofResponse, StorageValuesRequest, StorageValuesResponse,
8};
9use std::marker::PhantomData;
10
11/// A layer that sets a default [`BlockId`] for RPC methods that support block parameters.
12///
13/// This layer affects the following methods:
14/// - `eth_call`
15/// - `eth_estimateGas`
16/// - `eth_simulateV1`
17/// - `eth_createAccessList`
18/// - `eth_getAccountInfo`
19/// - `eth_getAccount`
20/// - `eth_getBalance`
21/// - `eth_getCode`
22/// - `eth_getProof`
23/// - `eth_getStorageAt`
24/// - `eth_getTransactionCount`
25#[derive(Debug, Clone, Copy)]
26pub struct BlockIdLayer {
27    block_id: BlockId,
28}
29
30impl BlockIdLayer {
31    /// Creates a new layer with the given block ID.
32    pub const fn new(block_id: BlockId) -> Self {
33        Self { block_id }
34    }
35}
36
37impl From<BlockId> for BlockIdLayer {
38    fn from(block_id: BlockId) -> Self {
39        Self::new(block_id)
40    }
41}
42
43impl<P, N> ProviderLayer<P, N> for BlockIdLayer
44where
45    P: Provider<N>,
46    N: Network,
47{
48    type Provider = BlockIdProvider<P, N>;
49
50    fn layer(&self, inner: P) -> Self::Provider {
51        BlockIdProvider::new(inner, self.block_id)
52    }
53}
54
55/// A provider that uses a configured default [`BlockId`].
56#[derive(Clone, Debug)]
57pub struct BlockIdProvider<P, N = alloy_network::Ethereum> {
58    inner: P,
59    block_id: BlockId,
60    _marker: PhantomData<N>,
61}
62
63impl<P: Provider<N>, N: Network> BlockIdProvider<P, N> {
64    /// Creates a new provider with the given block ID.
65    pub const fn new(inner: P, block_id: BlockId) -> Self {
66        Self { inner, block_id, _marker: PhantomData }
67    }
68}
69
70impl<P: Provider<N>, N: Network> Provider<N> for BlockIdProvider<P, N> {
71    #[inline(always)]
72    fn root(&self) -> &RootProvider<N> {
73        self.inner.root()
74    }
75
76    fn call(&self, tx: N::TransactionRequest) -> EthCall<N, Bytes> {
77        EthCall::call(self.weak_client(), tx).block(self.block_id)
78    }
79
80    fn estimate_gas(&self, tx: N::TransactionRequest) -> EthCall<N, U64, u64> {
81        EthCall::gas_estimate(self.weak_client(), tx)
82            .block(self.block_id)
83            .map_resp(crate::utils::convert_u64)
84    }
85
86    fn simulate<'req>(
87        &self,
88        payload: &'req SimulatePayload,
89    ) -> RpcWithBlock<&'req SimulatePayload, Vec<SimulatedBlock<N::BlockResponse>>> {
90        self.inner.simulate(payload).block_id(self.block_id)
91    }
92
93    fn create_access_list<'a>(
94        &self,
95        request: &'a N::TransactionRequest,
96    ) -> RpcWithBlock<&'a N::TransactionRequest, AccessListResult> {
97        self.inner.create_access_list(request).block_id(self.block_id)
98    }
99
100    fn get_account_info(
101        &self,
102        address: Address,
103    ) -> RpcWithBlock<Address, alloy_rpc_types_eth::AccountInfo> {
104        self.inner.get_account_info(address).block_id(self.block_id)
105    }
106
107    fn get_account(&self, address: Address) -> RpcWithBlock<Address, alloy_consensus::TrieAccount> {
108        self.inner.get_account(address).block_id(self.block_id)
109    }
110
111    fn get_balance(&self, address: Address) -> RpcWithBlock<Address, U256, U256> {
112        self.inner.get_balance(address).block_id(self.block_id)
113    }
114
115    fn get_code_at(&self, address: Address) -> RpcWithBlock<Address, Bytes> {
116        self.inner.get_code_at(address).block_id(self.block_id)
117    }
118
119    fn get_proof(
120        &self,
121        address: Address,
122        keys: Vec<StorageKey>,
123    ) -> RpcWithBlock<(Address, Vec<StorageKey>), EIP1186AccountProofResponse> {
124        self.inner.get_proof(address, keys).block_id(self.block_id)
125    }
126
127    fn get_storage_at(
128        &self,
129        address: Address,
130        key: U256,
131    ) -> RpcWithBlock<(Address, U256), StorageValue> {
132        self.inner.get_storage_at(address, key).block_id(self.block_id)
133    }
134
135    fn get_storage_values(
136        &self,
137        requests: StorageValuesRequest,
138    ) -> RpcWithBlock<(StorageValuesRequest,), StorageValuesResponse> {
139        self.inner.get_storage_values(requests).block_id(self.block_id)
140    }
141
142    fn get_transaction_count(
143        &self,
144        address: Address,
145    ) -> RpcWithBlock<Address, U64, u64, fn(U64) -> u64> {
146        self.inner.get_transaction_count(address).block_id(self.block_id)
147    }
148}