Skip to main content

xrpl_common_stdlib/types/
account_id.rs

1//! Account identifiers used throughout XRPL.
2//!
3//! This type wraps a 20-byte AccountID and is returned by many accessors.
4//! See also: <https://xrpl.org/docs/references/protocol/common-fields#accountid-fields>
5
6use crate::fields::decoder::{FieldDecoder, FromCurrentTx, FromLedger, decode_exact};
7use crate::types::decode_error::DecodeError;
8
9pub const ACCOUNT_ID_SIZE: usize = 20;
10
11/// A 20-byte account identifier on the XRP Ledger.
12///
13/// AccountIDs are derived from a public key and uniquely identify accounts on the ledger.
14/// They are used throughout XRPL for specifying senders, receivers, issuers, and other
15/// account-related fields.
16///
17/// ## Derived Traits
18///
19/// - `Copy`: Efficient for this 20-byte struct, enabling implicit copying
20/// - `PartialEq, Eq`: Enable comparisons and use in hash-based collections
21/// - `Debug, Clone`: Standard traits for development and consistency
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23#[repr(C)]
24pub struct AccountID(pub [u8; ACCOUNT_ID_SIZE]);
25
26impl From<[u8; ACCOUNT_ID_SIZE]> for AccountID {
27    fn from(value: [u8; ACCOUNT_ID_SIZE]) -> Self {
28        AccountID(value)
29    }
30}
31
32/// `FieldDecoder` for XRPL account identifiers: decodes a 20-byte buffer into an `AccountID`,
33/// failing if the host wrote a different number of bytes.
34impl FieldDecoder for AccountID {
35    type Buffer = [u8; ACCOUNT_ID_SIZE];
36
37    #[inline]
38    fn empty_buffer() -> Self::Buffer {
39        [0u8; ACCOUNT_ID_SIZE]
40    }
41
42    #[inline]
43    fn decode(buf: Self::Buffer, bytes_written: usize) -> core::result::Result<Self, DecodeError> {
44        decode_exact(buf, bytes_written)
45    }
46}
47
48impl FromCurrentTx for AccountID {}
49impl FromLedger for AccountID {}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn test_account_id_byte_order_preserved() {
57        // Test with distinct byte values to verify no byte swapping
58        let mut bytes = [0u8; ACCOUNT_ID_SIZE];
59        for (i, byte) in bytes.iter_mut().enumerate() {
60            *byte = i as u8;
61        }
62
63        let account_id = AccountID::from(bytes);
64
65        // Verify each byte is in the correct position
66        for i in 0..ACCOUNT_ID_SIZE {
67            assert_eq!(account_id.0[i], i as u8);
68        }
69    }
70}