eth_prices/network/mod.rs
1/*!
2Network timekeeping for multi-chain quoting.
3
4`eth-prices` splits network state into two complementary types:
5
6- [`NetworkTime`] — a single point-in-time on one network (EVM block or fiat timestamp).
7- [`NetworkInstant`] — a snapshot of multiple network times, keyed by [`NetworkId`].
8
9Because a single route can hop across different chains (e.g. swap on Ethereum, bridge to
10Arbitrum, swap again), the `Quoter::rate` method always receives a
11[`NetworkInstant`] so each step can look up the correct provider and block height.
12
13# Construction
14
15There are two entry points:
16
17**1. From a single network** — use [`NetworkTime::instant()`]:
18
19```rust,ignore
20use eth_prices::network::NetworkTime;
21use alloy::primitives::BlockNumber;
22
23let network = NetworkTime::EVM(1, BlockNumber::from(20_000_000), provider).instant();
24```
25
26**2. From scratch using the builder pattern** — chain multiple
27[`NetworkInstant`] builder methods together:
28
29```rust,ignore
30use eth_prices::network::NetworkInstant;
31
32let networks = NetworkInstant::default()
33 .with_fiat_timestamp(1_700_000_000)
34 .with_evm_block(1, 20_000_000, eth_provider)
35 .with_evm_block(42161, 200_000_000, arb_provider);
36```
37
38The async builders `with_evm_latest` and `with_evm_provider` fetch the latest block
39height from the RPC before inserting:
40
41```rust,ignore
42let networks = NetworkInstant::default()
43 .with_evm_latest(1, eth_provider)
44 .await?
45 .with_fiat_timestamp(now);
46```
47*/
48
49pub mod instant;
50pub mod time;
51
52use alloy::providers::Provider;
53pub use instant::NetworkInstant;
54pub use time::NetworkTime;
55
56use crate::{EthPricesError, provider::RpcProvider};
57
58#[derive(Debug, Clone, PartialEq, Eq, Hash)]
59pub enum Network {
60 EVM(NetworkId),
61 Fiat,
62}
63
64impl Network {
65 pub async fn from_provider(provider: &RpcProvider) -> Result<Self, EthPricesError> {
66 NetworkId::from_provider(provider).await.map(Network::EVM)
67 }
68}
69
70impl From<NetworkId> for Network {
71 fn from(network_id: NetworkId) -> Self {
72 Network::EVM(network_id)
73 }
74}
75
76impl From<&Network> for NetworkId {
77 fn from(network: &Network) -> Self {
78 match network {
79 Network::EVM(network_id) => network_id.clone(),
80 Network::Fiat => NetworkId(0),
81 }
82 }
83}
84
85#[derive(Debug, Clone, PartialEq, Eq, Hash)]
86pub struct NetworkId(pub u64);
87
88impl NetworkId {
89 pub async fn from_provider(provider: &RpcProvider) -> Result<Self, EthPricesError> {
90 provider
91 .get_chain_id()
92 .await
93 .map(NetworkId)
94 .map_err(EthPricesError::from)
95 }
96}
97
98impl From<&NetworkId> for Network {
99 fn from(network_id: &NetworkId) -> Self {
100 Network::EVM(network_id.clone())
101 }
102}
103
104impl From<u64> for NetworkId {
105 fn from(network_id: u64) -> Self {
106 NetworkId(network_id)
107 }
108}