soroban_sdk/
ledger.rs

1//! Ledger contains types for retrieving information about the current ledger.
2use crate::{env::internal, unwrap::UnwrapInfallible, BytesN, Env, TryIntoVal};
3
4/// Ledger retrieves information about the current ledger.
5///
6/// For more details about the ledger and the ledger header that the values in the Ledger are derived from, see:
7///  - <https://developers.stellar.org/docs/learn/encyclopedia/network-configuration/ledger-headers>
8///
9/// ### Examples
10///
11/// ```
12/// use soroban_sdk::Env;
13///
14/// # use soroban_sdk::{contract, contractimpl, BytesN};
15/// #
16/// # #[contract]
17/// # pub struct Contract;
18/// #
19/// # #[contractimpl]
20/// # impl Contract {
21/// #     pub fn f(env: Env) {
22/// let ledger = env.ledger();
23///
24/// let protocol_version = ledger.protocol_version();
25/// let sequence = ledger.sequence();
26/// let timestamp = ledger.timestamp();
27/// let network_id = ledger.network_id();
28/// #     }
29/// # }
30/// #
31/// # #[cfg(feature = "testutils")]
32/// # fn main() {
33/// #     let env = Env::default();
34/// #     let contract_id = env.register(Contract, ());
35/// #     ContractClient::new(&env, &contract_id).f();
36/// # }
37/// # #[cfg(not(feature = "testutils"))]
38/// # fn main() { }
39/// ```
40#[derive(Clone)]
41pub struct Ledger(Env);
42
43impl Ledger {
44    #[inline(always)]
45    pub(crate) fn env(&self) -> &Env {
46        &self.0
47    }
48
49    #[inline(always)]
50    pub(crate) fn new(env: &Env) -> Ledger {
51        Ledger(env.clone())
52    }
53
54    /// Returns the version of the protocol that the ledger created with.
55    pub fn protocol_version(&self) -> u32 {
56        internal::Env::get_ledger_version(self.env())
57            .unwrap_infallible()
58            .into()
59    }
60
61    /// Returns the sequence number of the ledger.
62    ///
63    /// The sequence number is a unique number for each ledger
64    /// that is sequential, incremented by one for each new ledger.
65    pub fn sequence(&self) -> u32 {
66        internal::Env::get_ledger_sequence(self.env())
67            .unwrap_infallible()
68            .into()
69    }
70
71    /// Returns the maximum ledger sequence number that data can live to.
72    #[doc(hidden)]
73    pub fn max_live_until_ledger(&self) -> u32 {
74        internal::Env::get_max_live_until_ledger(self.env())
75            .unwrap_infallible()
76            .into()
77    }
78
79    /// Returns a unix timestamp for when the ledger was closed.
80    ///
81    /// The timestamp is the number of seconds, excluding leap seconds, that
82    /// have elapsed since unix epoch. Unix epoch is January 1st, 1970, at
83    /// 00:00:00 UTC.
84    ///
85    /// For more details see:
86    ///  - <https://developers.stellar.org/docs/learn/encyclopedia/network-configuration/ledger-headers#close-time>
87    pub fn timestamp(&self) -> u64 {
88        internal::Env::get_ledger_timestamp(self.env())
89            .unwrap_infallible()
90            .try_into_val(self.env())
91            .unwrap()
92    }
93
94    /// Returns the network identifier.
95    ///
96    /// This is SHA-256 hash of the network passphrase, for example
97    /// for the Public Network this returns:
98    /// > SHA256(Public Global Stellar Network ; September 2015)
99    ///
100    /// Returns for the Test Network:
101    /// > SHA256(Test SDF Network ; September 2015)
102    pub fn network_id(&self) -> BytesN<32> {
103        let env = self.env();
104        let bin_obj = internal::Env::get_ledger_network_id(env).unwrap_infallible();
105        unsafe { BytesN::<32>::unchecked_new(env.clone(), bin_obj) }
106    }
107}
108
109#[cfg(any(test, feature = "testutils"))]
110use crate::testutils;
111
112#[cfg(any(test, feature = "testutils"))]
113#[cfg_attr(feature = "docs", doc(cfg(feature = "testutils")))]
114impl testutils::Ledger for Ledger {
115    fn set(&self, li: testutils::LedgerInfo) {
116        let env = self.env();
117        env.host().set_ledger_info(li).unwrap();
118    }
119
120    fn set_protocol_version(&self, protocol_version: u32) {
121        self.with_mut(|ledger_info| {
122            ledger_info.protocol_version = protocol_version;
123        });
124    }
125
126    fn set_sequence_number(&self, sequence_number: u32) {
127        self.with_mut(|ledger_info| {
128            ledger_info.sequence_number = sequence_number;
129        });
130    }
131
132    fn set_timestamp(&self, timestamp: u64) {
133        self.with_mut(|ledger_info| {
134            ledger_info.timestamp = timestamp;
135        });
136    }
137
138    fn set_network_id(&self, network_id: [u8; 32]) {
139        self.with_mut(|ledger_info| {
140            ledger_info.network_id = network_id;
141        });
142    }
143
144    fn set_base_reserve(&self, base_reserve: u32) {
145        self.with_mut(|ledger_info| {
146            ledger_info.base_reserve = base_reserve;
147        });
148    }
149
150    fn set_min_temp_entry_ttl(&self, min_temp_entry_ttl: u32) {
151        self.with_mut(|ledger_info| {
152            ledger_info.min_temp_entry_ttl = min_temp_entry_ttl;
153        });
154    }
155
156    fn set_min_persistent_entry_ttl(&self, min_persistent_entry_ttl: u32) {
157        self.with_mut(|ledger_info| {
158            ledger_info.min_persistent_entry_ttl = min_persistent_entry_ttl;
159        });
160    }
161
162    fn set_max_entry_ttl(&self, max_entry_ttl: u32) {
163        self.with_mut(|ledger_info| {
164            // For the sake of consistency across SDK methods,
165            // we always make  TTL values to not include the current ledger.
166            // The actual network setting in env expects this to include
167            // the current ledger, so we need to add 1 here.
168            ledger_info.max_entry_ttl = max_entry_ttl.saturating_add(1);
169        });
170    }
171
172    fn get(&self) -> testutils::LedgerInfo {
173        let env = self.env();
174        env.host().with_ledger_info(|li| Ok(li.clone())).unwrap()
175    }
176
177    fn with_mut<F>(&self, f: F)
178    where
179        F: FnMut(&mut internal::LedgerInfo),
180    {
181        let env = self.env();
182        env.host().with_mut_ledger_info(f).unwrap();
183    }
184}