xrpl_wasm_std/core/ledger_objects/
mod.rs

1pub mod account_root;
2pub mod current_escrow;
3pub mod escrow;
4pub mod nft;
5pub mod traits;
6
7pub mod current_ledger_object {
8    use crate::core::types::account_id::{ACCOUNT_ID_SIZE, AccountID};
9    use crate::core::types::amount::token_amount::TokenAmount;
10    use crate::core::types::blob::Blob;
11    use crate::core::types::hash_256::{HASH256_SIZE, Hash256};
12    use crate::host::error_codes::{
13        match_result_code, match_result_code_with_expected_bytes,
14        match_result_code_with_expected_bytes_optional,
15    };
16    use crate::host::{Result, get_current_ledger_obj_field, to_non_optional};
17
18    /// Retrieves an `AccountID` field from the current ledger object.
19    ///
20    /// # Arguments
21    ///
22    /// * `field_code` - The field code identifying which field to retrieve
23    ///
24    /// # Returns
25    ///
26    /// Returns a `Result<AccountID>` where:
27    /// * `Ok(AccountID)` - The account identifier for the specified field
28    /// * `Err(Error)` - If the field cannot be retrieved or has unexpected size
29    #[inline(always)]
30    pub fn get_account_id_field(field_code: i32) -> Result<AccountID> {
31        let mut buffer = [0x00; ACCOUNT_ID_SIZE];
32
33        let result_code =
34            unsafe { get_current_ledger_obj_field(field_code, buffer.as_mut_ptr(), buffer.len()) };
35
36        match_result_code_with_expected_bytes(result_code, buffer.len(), || buffer.into())
37    }
38
39    /// Retrieves a `TokenAmount` field from the current ledger object.
40    ///
41    /// # Arguments
42    ///
43    /// * `field_code` - The field code identifying which field to retrieve
44    ///
45    /// # Returns
46    ///
47    /// Returns a `Result<TokenAmount>` where:
48    /// * `Ok(AccountID)` - The account identifier for the specified field
49    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
50    #[inline]
51    pub fn get_amount_field(field_code: i32) -> Result<TokenAmount> {
52        const BUFFER_SIZE: usize = 48usize;
53
54        let mut buffer = [0u8; BUFFER_SIZE]; // Enough to hold an Amount
55
56        let result_code =
57            unsafe { get_current_ledger_obj_field(field_code, buffer.as_mut_ptr(), BUFFER_SIZE) };
58
59        match_result_code(result_code, || TokenAmount::from(buffer))
60    }
61
62    /// Retrieves a `u16` field from the current ledger object.
63    ///
64    /// # Arguments
65    ///
66    /// * `field_code` - The field code identifying which field to retrieve
67    ///
68    /// # Returns
69    ///
70    /// Returns a `Result<TokenAmount>` where:
71    /// * `Ok(AccountID)` - The account identifier for the specified field
72    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
73    #[inline]
74    pub fn get_u16_field(field_code: i32) -> Result<u16> {
75        to_non_optional(get_u16_field_optional(field_code))
76    }
77
78    /// Retrieves an optionally present `u16` field from the current ledger object.
79    ///
80    /// # Arguments
81    ///
82    /// * `field_code` - The field code identifying which field to retrieve
83    ///
84    /// # Returns
85    ///
86    /// Returns a `Result<TokenAmount>` where:
87    /// * `Ok(AccountID)` - The account identifier for the specified field
88    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
89    #[inline]
90    pub fn get_u16_field_optional(field_code: i32) -> Result<Option<u16>> {
91        let mut value: u16 = 0; // <-- Initialize 8 bytes (only works due to little endian encoding in WASM and WAMR-host
92        let value_ptr: *mut u8 = (&mut value as *mut u16).cast::<u8>();
93
94        let result_code = unsafe { get_current_ledger_obj_field(field_code, value_ptr, 2) };
95
96        match_result_code_with_expected_bytes_optional(result_code, 2, || Some(value))
97    }
98
99    /// Retrieves a `u32` field from the current ledger object.
100    ///
101    /// # Arguments
102    ///
103    /// * `field_code` - The field code identifying which field to retrieve
104    ///
105    /// # Returns
106    ///
107    /// Returns a `Result<TokenAmount>` where:
108    /// * `Ok(AccountID)` - The account identifier for the specified field
109    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
110    #[inline]
111    pub fn get_u32_field(field_code: i32) -> Result<u32> {
112        to_non_optional(get_u32_field_optional(field_code))
113    }
114
115    /// Retrieves an optionally present `u32` field from the current ledger object.
116    ///
117    /// # Arguments
118    ///
119    /// * `field_code` - The field code identifying which field to retrieve
120    ///
121    /// # Returns
122    ///
123    /// Returns a `Result<TokenAmount>` where:
124    /// * `Ok(AccountID)` - The account identifier for the specified field
125    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
126    #[inline]
127    pub fn get_u32_field_optional(field_code: i32) -> Result<Option<u32>> {
128        let mut value: u32 = 0; // <-- Initialize 8 bytes (only works due to little endian encoding in WASM and WAMR-host
129        let value_ptr: *mut u8 = (&mut value as *mut u32).cast::<u8>();
130
131        let result_code = unsafe { get_current_ledger_obj_field(field_code, value_ptr, 4) };
132
133        match_result_code_with_expected_bytes_optional(result_code, 4, || Some(value))
134    }
135
136    /// Retrieves a `u64` field from the current ledger object.
137    ///
138    /// # Arguments
139    ///
140    /// * `field_code` - The field code identifying which AccountID field to retrieve
141    ///
142    /// # Returns
143    ///
144    /// Returns a `Result<TokenAmount>` where:
145    /// * `Ok(AccountID)` - The account identifier for the specified field
146    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
147    #[inline]
148    pub fn get_u64_field(field_code: i32) -> Result<u64> {
149        to_non_optional(get_u64_field_optional(field_code))
150    }
151
152    /// Retrieves an optionally present `u64` field from the current ledger object.
153    ///
154    /// # Arguments
155    ///
156    /// * `field_code` - The field code identifying which field to retrieve
157    ///
158    /// # Returns
159    ///
160    /// Returns a `Result<TokenAmount>` where:
161    /// * `Ok(AccountID)` - The account identifier for the specified field
162    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
163    #[inline]
164    pub fn get_u64_field_optional(field_code: i32) -> Result<Option<u64>> {
165        let mut value: u64 = 0u64; // <-- Initialize 8 bytes (only works due to little endian encoding in WASM and WAMR-host
166        let value_ptr: *mut u8 = (&mut value as *mut u64).cast::<u8>();
167
168        let result_code = unsafe { get_current_ledger_obj_field(field_code, value_ptr, 8) };
169
170        match_result_code_with_expected_bytes_optional(result_code, 8, || Some(value))
171    }
172
173    /// Retrieves a `Hash256` field from the current ledger object.
174    ///
175    /// # Arguments
176    ///
177    /// * `field_code` - The field code identifying which AccountID field to retrieve
178    ///
179    /// # Returns
180    ///
181    /// Returns a `Result<TokenAmount>` where:
182    /// * `Ok(AccountID)` - The account identifier for the specified field
183    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
184    #[inline]
185    pub fn get_hash_256_field(field_code: i32) -> Result<Hash256> {
186        to_non_optional(get_hash_256_field_optional(field_code))
187    }
188
189    /// Retrieves an optionally present `Hash256` field from the current ledger object.
190    ///
191    /// # Arguments
192    ///
193    /// * `field_code` - The field code identifying which field to retrieve
194    ///
195    /// # Returns
196    ///
197    /// Returns a `Result<TokenAmount>` where:
198    /// * `Ok(AccountID)` - The account identifier for the specified field
199    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
200    #[inline]
201    pub fn get_hash_256_field_optional(field_code: i32) -> Result<Option<Hash256>> {
202        let mut buffer = [0u8; HASH256_SIZE]; // Enough to hold 256 bits (32 bytes)
203
204        let result_code =
205            unsafe { get_current_ledger_obj_field(field_code, buffer.as_mut_ptr(), buffer.len()) };
206
207        match_result_code_with_expected_bytes(result_code, HASH256_SIZE, || {
208            Some(Hash256(buffer)) // <-- Move the buffer into a Hash256
209        })
210    }
211
212    /// Retrieves a `Blob` field from the current ledger object.
213    ///
214    /// # Arguments
215    ///
216    /// * `field_code` - The field code identifying which AccountID field to retrieve
217    ///
218    /// # Returns
219    ///
220    /// Returns a `Result<TokenAmount>` where:
221    /// * `Ok(AccountID)` - The account identifier for the specified field
222    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
223    #[inline]
224    pub fn get_blob_field(field_code: i32) -> Result<Blob> {
225        to_non_optional(get_blob_field_optional(field_code))
226    }
227
228    /// Retrieves an optionally present `Blob` field from the current ledger object.
229    ///
230    /// # Arguments
231    ///
232    /// * `field_code` - The field code identifying which field to retrieve
233    ///
234    /// # Returns
235    ///
236    /// Returns a `Result<TokenAmount>` where:
237    /// * `Ok(AccountID)` - The account identifier for the specified field
238    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
239    #[inline]
240    pub fn get_blob_field_optional(field_code: i32) -> Result<Option<Blob>> {
241        let mut buffer = [0u8; 1024]; // Enough to hold the largest field, which is a memo.
242
243        let result_code =
244            unsafe { get_current_ledger_obj_field(field_code, buffer.as_mut_ptr(), buffer.len()) };
245
246        match_result_code(result_code, || {
247            Some(Blob {
248                data: buffer,
249                len: result_code as usize,
250            })
251        })
252    }
253}
254
255pub mod ledger_object {
256    use crate::core::types::account_id::{ACCOUNT_ID_SIZE, AccountID};
257    use crate::core::types::amount::token_amount::TokenAmount;
258    use crate::core::types::blob::Blob;
259    use crate::core::types::hash_256::{HASH256_SIZE, Hash256};
260    use crate::core::types::uint_128::{UINT128_SIZE, UInt128};
261    use crate::host::error_codes::{
262        match_result_code, match_result_code_optional, match_result_code_with_expected_bytes,
263        match_result_code_with_expected_bytes_optional,
264    };
265    use crate::host::{Result, get_ledger_obj_field, to_non_optional};
266
267    /// Retrieves an AccountID field from the current ledger object.
268    ///
269    /// # Arguments
270    ///
271    /// * `field_code` - The field code identifying which AccountID field to retrieve
272    ///
273    /// # Returns
274    ///
275    /// Returns a `Result<AccountID>` where:
276    /// * `Ok(AccountID)` - The account identifier for the specified field
277    /// * `Err(Error)` - If the field cannot be retrieved or has unexpected size
278    #[inline]
279    pub fn get_account_id_field(register_num: i32, field_code: i32) -> Result<AccountID> {
280        to_non_optional(get_account_id_field_optional(register_num, field_code))
281    }
282
283    pub fn get_account_id_field_optional(
284        register_num: i32,
285        field_code: i32,
286    ) -> Result<Option<AccountID>> {
287        let mut buffer = [0x00; ACCOUNT_ID_SIZE];
288
289        let result_code = unsafe {
290            get_ledger_obj_field(register_num, field_code, buffer.as_mut_ptr(), buffer.len())
291        };
292
293        match_result_code_with_expected_bytes_optional(result_code, buffer.len(), || {
294            let account_id: AccountID = buffer.into();
295            Some(account_id)
296        })
297    }
298
299    /// Retrieves a `TokenAmount` field from a specified ledger object.
300    ///
301    /// This function retrieves a token amount field from a ledger object stored in a register.
302    /// It wraps the optional variant and returns an error if the field is not present.
303    ///
304    /// # Arguments
305    ///
306    /// * `register_num` - The register number holding the ledger object to look for data in
307    /// * `field_code` - The field code identifying which TokenAmount field to retrieve
308    ///
309    /// # Returns
310    ///
311    /// Returns a `Result<TokenAmount>` where:
312    /// * `Ok(TokenAmount)` - The token amount for the specified field, which can be XRP, IOU, or MPT
313    /// * `Err(Error)` - If the field cannot be retrieved, is not present, or has an unexpected format
314    #[inline]
315    pub fn get_amount_field(register_num: i32, field_code: i32) -> Result<TokenAmount> {
316        to_non_optional(get_amount_field_optional(register_num, field_code))
317    }
318
319    /// Retrieves an optionally present `TokenAmount` field from a specified ledger object.
320    ///
321    /// This function attempts to retrieve a token amount field from a ledger object stored in a register.
322    /// Unlike the non-optional variant, this function returns `None` if the field is not present,
323    /// rather than returning an error.
324    ///
325    /// # Arguments
326    ///
327    /// * `register_num` - The register number holding the ledger object to look for data in
328    /// * `field_code` - The field code identifying which TokenAmount field to retrieve
329    ///
330    /// # Returns
331    ///
332    /// Returns a `Result<Option<TokenAmount>>` where:
333    /// * `Ok(Some(TokenAmount))` - The token amount for the specified field, which can be XRP, IOU, or MPT
334    /// * `Ok(None)` - If the field is not present in the ledger object
335    /// * `Err(Error)` - If the field retrieval operation failed or the data has an unexpected format
336    #[inline]
337    pub fn get_amount_field_optional(
338        register_num: i32,
339        field_code: i32,
340    ) -> Result<Option<TokenAmount>> {
341        const BUFFER_SIZE: usize = 48usize;
342
343        let mut buffer = [0u8; BUFFER_SIZE]; // Enough to hold an Amount
344
345        let result_code = unsafe {
346            get_ledger_obj_field(register_num, field_code, buffer.as_mut_ptr(), BUFFER_SIZE)
347        };
348
349        match_result_code_optional(result_code, || Some(TokenAmount::from(buffer)))
350    }
351
352    /// Retrieves a `u16` field from the specified ledger object.
353    ///
354    /// # Arguments
355    ///
356    /// * `register_num` - The register number holding the ledger object to look for data in.
357    /// * `field_code` - The field code identifying which field to retrieve
358    ///
359    /// # Returns
360    ///
361    /// Returns a `Result<TokenAmount>` where:
362    /// * `Ok(AccountID)` - The account identifier for the specified field
363    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
364    #[inline]
365    pub fn get_u16_field(register_num: i32, field_code: i32) -> Result<u16> {
366        to_non_optional(get_u16_field_optional(register_num, field_code))
367    }
368
369    /// Retrieves an optionally present `u16` field from the specified ledger object.
370    ///
371    /// # Arguments
372    ///
373    /// * `register_num` - The register number holding the ledger object to look for data in.
374    /// * `field_code` - The field code identifying which field to retrieve
375    ///
376    /// # Returns
377    ///
378    /// Returns a `Result<TokenAmount>` where:
379    /// * `Ok(AccountID)` - The account identifier for the specified field
380    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
381    #[inline]
382    pub fn get_u16_field_optional(register_num: i32, field_code: i32) -> Result<Option<u16>> {
383        let mut value: u16 = 0; // <-- Initialize 8 bytes (only works due to little endian encoding in WASM and WAMR-host
384        let value_ptr: *mut u8 = (&mut value as *mut u16).cast::<u8>();
385
386        let result_code = unsafe { get_ledger_obj_field(register_num, field_code, value_ptr, 2) };
387
388        match_result_code_with_expected_bytes_optional(result_code, 2, || Some(value))
389    }
390
391    /// Retrieves a `u32` field from the specified ledger object.
392    ///
393    /// # Arguments
394    ///
395    /// * `register_num` - The register number holding the ledger object to look for data in.
396    /// * `field_code` - The field code identifying which AccountID field to retrieve
397    ///
398    /// # Returns
399    ///
400    /// Returns a `Result<TokenAmount>` where:
401    /// * `Ok(AccountID)` - The account identifier for the specified field
402    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
403    #[inline]
404    pub fn get_u32_field(register_num: i32, field_code: i32) -> Result<u32> {
405        to_non_optional(get_u32_field_optional(register_num, field_code))
406    }
407
408    /// Retrieves an optionally present `u32` field from the specified ledger object.
409    ///
410    /// # Arguments
411    ///
412    /// * `register_num` - The register number holding the ledger object to look for data in.
413    /// * `field_code` - The field code identifying which field to retrieve
414    ///
415    /// # Returns
416    ///
417    /// Returns a `Result<TokenAmount>` where:
418    /// * `Ok(AccountID)` - The account identifier for the specified field
419    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
420    #[inline]
421    pub fn get_u32_field_optional(register_num: i32, field_code: i32) -> Result<Option<u32>> {
422        let mut value: u32 = 0; // <-- Initialize 8 bytes (only works due to little endian encoding in WASM and WAMR-host
423        let value_ptr: *mut u8 = (&mut value as *mut u32).cast::<u8>();
424
425        let result_code = unsafe { get_ledger_obj_field(register_num, field_code, value_ptr, 4) };
426
427        match_result_code_with_expected_bytes_optional(result_code, 4, || Some(value))
428    }
429
430    /// Retrieves a `u64` field from the specified ledger object.
431    ///
432    /// # Arguments
433    ///
434    /// * `register_num` - The register number holding the ledger object to look for data in.
435    /// * `field_code` - The field code identifying which AccountID field to retrieve
436    ///
437    /// # Returns
438    ///
439    /// Returns a `Result<TokenAmount>` where:
440    /// * `Ok(AccountID)` - The account identifier for the specified field
441    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
442    #[inline]
443    pub fn get_u64_field(register_num: i32, field_code: i32) -> Result<u64> {
444        to_non_optional(get_u64_field_optional(register_num, field_code))
445    }
446
447    /// Retrieves an optionally present `u64` field from the specified ledger object.
448    ///
449    /// # Arguments
450    ///
451    /// * `register_num` - The register number holding the ledger object to look for data in.
452    /// * `field_code` - The field code identifying which field to retrieve
453    ///
454    /// # Returns
455    ///
456    /// Returns a `Result<TokenAmount>` where:
457    /// * `Ok(AccountID)` - The account identifier for the specified field
458    /// * `Err(Error)` - If the field cannot be retrieved or has an unexpected size.
459    #[inline]
460    pub fn get_u64_field_optional(register_num: i32, field_code: i32) -> Result<Option<u64>> {
461        let mut value: u64 = 0; // <-- Initialize 8 bytes (only works due to little endian encoding in WASM and WAMR-host
462        let value_ptr: *mut u8 = (&mut value as *mut u64).cast::<u8>();
463
464        let result_code = unsafe { get_ledger_obj_field(register_num, field_code, value_ptr, 8) };
465
466        match_result_code_with_expected_bytes_optional(result_code, 4, || Some(value))
467    }
468
469    #[inline]
470    pub fn get_uint_128_field(register_num: i32, field_code: i32) -> Result<UInt128> {
471        to_non_optional(get_uint_128_field_optional(register_num, field_code))
472    }
473
474    #[inline]
475    pub fn get_uint_128_field_optional(
476        register_num: i32,
477        field_code: i32,
478    ) -> Result<Option<UInt128>> {
479        let mut buffer = [0u8; UINT128_SIZE]; // Enough to hold 128 bits (16 bytes)
480
481        let result_code = unsafe {
482            get_ledger_obj_field(register_num, field_code, buffer.as_mut_ptr(), buffer.len())
483        };
484
485        match_result_code_with_expected_bytes(result_code, UINT128_SIZE, || {
486            Some(UInt128(buffer)) // <-- Move the buffer into a UInt128
487        })
488    }
489
490    #[inline]
491    pub fn get_hash_256_field(register_num: i32, field_code: i32) -> Result<Hash256> {
492        to_non_optional(get_hash_256_field_optional(register_num, field_code))
493    }
494
495    #[inline]
496    pub fn get_hash_256_field_optional(
497        register_num: i32,
498        field_code: i32,
499    ) -> Result<Option<Hash256>> {
500        let mut buffer = [0u8; HASH256_SIZE]; // Enough to hold 256 bits (32 bytes)
501
502        let result_code = unsafe {
503            get_ledger_obj_field(register_num, field_code, buffer.as_mut_ptr(), buffer.len())
504        };
505
506        match_result_code_with_expected_bytes(result_code, HASH256_SIZE, || {
507            Some(Hash256(buffer)) // <-- Move the buffer into an Hash256
508        })
509    }
510
511    #[inline]
512    pub fn get_blob_field(register_num: i32, field_code: i32) -> Result<Blob> {
513        to_non_optional(get_blob_field_optional(register_num, field_code))
514    }
515
516    #[inline]
517    pub fn get_blob_field_optional(register_num: i32, field_code: i32) -> Result<Option<Blob>> {
518        let mut buffer = [0u8; 1024]; // Enough to hold the largest field, which is a memo.
519
520        let result_code = unsafe {
521            get_ledger_obj_field(register_num, field_code, buffer.as_mut_ptr(), buffer.len())
522        };
523
524        match_result_code(result_code, || {
525            Some(Blob {
526                data: buffer,
527                len: result_code as usize,
528            })
529        })
530    }
531}