wasm_host_simulator/
decoding.rs

1use crate::hashing::HASH256_LEN;
2use bigdecimal::{BigDecimal, Signed, ToPrimitive, Zero};
3use lazy_static::lazy_static;
4use serde_json::Value;
5use std::collections::HashMap;
6use std::str::FromStr;
7use xrpl::core::addresscodec::utils::decode_base58;
8use xrpl::core::binarycodec::definitions::{get_ledger_entry_type_code, get_transaction_type_code};
9use xrpl::core::binarycodec::exceptions::XRPLBinaryCodecException;
10use xrpl::core::binarycodec::types::{Amount, Currency, Issue};
11use xrpl::core::exceptions::{XRPLCoreException, XRPLCoreResult};
12use xrpl::utils::exceptions::XRPRangeException;
13use xrpl::utils::{MAX_IOU_EXPONENT, MAX_IOU_PRECISION, MIN_IOU_EXPONENT, verify_valid_ic_value};
14
15pub const ACCOUNT_ID_LEN: usize = 20;
16pub type AccountId = Vec<u8>;
17
18pub const CURRENCY_LEN: usize = 20;
19pub const MPT_ID_LEN: usize = 24;
20
21/* from rippled:
22
23    STYPE(STI_UNKNOWN, -2)                        \
24    STYPE(STI_NOTPRESENT, 0)                      \
25    STYPE(STI_UINT16, 1)                          \
26                                                  \
27    /* types (common) */                          \
28    STYPE(STI_UINT32, 2)                          \
29    STYPE(STI_UINT64, 3)                          \
30    STYPE(STI_UINT128, 4)                         \
31    STYPE(STI_UINT256, 5)                         \
32    STYPE(STI_AMOUNT, 6)                          \
33    STYPE(STI_VL, 7)                              \
34    STYPE(STI_ACCOUNT, 8)                         \
35    STYPE(STI_NUMBER, 9)                          \
36                                                  \
37    /* 10-13 are reserved */                      \
38    STYPE(STI_OBJECT, 14)                         \
39    STYPE(STI_ARRAY, 15)                          \
40                                                  \
41    /* types (uncommon) */                        \
42    STYPE(STI_UINT8, 16)                          \
43    STYPE(STI_UINT160, 17)                        \
44    STYPE(STI_PATHSET, 18)                        \
45    STYPE(STI_VECTOR256, 19)                      \
46    STYPE(STI_UINT96, 20)                         \
47    STYPE(STI_UINT192, 21)                        \
48    STYPE(STI_UINT384, 22)                        \
49    STYPE(STI_UINT512, 23)                        \
50    STYPE(STI_ISSUE, 24)                          \
51    STYPE(STI_XCHAIN_BRIDGE, 25)                  \
52    STYPE(STI_CURRENCY, 26)                       \
53                                                  \
54    /* high-level types */                        \
55    /* cannot be serialized inside other types */ \
56    STYPE(STI_TRANSACTION, 10001)                 \
57    STYPE(STI_LEDGERENTRY, 10002)                 \
58    STYPE(STI_VALIDATION, 10003)                  \
59    STYPE(STI_METADATA, 10004)
60
61*/
62#[allow(non_camel_case_types)]
63#[derive(Clone, PartialEq)]
64#[allow(clippy::upper_case_acronyms)]
65pub enum Decodable {
66    UINT16,
67    Uint16_TX_TYPE,
68    UINT16_LEDGER_OBJECT_TYPE,
69    UINT32,
70    UINT64,
71    UINT128,
72    UINT256,
73    AMOUNT,
74    VL_HEX,
75    VL_OTHER,
76    ACCOUNT,
77    NUMBER,
78    OBJECT,
79    ARRAY,
80    UINT8,
81    UINT160,
82    PATHSET,
83    VECTOR256,
84    UINT96,
85    UINT192,
86    UINT384,
87    UINT512,
88    ISSUE,
89    XCHAIN_BRIDGE,
90    CURRENCY,
91    AS_IS,
92    NOT,
93}
94
95impl Decodable {
96    pub fn from_sfield(field: i32) -> Self {
97        assert!(field >= 0);
98        if let Some(name) = SField_To_Name.get(&field) {
99            if name == "TransactionType" {
100                return Decodable::Uint16_TX_TYPE;
101            } else if name == "LedgerEntryType" {
102                return Decodable::UINT16_LEDGER_OBJECT_TYPE;
103            } else if name == "PublicKey"
104                || name == "MessageKey"
105                || name == "SigningPubKey"
106                || name == "TxnSignature"
107            {
108                return Decodable::VL_HEX;
109            }
110        }
111
112        let field_type = field >> 16;
113        match field_type {
114            1 => Decodable::UINT16,
115            2 => Decodable::UINT32,
116            3 => Decodable::UINT64,
117            4 => Decodable::UINT128,
118            5 => Decodable::UINT256,
119            6 => Decodable::AMOUNT,
120            7 => Decodable::VL_OTHER,
121            8 => Decodable::ACCOUNT,
122            9 => Decodable::NUMBER,
123            // 10-13 are reserved as stated in rippled
124            14 => Decodable::OBJECT,
125            15 => Decodable::ARRAY,
126            16 => Decodable::UINT8,
127            17 => Decodable::UINT160,
128            18 => Decodable::PATHSET,
129            19 => Decodable::VECTOR256,
130            20 => Decodable::UINT96,
131            21 => Decodable::UINT192,
132            22 => Decodable::UINT384,
133            23 => Decodable::UINT512,
134            24 => Decodable::ISSUE,
135            25 => Decodable::XCHAIN_BRIDGE,
136            26 => Decodable::CURRENCY,
137
138            _ => Decodable::NOT,
139        }
140    }
141}
142
143pub fn decode(s: &str, decodable: Decodable) -> Option<Vec<u8>> {
144    match decodable {
145        Decodable::UINT16 => decode_u16(s),
146        Decodable::Uint16_TX_TYPE => decode_tx_type(s),
147        Decodable::UINT16_LEDGER_OBJECT_TYPE => decode_ledger_obj_type(s),
148        Decodable::UINT32 => decode_u32(s),
149        Decodable::UINT64 => decode_u64(s),
150        Decodable::UINT128 => decode_u128(s),
151        Decodable::UINT256 => decode_hash(s),
152        Decodable::AMOUNT => decode_amount(s),
153        Decodable::VL_HEX => decode_hex(s),
154        Decodable::VL_OTHER => decode_vl_other(s),
155        Decodable::ACCOUNT => decode_account_id(s),
156        Decodable::NUMBER => decode_number(s),
157        Decodable::OBJECT => not_leaf(s),
158        Decodable::ARRAY => not_leaf(s),
159        Decodable::UINT8 => decode_u8(s),
160        Decodable::UINT160 => decode_hex(s),
161        Decodable::PATHSET => not_leaf(s),
162        Decodable::VECTOR256 => decode_hex(s),
163        Decodable::UINT96 => decode_hex(s),
164        Decodable::UINT192 => decode_hex(s),
165        Decodable::UINT384 => decode_hex(s),
166        Decodable::UINT512 => decode_hex(s),
167        Decodable::ISSUE => decode_issue(s),
168        Decodable::XCHAIN_BRIDGE => not_leaf(s),
169        Decodable::CURRENCY => decode_currency(s),
170        Decodable::AS_IS => raw_string_to_bytes(s),
171        Decodable::NOT => decode_not(s),
172    }
173}
174
175pub fn decode_tx_type(tx_type: &str) -> Option<Vec<u8>> {
176    get_transaction_type_code(tx_type).map(|num| num.to_le_bytes().to_vec())
177}
178
179pub fn decode_ledger_obj_type(lo_type: &str) -> Option<Vec<u8>> {
180    get_ledger_entry_type_code(lo_type).map(|num| num.to_le_bytes().to_vec())
181}
182
183pub fn decode_account_id(base58_account_id: &str) -> Option<Vec<u8>> {
184    match decode_base58(base58_account_id, &[0x0]) {
185        Ok(aid) => {
186            if aid.len() == ACCOUNT_ID_LEN {
187                Some(aid)
188            } else {
189                None
190            }
191        }
192        Err(_) => None,
193    }
194}
195
196pub fn decode_hash(hex_hash: &str) -> Option<Vec<u8>> {
197    match hex::decode(hex_hash) {
198        Ok(bytes) => {
199            if bytes.len() == HASH256_LEN {
200                Some(bytes)
201            } else {
202                None
203            }
204        }
205        Err(_) => None,
206    }
207}
208pub fn decode_hex(s: &str) -> Option<Vec<u8>> {
209    hex::decode(s).ok()
210}
211
212pub fn decode_u8(s: &str) -> Option<Vec<u8>> {
213    match s.parse::<u8>() {
214        Ok(num) => Some(num.to_le_bytes().to_vec()),
215        Err(_) => None,
216    }
217}
218
219pub fn decode_u16(s: &str) -> Option<Vec<u8>> {
220    match s.parse::<u16>() {
221        Ok(num) => Some(num.to_le_bytes().to_vec()),
222        Err(_) => None,
223    }
224}
225
226pub fn decode_u32(s: &str) -> Option<Vec<u8>> {
227    match s.parse::<u32>() {
228        Ok(num) => Some(num.to_le_bytes().to_vec()),
229        Err(_) => None,
230    }
231}
232
233pub fn decode_u64(s: &str) -> Option<Vec<u8>> {
234    match s.parse::<u64>() {
235        Ok(num) => Some(num.to_le_bytes().to_vec()),
236        Err(_) => None,
237    }
238}
239
240pub fn decode_u128(hex_hash: &str) -> Option<Vec<u8>> {
241    match hex::decode(hex_hash) {
242        Ok(bytes) => {
243            if bytes.len() == 16 {
244                Some(bytes)
245            } else {
246                None
247            }
248        }
249        Err(_) => None,
250    }
251}
252
253pub fn decode_vl_other(s: &str) -> Option<Vec<u8>> {
254    decode_hex(s)
255}
256
257// the following consts, _serialize_issued_currency_value and
258// _deserialize_issued_currency_amount functions are copied
259// from https://github.com/sephynox/xrpl-rust
260const _MIN_MANTISSA: u128 = u128::pow(10, 15);
261const _MAX_MANTISSA: u128 = u128::pow(10, 16) - 1;
262const _POS_SIGN_BIT_MASK: i64 = 0x4000000000000000;
263const _ZERO_CURRENCY_AMOUNT_HEX: u64 = 0x8000000000000000;
264/// Serializes the value field of an issued currency amount
265/// to its bytes representation.
266pub fn _serialize_issued_currency_value(decimal: BigDecimal) -> XRPLCoreResult<[u8; 8]> {
267    let decimal = decimal.with_prec(MAX_IOU_PRECISION as u64);
268    verify_valid_ic_value(&decimal.to_scientific_notation())
269        .map_err(|e| XRPLCoreException::XRPLUtilsError(e.to_string()))?;
270
271    if decimal.is_zero() {
272        return Ok((_ZERO_CURRENCY_AMOUNT_HEX).to_be_bytes());
273    };
274
275    let is_positive: bool = decimal.is_positive();
276    let (mantissa_str, scale) = decimal.normalized().as_bigint_and_exponent();
277    let mut exp: i32 = -(scale as i32);
278    let mut mantissa: u128 = mantissa_str.abs().to_u128().unwrap();
279
280    while mantissa < _MIN_MANTISSA && exp > MIN_IOU_EXPONENT {
281        mantissa *= 10;
282        exp -= 1;
283    }
284
285    while mantissa > _MAX_MANTISSA {
286        if exp >= MAX_IOU_EXPONENT {
287            return Err(XRPLBinaryCodecException::from(
288                XRPRangeException::UnexpectedICAmountOverflow {
289                    max: MAX_IOU_EXPONENT as usize,
290                    found: exp as usize,
291                },
292            )
293            .into());
294        } else {
295            mantissa /= 10;
296            exp += 1;
297        }
298    }
299
300    if exp < MIN_IOU_EXPONENT || mantissa < _MIN_MANTISSA {
301        // Round to zero
302        Ok((_ZERO_CURRENCY_AMOUNT_HEX).to_be_bytes())
303    } else if exp > MAX_IOU_EXPONENT || mantissa > _MAX_MANTISSA {
304        Err(
305            XRPLBinaryCodecException::from(XRPRangeException::UnexpectedICAmountOverflow {
306                max: MAX_IOU_EXPONENT as usize,
307                found: exp as usize,
308            })
309            .into(),
310        )
311    } else {
312        // "Not XRP" bit set
313        let mut serial: i128 = _ZERO_CURRENCY_AMOUNT_HEX as i128;
314
315        // "Is positive" bit set
316        if is_positive {
317            serial |= _POS_SIGN_BIT_MASK as i128;
318        };
319
320        // next 8 bits are exponents
321        serial |= ((exp as i64 + 97) << 54) as i128;
322        // last 54 bits are mantissa
323        serial |= mantissa as i128;
324
325        Ok((serial as u64).to_be_bytes())
326    }
327}
328
329//TODO we will use rippled Number class for computation
330pub fn _deserialize_issued_currency_amount(bytes: [u8; 8]) -> XRPLCoreResult<BigDecimal> {
331    let mut value: BigDecimal;
332
333    // Some wizardry by Amie Corso
334    let exp = ((bytes[0] as i32 & 0x3F) << 2) + ((bytes[1] as i32 & 0xFF) >> 6) - 97;
335
336    if exp < MIN_IOU_EXPONENT {
337        value = BigDecimal::from(0);
338    } else {
339        let hex_mantissa = hex::encode([&[bytes[1] & 0x3F], &bytes[2..]].concat());
340        let int_mantissa = i128::from_str_radix(&hex_mantissa, 16)
341            .map_err(XRPLBinaryCodecException::ParseIntError)?;
342
343        // Adjust scale using the exponent
344        let scale = exp.unsigned_abs();
345        value = BigDecimal::new(int_mantissa.into(), scale as i64);
346
347        // Handle the sign
348        if bytes[0] & 0x40 > 0 {
349            // Set the value to positive (BigDecimal assumes positive by default)
350            value = value.abs();
351        } else {
352            // Set the value to negative
353            value = -value.abs();
354        }
355    }
356    verify_valid_ic_value(&value.to_string())
357        .map_err(|e| XRPLCoreException::XRPLUtilsError(e.to_string()))?;
358
359    Ok(value)
360}
361
362pub fn decode_number(s: &str) -> Option<Vec<u8>> {
363    let value = BigDecimal::from_str(s).ok()?;
364    _serialize_issued_currency_value(value)
365        .ok()
366        .map(|bytes| bytes.to_vec())
367}
368
369pub fn decode_currency(s: &str) -> Option<Vec<u8>> {
370    match Currency::try_from(s) {
371        Ok(currency) => Some(currency.as_ref().to_vec()),
372        Err(_) => None,
373    }
374}
375
376pub const POSITIVE_MPT: u8 = 0b_0110_0000;
377pub const NEGATIVE_MPT: u8 = 0b_0010_0000;
378
379pub fn decode_amount_json(value: Value) -> Option<Vec<u8>> {
380    // try to decode an MPT
381    if let Some(mpt_issuance_id) = value.get("mpt_issuance_id") {
382        if let Some(amount_value) = value.get("value") {
383            // in rippled:
384            // TYPED_SFIELD(sfMPTAmount,                UINT64,    26)
385            //
386            // So amount value should always be positive, but since there is a sign bit
387            // in MPT amount encoding, we try to handle negative values just in case.
388            let amount = amount_value.as_str()?.parse::<i64>().ok()?;
389            let (negative, amount_abs) = if amount < 0 {
390                // amount.wrapping_neg() handles i64::MIN correctly,
391                // where -i64::MIN would overflow in regular arithmetic.
392                (true, amount.wrapping_neg() as u64)
393            } else {
394                (false, amount as u64)
395            };
396
397            let mut bytes = Vec::new();
398            bytes.push(if negative { NEGATIVE_MPT } else { POSITIVE_MPT });
399            // Big Endian matches what rippled returns
400            bytes.append(&mut amount_abs.to_be_bytes().to_vec());
401            let mpt_issuance_id = mpt_issuance_id.as_str()?.to_string();
402            let mut mpt_issuance_id_bytes = hex::decode(mpt_issuance_id.as_str()).ok()?;
403            bytes.append(&mut mpt_issuance_id_bytes);
404            return Some(bytes);
405        }
406        return None;
407    }
408
409    // Helper function to normalize amount values - convert numbers to strings
410    // This handles cases where JSON amounts are numbers instead of strings
411    let normalized_value = normalize_amount_value(value.clone());
412
413    // Use the library to decode both XRP and IOU amounts
414    match Amount::try_from(normalized_value) {
415        Ok(amount) => Some(amount.as_ref().to_vec()),
416        Err(_) => {
417            // Fallback: try the original value in case normalization changed something important
418            match Amount::try_from(value) {
419                Ok(amount) => Some(amount.as_ref().to_vec()),
420                Err(_) => None,
421            }
422        }
423    }
424}
425
426/// Normalize amount values by converting numbers to strings
427/// This handles both simple amounts (XRP) and complex amounts (IOU) with numeric values
428fn normalize_amount_value(mut value: Value) -> Value {
429    // Handle simple numeric amounts (XRP)
430    if value.is_number() {
431        if let Some(num) = value.as_i64() {
432            return Value::String(num.to_string());
433        }
434        if let Some(num) = value.as_f64() {
435            return Value::String(num.to_string());
436        }
437    }
438
439    // Handle IOU amounts with numeric value field
440    if let Some(obj) = value.as_object_mut()
441        && let Some(amount_value) = obj.get("value")
442        && amount_value.is_number()
443    {
444        if let Some(num) = amount_value.as_i64() {
445            obj.insert("value".to_string(), Value::String(num.to_string()));
446        } else if let Some(num) = amount_value.as_f64() {
447            obj.insert("value".to_string(), Value::String(num.to_string()));
448        }
449    }
450
451    value
452}
453
454pub fn decode_amount(s: &str) -> Option<Vec<u8>> {
455    let v: Value = serde_json::from_str(s).expect("Invalid json string");
456    decode_amount_json(v)
457}
458
459pub fn decode_issue_json(value: Value) -> Option<Vec<u8>> {
460    if let Some(mpt_issuance_id) = value.get("mpt_issuance_id") {
461        return decode_hex(mpt_issuance_id.as_str()?);
462    }
463    match Issue::try_from(value) {
464        Ok(issue) => Some(issue.as_ref().to_vec()),
465        Err(_) => None,
466    }
467}
468
469pub fn decode_issue(s: &str) -> Option<Vec<u8>> {
470    let v: Value = serde_json::from_str(s).expect("Invalid json string");
471    decode_issue_json(v)
472}
473
474pub fn not_leaf(_: &str) -> Option<Vec<u8>> {
475    None
476}
477
478pub fn decode_not(_: &str) -> Option<Vec<u8>> {
479    None
480}
481
482pub fn raw_string_to_bytes(s: &str) -> Option<Vec<u8>> {
483    Some(s.as_bytes().to_vec())
484}
485
486lazy_static! {
487    pub static ref SField_To_Name: HashMap<i32, String> = polulate_field_names();
488}
489
490fn polulate_field_names() -> HashMap<i32, String> {
491    let mut sfield_names: HashMap<i32, String> = HashMap::new();
492    sfield_names.insert(-1, "Invalid".to_string());
493    sfield_names.insert(0, "Generic".to_string());
494    sfield_names.insert(65537, "LedgerEntryType".to_string());
495    sfield_names.insert(65538, "TransactionType".to_string());
496    sfield_names.insert(65539, "SignerWeight".to_string());
497    sfield_names.insert(65540, "TransferFee".to_string());
498    sfield_names.insert(65541, "TradingFee".to_string());
499    sfield_names.insert(65542, "DiscountedFee".to_string());
500    sfield_names.insert(65552, "Version".to_string());
501    sfield_names.insert(65553, "HookStateChangeCount".to_string());
502    sfield_names.insert(65554, "HookEmitCount".to_string());
503    sfield_names.insert(65555, "HookExecutionIndex".to_string());
504    sfield_names.insert(65556, "HookApiVersion".to_string());
505    sfield_names.insert(65557, "LedgerFixType".to_string());
506    sfield_names.insert(131073, "NetworkID".to_string());
507    sfield_names.insert(131074, "Flags".to_string());
508    sfield_names.insert(131075, "SourceTag".to_string());
509    sfield_names.insert(131076, "Sequence".to_string());
510    sfield_names.insert(131077, "PreviousTxnLgrSeq".to_string());
511    sfield_names.insert(131078, "LedgerSequence".to_string());
512    sfield_names.insert(131079, "CloseTime".to_string());
513    sfield_names.insert(131080, "ParentCloseTime".to_string());
514    sfield_names.insert(131081, "SigningTime".to_string());
515    sfield_names.insert(131082, "Expiration".to_string());
516    sfield_names.insert(131083, "TransferRate".to_string());
517    sfield_names.insert(131084, "WalletSize".to_string());
518    sfield_names.insert(131085, "OwnerCount".to_string());
519    sfield_names.insert(131086, "DestinationTag".to_string());
520    sfield_names.insert(131087, "LastUpdateTime".to_string());
521    sfield_names.insert(131088, "HighQualityIn".to_string());
522    sfield_names.insert(131089, "HighQualityOut".to_string());
523    sfield_names.insert(131090, "LowQualityIn".to_string());
524    sfield_names.insert(131091, "LowQualityOut".to_string());
525    sfield_names.insert(131092, "QualityIn".to_string());
526    sfield_names.insert(131093, "QualityOut".to_string());
527    sfield_names.insert(131094, "StampEscrow".to_string());
528    sfield_names.insert(131095, "BondAmount".to_string());
529    sfield_names.insert(131096, "LoadFee".to_string());
530    sfield_names.insert(131097, "OfferSequence".to_string());
531    sfield_names.insert(131098, "FirstLedgerSequence".to_string());
532    sfield_names.insert(131099, "LastLedgerSequence".to_string());
533    sfield_names.insert(131100, "TransactionIndex".to_string());
534    sfield_names.insert(131101, "OperationLimit".to_string());
535    sfield_names.insert(131102, "ReferenceFeeUnits".to_string());
536    sfield_names.insert(131103, "ReserveBase".to_string());
537    sfield_names.insert(131104, "ReserveIncrement".to_string());
538    sfield_names.insert(131105, "SetFlag".to_string());
539    sfield_names.insert(131106, "ClearFlag".to_string());
540    sfield_names.insert(131107, "SignerQuorum".to_string());
541    sfield_names.insert(131108, "CancelAfter".to_string());
542    sfield_names.insert(131109, "FinishAfter".to_string());
543    sfield_names.insert(131110, "SignerListID".to_string());
544    sfield_names.insert(131111, "SettleDelay".to_string());
545    sfield_names.insert(131112, "TicketCount".to_string());
546    sfield_names.insert(131113, "TicketSequence".to_string());
547    sfield_names.insert(131114, "NFTokenTaxon".to_string());
548    sfield_names.insert(131115, "MintedNFTokens".to_string());
549    sfield_names.insert(131116, "BurnedNFTokens".to_string());
550    sfield_names.insert(131117, "HookStateCount".to_string());
551    sfield_names.insert(131118, "EmitGeneration".to_string());
552    sfield_names.insert(131120, "VoteWeight".to_string());
553    sfield_names.insert(131122, "FirstNFTokenSequence".to_string());
554    sfield_names.insert(131123, "OracleDocumentID".to_string());
555    sfield_names.insert(131124, "ExtensionComputeLimit".to_string());
556    sfield_names.insert(131125, "ExtensionSizeLimit".to_string());
557    sfield_names.insert(131126, "GasPrice".to_string());
558    sfield_names.insert(131127, "ComputationAllowance".to_string());
559    sfield_names.insert(196609, "IndexNext".to_string());
560    sfield_names.insert(196610, "IndexPrevious".to_string());
561    sfield_names.insert(196611, "BookNode".to_string());
562    sfield_names.insert(196612, "OwnerNode".to_string());
563    sfield_names.insert(196613, "BaseFee".to_string());
564    sfield_names.insert(196614, "ExchangeRate".to_string());
565    sfield_names.insert(196615, "LowNode".to_string());
566    sfield_names.insert(196616, "HighNode".to_string());
567    sfield_names.insert(196617, "DestinationNode".to_string());
568    sfield_names.insert(196618, "Cookie".to_string());
569    sfield_names.insert(196619, "ServerVersion".to_string());
570    sfield_names.insert(196620, "NFTokenOfferNode".to_string());
571    sfield_names.insert(196621, "EmitBurden".to_string());
572    sfield_names.insert(196624, "HookOn".to_string());
573    sfield_names.insert(196625, "HookInstructionCount".to_string());
574    sfield_names.insert(196626, "HookReturnCode".to_string());
575    sfield_names.insert(196627, "ReferenceCount".to_string());
576    sfield_names.insert(196628, "XChainClaimID".to_string());
577    sfield_names.insert(196629, "XChainAccountCreateCount".to_string());
578    sfield_names.insert(196630, "XChainAccountClaimCount".to_string());
579    sfield_names.insert(196631, "AssetPrice".to_string());
580    sfield_names.insert(196632, "MaximumAmount".to_string());
581    sfield_names.insert(196633, "OutstandingAmount".to_string());
582    sfield_names.insert(196634, "MPTAmount".to_string());
583    sfield_names.insert(196635, "IssuerNode".to_string());
584    sfield_names.insert(196636, "SubjectNode".to_string());
585    sfield_names.insert(262145, "EmailHash".to_string());
586    sfield_names.insert(327681, "LedgerHash".to_string());
587    sfield_names.insert(327682, "ParentHash".to_string());
588    sfield_names.insert(327683, "TransactionHash".to_string());
589    sfield_names.insert(327684, "AccountHash".to_string());
590    sfield_names.insert(327685, "PreviousTxnID".to_string());
591    sfield_names.insert(327686, "LedgerIndex".to_string());
592    sfield_names.insert(327687, "WalletLocator".to_string());
593    sfield_names.insert(327688, "RootIndex".to_string());
594    sfield_names.insert(327689, "AccountTxnID".to_string());
595    sfield_names.insert(327690, "NFTokenID".to_string());
596    sfield_names.insert(327691, "EmitParentTxnID".to_string());
597    sfield_names.insert(327692, "EmitNonce".to_string());
598    sfield_names.insert(327693, "EmitHookHash".to_string());
599    sfield_names.insert(327694, "AMMID".to_string());
600    sfield_names.insert(327696, "BookDirectory".to_string());
601    sfield_names.insert(327697, "InvoiceID".to_string());
602    sfield_names.insert(327698, "Nickname".to_string());
603    sfield_names.insert(327699, "Amendment".to_string());
604    sfield_names.insert(327701, "Digest".to_string());
605    sfield_names.insert(327702, "Channel".to_string());
606    sfield_names.insert(327703, "ConsensusHash".to_string());
607    sfield_names.insert(327704, "CheckID".to_string());
608    sfield_names.insert(327705, "ValidatedHash".to_string());
609    sfield_names.insert(327706, "PreviousPageMin".to_string());
610    sfield_names.insert(327707, "NextPageMin".to_string());
611    sfield_names.insert(327708, "NFTokenBuyOffer".to_string());
612    sfield_names.insert(327709, "NFTokenSellOffer".to_string());
613    sfield_names.insert(327710, "HookStateKey".to_string());
614    sfield_names.insert(327711, "HookHash".to_string());
615    sfield_names.insert(327712, "HookNamespace".to_string());
616    sfield_names.insert(327713, "HookSetTxnID".to_string());
617    sfield_names.insert(327714, "DomainID".to_string());
618    sfield_names.insert(327937, "hash".to_string());
619    sfield_names.insert(327938, "index".to_string());
620    sfield_names.insert(393217, "Amount".to_string());
621    sfield_names.insert(393218, "Balance".to_string());
622    sfield_names.insert(393219, "LimitAmount".to_string());
623    sfield_names.insert(393220, "TakerPays".to_string());
624    sfield_names.insert(393221, "TakerGets".to_string());
625    sfield_names.insert(393222, "LowLimit".to_string());
626    sfield_names.insert(393223, "HighLimit".to_string());
627    sfield_names.insert(393224, "Fee".to_string());
628    sfield_names.insert(393225, "SendMax".to_string());
629    sfield_names.insert(393226, "DeliverMin".to_string());
630    sfield_names.insert(393227, "Amount2".to_string());
631    sfield_names.insert(393228, "BidMin".to_string());
632    sfield_names.insert(393229, "BidMax".to_string());
633    sfield_names.insert(393232, "MinimumOffer".to_string());
634    sfield_names.insert(393233, "RippleEscrow".to_string());
635    sfield_names.insert(393234, "DeliveredAmount".to_string());
636    sfield_names.insert(393235, "NFTokenBrokerFee".to_string());
637    sfield_names.insert(393238, "BaseFeeDrops".to_string());
638    sfield_names.insert(393239, "ReserveBaseDrops".to_string());
639    sfield_names.insert(393240, "ReserveIncrementDrops".to_string());
640    sfield_names.insert(393241, "LPTokenOut".to_string());
641    sfield_names.insert(393242, "LPTokenIn".to_string());
642    sfield_names.insert(393243, "EPrice".to_string());
643    sfield_names.insert(393244, "Price".to_string());
644    sfield_names.insert(393245, "SignatureReward".to_string());
645    sfield_names.insert(393246, "MinAccountCreateAmount".to_string());
646    sfield_names.insert(393247, "LPTokenBalance".to_string());
647    sfield_names.insert(458753, "PublicKey".to_string());
648    sfield_names.insert(458754, "MessageKey".to_string());
649    sfield_names.insert(458755, "SigningPubKey".to_string());
650    sfield_names.insert(458756, "TxnSignature".to_string());
651    sfield_names.insert(458757, "URI".to_string());
652    sfield_names.insert(458758, "Signature".to_string());
653    sfield_names.insert(458759, "Domain".to_string());
654    sfield_names.insert(458760, "FundCode".to_string());
655    sfield_names.insert(458761, "RemoveCode".to_string());
656    sfield_names.insert(458762, "ExpireCode".to_string());
657    sfield_names.insert(458763, "CreateCode".to_string());
658    sfield_names.insert(458764, "MemoType".to_string());
659    sfield_names.insert(458765, "MemoData".to_string());
660    sfield_names.insert(458766, "MemoFormat".to_string());
661    sfield_names.insert(458768, "Fulfillment".to_string());
662    sfield_names.insert(458769, "Condition".to_string());
663    sfield_names.insert(458770, "MasterSignature".to_string());
664    sfield_names.insert(458771, "UNLModifyValidator".to_string());
665    sfield_names.insert(458772, "ValidatorToDisable".to_string());
666    sfield_names.insert(458773, "ValidatorToReEnable".to_string());
667    sfield_names.insert(458774, "HookStateData".to_string());
668    sfield_names.insert(458775, "HookReturnString".to_string());
669    sfield_names.insert(458776, "HookParameterName".to_string());
670    sfield_names.insert(458777, "HookParameterValue".to_string());
671    sfield_names.insert(458778, "DIDDocument".to_string());
672    sfield_names.insert(458779, "Data".to_string());
673    sfield_names.insert(458780, "AssetClass".to_string());
674    sfield_names.insert(458781, "Provider".to_string());
675    sfield_names.insert(458782, "MPTokenMetadata".to_string());
676    sfield_names.insert(458783, "CredentialType".to_string());
677    sfield_names.insert(458784, "FinishFunction".to_string());
678    sfield_names.insert(524289, "Account".to_string());
679    sfield_names.insert(524290, "Owner".to_string());
680    sfield_names.insert(524291, "Destination".to_string());
681    sfield_names.insert(524292, "Issuer".to_string());
682    sfield_names.insert(524293, "Authorize".to_string());
683    sfield_names.insert(524294, "Unauthorize".to_string());
684    sfield_names.insert(524296, "RegularKey".to_string());
685    sfield_names.insert(524297, "NFTokenMinter".to_string());
686    sfield_names.insert(524298, "EmitCallback".to_string());
687    sfield_names.insert(524299, "Holder".to_string());
688    sfield_names.insert(524304, "HookAccount".to_string());
689    sfield_names.insert(524306, "OtherChainSource".to_string());
690    sfield_names.insert(524307, "OtherChainDestination".to_string());
691    sfield_names.insert(524308, "AttestationSignerAccount".to_string());
692    sfield_names.insert(524309, "AttestationRewardAccount".to_string());
693    sfield_names.insert(524310, "LockingChainDoor".to_string());
694    sfield_names.insert(524311, "IssuingChainDoor".to_string());
695    sfield_names.insert(524312, "Subject".to_string());
696    sfield_names.insert(589825, "Number".to_string());
697    sfield_names.insert(917506, "TransactionMetaData".to_string());
698    sfield_names.insert(917507, "CreatedNode".to_string());
699    sfield_names.insert(917508, "DeletedNode".to_string());
700    sfield_names.insert(917509, "ModifiedNode".to_string());
701    sfield_names.insert(917510, "PreviousFields".to_string());
702    sfield_names.insert(917511, "FinalFields".to_string());
703    sfield_names.insert(917512, "NewFields".to_string());
704    sfield_names.insert(917513, "TemplateEntry".to_string());
705    sfield_names.insert(917514, "Memo".to_string());
706    sfield_names.insert(917515, "SignerEntry".to_string());
707    sfield_names.insert(917516, "NFToken".to_string());
708    sfield_names.insert(917517, "EmitDetails".to_string());
709    sfield_names.insert(917518, "Hook".to_string());
710    sfield_names.insert(917520, "Signer".to_string());
711    sfield_names.insert(917522, "Majority".to_string());
712    sfield_names.insert(917523, "DisabledValidator".to_string());
713    sfield_names.insert(917524, "EmittedTxn".to_string());
714    sfield_names.insert(917525, "HookExecution".to_string());
715    sfield_names.insert(917526, "HookDefinition".to_string());
716    sfield_names.insert(917527, "HookParameter".to_string());
717    sfield_names.insert(917528, "HookGrant".to_string());
718    sfield_names.insert(917529, "VoteEntry".to_string());
719    sfield_names.insert(917530, "AuctionSlot".to_string());
720    sfield_names.insert(917531, "AuthAccount".to_string());
721    sfield_names.insert(917532, "XChainClaimProofSig".to_string());
722    sfield_names.insert(917533, "XChainCreateAccountProofSig".to_string());
723    sfield_names.insert(
724        917534,
725        "XChainClaimAttestationCollectionElement".to_string(),
726    );
727    sfield_names.insert(
728        917535,
729        "XChainCreateAccountAttestationCollectionElement".to_string(),
730    );
731    sfield_names.insert(917536, "PriceData".to_string());
732    sfield_names.insert(917537, "Credential".to_string());
733    sfield_names.insert(983043, "Signers".to_string());
734    sfield_names.insert(983044, "SignerEntries".to_string());
735    sfield_names.insert(983045, "Template".to_string());
736    sfield_names.insert(983046, "Necessary".to_string());
737    sfield_names.insert(983047, "Sufficient".to_string());
738    sfield_names.insert(983048, "AffectedNodes".to_string());
739    sfield_names.insert(983049, "Memos".to_string());
740    sfield_names.insert(983050, "NFTokens".to_string());
741    sfield_names.insert(983051, "Hooks".to_string());
742    sfield_names.insert(983052, "VoteSlots".to_string());
743    sfield_names.insert(983056, "Majorities".to_string());
744    sfield_names.insert(983057, "DisabledValidators".to_string());
745    sfield_names.insert(983058, "HookExecutions".to_string());
746    sfield_names.insert(983059, "HookParameters".to_string());
747    sfield_names.insert(983060, "HookGrants".to_string());
748    sfield_names.insert(983061, "XChainClaimAttestations".to_string());
749    sfield_names.insert(983062, "XChainCreateAccountAttestations".to_string());
750    sfield_names.insert(983064, "PriceDataSeries".to_string());
751    sfield_names.insert(983065, "AuthAccounts".to_string());
752    sfield_names.insert(983066, "AuthorizeCredentials".to_string());
753    sfield_names.insert(983067, "UnauthorizeCredentials".to_string());
754    sfield_names.insert(983068, "AcceptedCredentials".to_string());
755    sfield_names.insert(1048577, "CloseResolution".to_string());
756    sfield_names.insert(1048578, "Method".to_string());
757    sfield_names.insert(1048579, "TransactionResult".to_string());
758    sfield_names.insert(1048580, "Scale".to_string());
759    sfield_names.insert(1048581, "AssetScale".to_string());
760    sfield_names.insert(1048592, "TickSize".to_string());
761    sfield_names.insert(1048593, "UNLModifyDisabling".to_string());
762    sfield_names.insert(1048594, "HookResult".to_string());
763    sfield_names.insert(1048595, "WasLockingChainSend".to_string());
764    sfield_names.insert(1114113, "TakerPaysCurrency".to_string());
765    sfield_names.insert(1114114, "TakerPaysIssuer".to_string());
766    sfield_names.insert(1114115, "TakerGetsCurrency".to_string());
767    sfield_names.insert(1114116, "TakerGetsIssuer".to_string());
768    sfield_names.insert(1179649, "Paths".to_string());
769    sfield_names.insert(1245185, "Indexes".to_string());
770    sfield_names.insert(1245186, "Hashes".to_string());
771    sfield_names.insert(1245187, "Amendments".to_string());
772    sfield_names.insert(1245188, "NFTokenOffers".to_string());
773    sfield_names.insert(1245189, "CredentialIDs".to_string());
774    sfield_names.insert(1376257, "MPTokenIssuanceID".to_string());
775    sfield_names.insert(1572865, "LockingChainIssue".to_string());
776    sfield_names.insert(1572866, "IssuingChainIssue".to_string());
777    sfield_names.insert(1572867, "Asset".to_string());
778    sfield_names.insert(1572868, "Asset2".to_string());
779    sfield_names.insert(1638401, "XChainBridge".to_string());
780    sfield_names.insert(1703937, "BaseAsset".to_string());
781    sfield_names.insert(1703938, "QuoteAsset".to_string());
782    sfield_names.insert(655425793, "Transaction".to_string());
783    sfield_names.insert(655491329, "LedgerEntry".to_string());
784    sfield_names.insert(655556865, "Validation".to_string());
785    sfield_names.insert(655622401, "Metadata".to_string());
786    sfield_names
787}