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}