Skip to main content

xrpl/models/ledger/objects/
mod.rs

1pub mod account_root;
2pub mod amendments;
3pub mod amm;
4pub mod bridge;
5pub mod check;
6pub mod credential;
7pub mod deposit_preauth;
8pub mod did;
9pub mod directory_node;
10pub mod escrow;
11pub mod fee_settings;
12pub mod ledger_hashes;
13pub mod mptoken;
14pub mod mptoken_issuance;
15pub mod negative_unl;
16pub mod nftoken_offer;
17pub mod nftoken_page;
18pub mod offer;
19pub mod oracle;
20pub mod pay_channel;
21pub mod permissioned_domain;
22pub mod ripple_state;
23pub mod signer_list;
24pub mod ticket;
25pub mod vault;
26pub mod xchain_owned_claim_id;
27pub mod xchain_owned_create_account_claim_id;
28
29use account_root::AccountRoot;
30use amendments::Amendments;
31use amm::AMM;
32use bridge::Bridge;
33use check::Check;
34use credential::Credential;
35use deposit_preauth::DepositPreauth;
36use derive_new::new;
37use did::DID;
38use directory_node::DirectoryNode;
39use escrow::Escrow;
40use fee_settings::FeeSettings;
41use ledger_hashes::LedgerHashes;
42use mptoken::MPToken;
43use mptoken_issuance::MPTokenIssuance;
44use negative_unl::NegativeUNL;
45use nftoken_offer::NFTokenOffer;
46use nftoken_page::NFTokenPage;
47use offer::Offer;
48use oracle::Oracle;
49use pay_channel::PayChannel;
50use permissioned_domain::PermissionedDomain;
51use ripple_state::RippleState;
52use signer_list::SignerList;
53use strum::IntoEnumIterator;
54
55use alloc::borrow::Cow;
56use serde::{Deserialize, Serialize};
57use serde_with::skip_serializing_none;
58use strum_macros::Display;
59use ticket::Ticket;
60use vault::Vault;
61use xchain_owned_claim_id::XChainOwnedClaimID;
62use xchain_owned_create_account_claim_id::XChainOwnedCreateAccountClaimID;
63
64use crate::_serde::lgr_obj_flags;
65use crate::models::{Amount, FlagCollection};
66
67#[derive(Debug, Clone, Serialize, Deserialize, Display, PartialEq, Eq)]
68pub enum LedgerEntryType {
69    AccountRoot = 0x0061,
70    Amendments = 0x0066,
71    AMM = 0x0079,
72    Bridge = 0x0069,
73    Check = 0x0043,
74    DID = 0x0049,
75    Credential = 0x0081,
76    DepositPreauth = 0x0070,
77    DirectoryNode = 0x0064,
78    Escrow = 0x0075,
79    FeeSettings = 0x0073,
80    LedgerHashes = 0x0068,
81    MPToken = 0x007F,
82    MPTokenIssuance = 0x007E,
83    NegativeUNL = 0x004E,
84    NFTokenOffer = 0x0037,
85    NFTokenPage = 0x0050,
86    Offer = 0x006F,
87    Oracle = 0x0080,
88    PayChannel = 0x0078,
89    PermissionedDomain = 0x0082,
90    RippleState = 0x0072,
91    SignerList = 0x0053,
92    Ticket = 0x0054,
93    Vault = 0x0084,
94    XChainOwnedClaimID = 0x0071,
95    XChainOwnedCreateAccountClaimID = 0x0074,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
99pub enum LedgerEntry<'a> {
100    AccountRoot(AccountRoot<'a>),
101    Amendments(Amendments<'a>),
102    AMM(AMM<'a>),
103    Bridge(Bridge<'a>),
104    Check(Check<'a>),
105    DID(DID<'a>),
106    Credential(Credential<'a>),
107    DepositPreauth(DepositPreauth<'a>),
108    DirectoryNode(DirectoryNode<'a>),
109    Escrow(Escrow<'a>),
110    FeeSettings(FeeSettings<'a>),
111    LedgerHashes(LedgerHashes<'a>),
112    MPToken(MPToken<'a>),
113    MPTokenIssuance(MPTokenIssuance<'a>),
114    NegativeUNL(NegativeUNL<'a>),
115    NFTokenOffer(NFTokenOffer<'a>),
116    NFTokenPage(NFTokenPage<'a>),
117    Offer(Offer<'a>),
118    Oracle(Oracle<'a>),
119    PayChannel(PayChannel<'a>),
120    PermissionedDomain(PermissionedDomain<'a>),
121    RippleState(RippleState<'a>),
122    SignerList(SignerList<'a>),
123    Ticket(Ticket<'a>),
124    Vault(Vault<'a>),
125    XChainOwnedClaimID(XChainOwnedClaimID<'a>),
126    XChainOwnedCreateAccountClaimID(XChainOwnedCreateAccountClaimID<'a>),
127}
128
129#[skip_serializing_none]
130#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
131#[serde(rename_all = "PascalCase")]
132pub struct XChainClaimProofSig<'a> {
133    pub amount: Amount<'a>,
134    pub attestation_reward_account: Cow<'a, str>,
135    pub attestation_signer_account: Cow<'a, str>,
136    pub destination: Cow<'a, str>,
137    pub public_key: Cow<'a, str>,
138    pub was_locking_chain_send: u8,
139}
140
141/// The base fields for all ledger object models.
142///
143/// See Ledger Object Common Fields:
144/// `<https://xrpl.org/ledger-entry-common-fields.html>`
145#[skip_serializing_none]
146#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, new)]
147#[serde(rename_all = "PascalCase")]
148pub struct CommonFields<'a, F>
149where
150    F: IntoEnumIterator + Serialize + core::fmt::Debug,
151{
152    /// A bit-map of boolean flags enabled for this account.
153    #[serde(with = "lgr_obj_flags")]
154    pub flags: FlagCollection<F>,
155    /// The type of the ledger object.
156    pub ledger_entry_type: LedgerEntryType,
157    /// The object ID of a single object to retrieve from the ledger, as a
158    /// 64-character (256-bit) hexadecimal string.
159    #[serde(rename = "index")]
160    pub index: Option<Cow<'a, str>>,
161    /// The object ID in transaction metadata of a single object to retrieve from the ledger, as a
162    /// 64-character (256-bit) hexadecimal string.
163    pub ledger_index: Option<Cow<'a, str>>,
164}
165
166impl<'a, T> LedgerObject<T> for CommonFields<'a, T>
167where
168    T: IntoEnumIterator + Serialize + PartialEq + core::fmt::Debug,
169{
170    fn has_flag(&self, flag: &T) -> bool {
171        self.flags.0.contains(flag)
172    }
173
174    fn get_ledger_entry_type(&self) -> LedgerEntryType {
175        self.ledger_entry_type.clone()
176    }
177}
178
179/// Standard functions for ledger objects.
180pub trait LedgerObject<T>
181where
182    T: IntoEnumIterator + Serialize,
183{
184    fn has_flag(&self, flag: &T) -> bool {
185        let _txn_flag = flag;
186        false
187    }
188
189    fn get_ledger_entry_type(&self) -> LedgerEntryType;
190}
191
192#[cfg(test)]
193mod tests {
194    use super::*;
195    use crate::models::amount::XRPAmount;
196    use crate::models::currency::XRP;
197    use crate::models::NoFlags;
198    use alloc::string::ToString;
199
200    #[test]
201    fn test_common_fields_new() {
202        let fields: CommonFields<'_, NoFlags> = CommonFields::new(
203            FlagCollection::default(),
204            LedgerEntryType::Bridge,
205            Some("AABBCC".into()),
206            Some("DDEEFF".into()),
207        );
208        assert_eq!(fields.get_ledger_entry_type(), LedgerEntryType::Bridge);
209        // The default impl on `LedgerObject` should return `false` here - no
210        // flag set is true. Pull a flag from the enum to satisfy IntoEnumIter.
211        // Because NoFlags has no variants, simply check the trait wiring works.
212        assert_eq!(fields.flags.0.len(), 0);
213    }
214
215    #[test]
216    fn test_ledger_entry_type_display() {
217        // The Display impl is auto-derived from `strum_macros::Display`.
218        assert_eq!(LedgerEntryType::AccountRoot.to_string(), "AccountRoot");
219        assert_eq!(LedgerEntryType::Bridge.to_string(), "Bridge");
220        assert_eq!(
221            LedgerEntryType::XChainOwnedClaimID.to_string(),
222            "XChainOwnedClaimID"
223        );
224    }
225
226    #[test]
227    fn test_ledger_entry_enum_serde_round_trip() {
228        let bridge = Bridge::new(
229            Some("AABBCC".into()),
230            Some("DDEEFF".into()),
231            "rPV4mZjsXfH2HvUSPLNmqz1J8d3Lpv7tpe".into(),
232            XRPAmount::from("100"),
233            0,
234            0,
235            crate::models::XChainBridge {
236                locking_chain_door: "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4".into(),
237                locking_chain_issue: XRP::new().into(),
238                issuing_chain_door: "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh".into(),
239                issuing_chain_issue: XRP::new().into(),
240            },
241            "1".into(),
242            None,
243        );
244        let entry = LedgerEntry::Bridge(bridge);
245        let serialized = serde_json::to_string(&entry).unwrap();
246        // The enum is untagged-ish; default behaviour is externally tagged on
247        // variant name. Either way, round-trip must work for the same JSON.
248        let deserialized: LedgerEntry = serde_json::from_str(&serialized).unwrap();
249        assert_eq!(entry, deserialized);
250    }
251}