cma_rust_parser/
parser.rs

1use crate::helpers::{hex_to_string, PortalMatcher, Portals, CARTESI_ADDRESSES};
2use ethers_core::abi::{encode, Token};
3use ethers_core::types::{Address, Bytes, U256};
4use ethers_core::utils::{id, to_checksum};
5
6use hex;
7use json::{JsonValue};
8
9#[repr(u32)]
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum TxHexCodes {
12    // Bytecode for solidity WithdrawEther(uint256,bytes) = 8cf70f0b
13    WithdrawEther = 0x8cf70f0b,
14    // Bytecode for solidity WithdrawErc20(address,uint256,bytes) = 4f94d342
15    WithdrawErc20 = 0x4f94d342,
16    // Bytecode for solidity WithdrawErc721(address,uint256,bytes) = 33acf293
17    WithdrawErc721 = 0x33acf293,
18    // Bytecode for solidity WithdrawErc1155Single(address,uint256,uint256,bytes) = 8bb0a811
19    WithdrawErc1155Single = 0x8bb0a811,
20    // Bytecode for solidity WithdrawErc1155Batch(address,uint256[],uint256[],bytes) = 50c80019
21    WithdrawErc1155Batch = 0x50c80019,
22
23    // Bytecode for solidity TransferEther(uint256,bytes32,bytes) = 428c9c4d
24    TransferEther = 0x428c9c4d,
25    // Bytecode for solidity TransferErc20(address,bytes32,uint256,bytes) = 03d61dcd
26    TransferErc20 = 0x03d61dcd,
27    // Bytecode for solidity TransferErc721(address,bytes32,uint256,bytes) = af615a5a
28    TransferErc721 = 0xaf615a5a,
29    // Bytecode for solidity TransferErc1155Single(address,bytes32,uint256,uint256,bytes) = e1c913ed
30    TransferErc1155Single = 0xe1c913ed,
31    // Bytecode for solidity TransferErc1155Batch(address,bytes32,uint256[],uint256[],bytes) = 638ac6f9
32    TransferErc1155Batch = 0x638ac6f9,
33
34    // Bytecode for solidity transfer(address,uint256) = a9059cbb
35    Erc20TransferFunctionSelectorFunsel = 0xa9059cbb,
36    // Bytecode for solidity safeTransferFrom(address,address,uint256) = 42842e0e
37    Erc721TransferFunctionSelectorFunsel = 0x42842e0e,
38    // Bytecode for solidity safeTransferFrom(address,address,uint256,uint256,bytes) = f242432a
39    Erc1155SingleTransferFunctionSelectorFunsel = 0xf242432a,
40    // Bytecode for solidity safeBatchTransferFrom(address,address,uint256[],uint256[],bytes) = 2eb2c2d6
41    Erc1155BatchTransferFunctionSelectorFunsel = 0x2eb2c2d6,
42}
43
44pub enum CmaVoucherFieldType {
45    EtherVoucherFields(CmaParserEtherVoucherFields),
46    Erc20VoucherFields(CmaParserErc20VoucherFields),
47    Erc721VoucherFields(CmaParserErc721VoucherFields),
48    Erc1155SingleVoucherFields(CmaParserErc1155SingleVoucherFields),
49    Erc1155BatchVoucherFields(CmaParserErc1155BatchVoucherFields),
50}
51
52enum TokenType {
53    Erc20,
54    Erc721,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum CmaParserInputType {
59    CmaParserInputTypeNone,
60    CmaParserInputTypeAuto,
61    CmaParserInputTypeUnidentified,
62    CmaParserInputTypeEtherDeposit,
63    CmaParserInputTypeErc20Deposit,
64    CmaParserInputTypeErc721Deposit,
65    CmaParserInputTypeErc1155SingleDeposit,
66    CmaParserInputTypeErc1155BatchDeposit,
67    CmaParserInputTypeEtherWithdrawal,
68    CmaParserInputTypeErc20Withdrawal,
69    CmaParserInputTypeErc721Withdrawal,
70    CmaParserInputTypeErc1155SingleWithdrawal,
71    CmaParserInputTypeErc1155BatchWithdrawal,
72    CmaParserInputTypeEtherTransfer,
73    CmaParserInputTypeErc20Transfer,
74    CmaParserInputTypeErc721Transfer,
75    CmaParserInputTypeErc1155SingleTransfer,
76    CmaParserInputTypeErc1155BatchTransfer,
77    CmaParserInputTypeBalance,
78    CmaParserInputTypeSupply,
79}
80
81impl CmaParserInputType {
82    pub fn from_string(s: &str) -> Self {
83        match s {
84            "EtherDeposit" => CmaParserInputType::CmaParserInputTypeEtherDeposit,
85            "Erc20Deposit" => CmaParserInputType::CmaParserInputTypeErc20Deposit,
86            "Erc721Deposit" => CmaParserInputType::CmaParserInputTypeErc721Deposit,
87            "Erc1155SingleDeposit" => CmaParserInputType::CmaParserInputTypeErc1155SingleDeposit,
88            "Erc1155BatchDeposit" => CmaParserInputType::CmaParserInputTypeErc1155BatchDeposit,
89            "EtherWithdrawal" => CmaParserInputType::CmaParserInputTypeEtherWithdrawal,
90            "Erc20Withdrawal" => CmaParserInputType::CmaParserInputTypeErc20Withdrawal,
91            "Erc721Withdrawal" => CmaParserInputType::CmaParserInputTypeErc721Withdrawal,
92            "Erc1155SingleWithdrawal" => {
93                CmaParserInputType::CmaParserInputTypeErc1155SingleWithdrawal
94            }
95            "Erc1155BatchWithdrawal" => {
96                CmaParserInputType::CmaParserInputTypeErc1155BatchWithdrawal
97            }
98            "EtherTransfer" => CmaParserInputType::CmaParserInputTypeEtherTransfer,
99            "Erc20Transfer" => CmaParserInputType::CmaParserInputTypeErc20Transfer,
100            "Erc721Transfer" => CmaParserInputType::CmaParserInputTypeErc721Transfer,
101            "Erc1155SingleTransfer" => CmaParserInputType::CmaParserInputTypeErc1155SingleTransfer,
102            "Erc1155BatchTransfer" => CmaParserInputType::CmaParserInputTypeErc1155BatchTransfer,
103            "ledgerGetBalance" => CmaParserInputType::CmaParserInputTypeBalance,
104            "ledgerGetTotalSupply" => CmaParserInputType::CmaParserInputTypeSupply,
105            _ => CmaParserInputType::CmaParserInputTypeUnidentified,
106        }
107    }
108}
109
110pub enum CmaParserVoucherType {
111    CmaParserVoucherTypeNone,
112    CmaParserVoucherTypeEther,
113    CmaParserVoucherTypeErc20,
114    CmaParserVoucherTypeErc721,
115    CmaParserVoucherTypeErc1155Single,
116    CmaParserVoucherTypeErc1155Batch,
117}
118
119#[derive(Debug, Clone, PartialEq, Eq)]
120pub enum CmaParserUnidentifiedInputType {
121    CmaParserUnidentifiedInputJsonPayload(JsonValue),
122    CmaParserUnidentifiedInputStringPayload(String),
123}
124
125#[derive(Debug, Clone, PartialEq, Eq)]
126pub enum CmaParserError {
127    Success,
128    IncompatibleInput,
129    MalformedInput,
130    Unknown,
131    Message(String),
132}
133
134impl CmaParserError {
135    pub fn from_code(code: i32) -> Self {
136        match code {
137            0 => Self::Success,
138            -2001 => Self::IncompatibleInput,
139            -2002 => Self::MalformedInput,
140            -2003 => Self::Unknown,
141            -2004 => Self::Message("Unknown error".to_string()),
142            _ => Self::Unknown,
143        }
144    }
145
146    pub fn to_code(self) -> i32 {
147        match self {
148            Self::Success => 0,
149            Self::IncompatibleInput => -2001,
150            Self::MalformedInput => -2002,
151            Self::Unknown => -2003,
152            Self::Message(_) => -2004,
153        }
154    }
155}
156
157#[derive(Debug, Clone, PartialEq, Eq)]
158pub struct CmaVoucher {
159    pub destination: String,
160    pub value: String,
161    pub payload: String,
162}
163
164
165
166#[derive(Debug, Clone, PartialEq, Eq)]
167pub struct CmaParserUnidentifiedInput {
168    pub raw_input: CmaParserUnidentifiedInputType,
169    pub msg_sender: Address,
170}
171
172
173
174pub struct CmaParserEtherVoucherFields {
175    pub amount: U256,
176    pub receiver: Address,
177}
178pub struct CmaParserErc20VoucherFields {
179    pub token: Address,
180    pub receiver: Address,
181    pub value: U256,
182    pub amount: U256,
183}
184pub struct CmaParserErc721VoucherFields {
185    pub token: Address,
186    pub token_id: U256,
187    pub receiver: Address,
188    pub value: U256,
189    pub application_address: Address,
190}
191pub struct CmaParserErc1155SingleVoucherFields {
192    pub token: Address,
193    pub token_id: U256,
194    pub receiver: Address,
195    pub value: U256,
196    pub amount: U256,
197}
198pub struct CmaParserErc1155BatchVoucherFields {
199    pub token: Address,
200    pub receiver: Address,
201    pub count: usize,
202    pub token_ids: Vec<U256>,
203    pub value: U256,
204    pub amounts: Vec<U256>,
205}
206
207#[derive(Debug, Clone, PartialEq, Eq)]
208pub struct CmaParserEtherDeposit {
209    pub sender: Address,
210    pub amount: U256,
211    pub exec_layer_data: Bytes,
212}
213
214pub struct CmaParserErc20Deposit {
215    pub sender: Address,
216    pub token: Address,
217    pub amount: U256,
218    pub exec_layer_data: Bytes,
219}
220
221pub struct CmaParserErc721Deposit {
222    pub sender: Address,
223    pub token: Address,
224    pub token_id: U256,
225    pub exec_layer_data: Bytes,
226}
227
228pub struct CmaParserErc1155SingleDeposit {
229    pub sender: Address,
230    pub token: Address,
231    pub token_id: U256,
232    pub amount: U256,
233    pub exec_layer_data: Bytes,
234}
235
236pub struct CmaParserErc1155BatchDeposit {
237    pub sender: Address,
238    pub token: Address,
239    pub count: usize,
240    pub token_ids: Vec<U256>,
241    pub amounts: Vec<U256>,
242    pub base_layer_data: Bytes,
243    pub exec_layer_data: Bytes,
244}
245
246pub struct CmaParserEtherWithdrawal {
247    pub receiver: Address,
248    pub amount: U256,
249    pub exec_layer_data: String,
250}
251
252pub struct CmaParserErc20Withdrawal {
253    pub receiver: Address,
254    pub token: Address,
255    pub amount: U256,
256    pub exec_layer_data: String,
257}
258
259pub struct CmaParserErc721Withdrawal {
260    pub receiver: Address,
261    pub token: Address,
262    pub token_id: U256,
263    pub exec_layer_data: String,
264}
265
266pub struct CmaParserErc1155SingleWithdrawal {
267    pub receiver: Address,
268    pub token: Address,
269    pub token_id: U256,
270    pub amount: U256,
271    pub exec_layer_data: String,
272}
273
274pub struct CmaParserErc1155BatchWithdrawal {
275    pub receiver: Address,
276    pub token: Address,
277    pub count: usize,
278    pub token_ids: Vec<U256>,
279    pub amounts: Vec<U256>,
280    pub base_layer_data: String,
281    pub exec_layer_data: String,
282}
283
284pub struct CmaParserEtherTransfer {
285    pub sender: Address,
286    pub receiver: Address,
287    pub amount: U256,
288    pub exec_layer_data: String,
289}
290
291pub struct CmaParserErc20Transfer {
292    pub sender: Address,
293    pub receiver: Address,
294    pub token: Address,
295    pub amount: U256,
296    pub exec_layer_data: String,
297}
298
299pub struct CmaParserErc721Transfer {
300    pub sender: Address,
301    pub receiver: Address,
302    pub token: Address,
303    pub token_id: U256,
304    pub exec_layer_data: String,
305}
306
307pub struct CmaParserErc1155SingleTransfer {
308    pub sender: Address,
309    pub receiver: Address,
310    pub token: Address,
311    pub token_id: U256,
312    pub amount: U256,
313    pub exec_layer_data: String,
314}
315
316pub struct CmaParserErc1155BatchTransfer {
317    pub sender: Address,
318    pub receiver: Address,
319    pub token: Address,
320    pub count: usize,
321    pub token_ids: Vec<U256>,
322    pub amounts: Vec<U256>,
323    pub base_layer_data: String,
324    pub exec_layer_data: String,
325}
326
327pub struct CmaParserBalance {
328    pub account: Address,
329    pub token: Address,
330    pub token_ids: Option<Vec<U256>>,
331}
332
333pub struct CmaParserSupply {
334    pub token: Address,
335    pub token_ids: Vec<U256>,
336}
337
338pub enum CmaParserInputData {
339    EtherDeposit(CmaParserEtherDeposit),
340    Erc20Deposit(CmaParserErc20Deposit),
341    Erc721Deposit(CmaParserErc721Deposit),
342    Erc1155SingleDeposit(CmaParserErc1155SingleDeposit),
343    Erc1155BatchDeposit(CmaParserErc1155BatchDeposit),
344    EtherWithdrawal(CmaParserEtherWithdrawal),
345    Erc20Withdrawal(CmaParserErc20Withdrawal),
346    Erc721Withdrawal(CmaParserErc721Withdrawal),
347    Erc1155SingleWithdrawal(CmaParserErc1155SingleWithdrawal),
348    Erc1155BatchWithdrawal(CmaParserErc1155BatchWithdrawal),
349    EtherTransfer(CmaParserEtherTransfer),
350    Erc20Transfer(CmaParserErc20Transfer),
351    Erc721Transfer(CmaParserErc721Transfer),
352    Erc1155SingleTransfer(CmaParserErc1155SingleTransfer),
353    Erc1155BatchTransfer(CmaParserErc1155BatchTransfer),
354    Balance(CmaParserBalance),
355    Supply(CmaParserSupply),
356    Unidentified(CmaParserUnidentifiedInput),
357}
358
359pub struct CmaParserInput {
360    pub req_type: CmaParserInputType,
361    pub input: CmaParserInputData,
362}
363
364fn handle_unidentified_method(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
365    let payload_hex = input["data"]["payload"]
366        .as_str()
367        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
368    let payload_str = hex_to_string(payload_hex)
369        .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
370    let msg_sender =
371        input["data"]["metadata"]["msg_sender"]
372            .as_str()
373            .ok_or(CmaParserError::Message(String::from(
374                "Invalid msg_sender address",
375            )))?;
376    let sender = Address::from_slice(
377        &hex::decode(msg_sender.trim_start_matches("0x"))
378            .map_err(|e| CmaParserError::Message(format!("hex decode error: {}", e)))?,
379    );
380
381    match json::parse(&payload_str) {
382        Ok(parsed_json) => {
383            return Ok(CmaParserInputData::Unidentified(CmaParserUnidentifiedInput {
384                raw_input: CmaParserUnidentifiedInputType::CmaParserUnidentifiedInputJsonPayload(
385                    parsed_json,
386                ),
387                msg_sender: sender,
388            }));
389        }
390        Err(_) => {
391            return Ok(CmaParserInputData::Unidentified(CmaParserUnidentifiedInput {
392                raw_input:
393                    CmaParserUnidentifiedInputType::CmaParserUnidentifiedInputStringPayload(
394                        payload_str,
395                    ),
396                msg_sender: sender,
397            }));
398        }
399    }
400}
401
402fn handle_parse_ether_deposit(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
403    let payload_hex = input["data"]["payload"]
404        .as_str()
405        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
406    let payload = payload_hex.trim_start_matches("0x");
407
408    let bytes = hex::decode(payload)
409        .map_err(|e| CmaParserError::Message(format!("hex decode error: {}", e)))?;
410
411    if bytes.len() < 20 + 32 {
412        return Err(CmaParserError::Message(
413            "Invalid payload length".to_string(),
414        ));
415    }
416
417    let sender_bytes = &bytes[0..20];
418    let sender = Address::from_slice(sender_bytes);
419
420    let value_bytes = &bytes[20..52];
421    let value = U256::from_big_endian(value_bytes);
422
423    let exec_layer_data = Bytes::from(bytes[52..].to_vec());
424
425    Ok(CmaParserInputData::EtherDeposit(CmaParserEtherDeposit {
426        sender,
427        amount: value,
428        exec_layer_data,
429    }))
430}
431
432fn handle_parse_erc20_and_erc721_deposit(
433    input: JsonValue,
434    t_type: TokenType,
435) -> Result<CmaParserInputData, CmaParserError> {
436    let payload_hex = input["data"]["payload"]
437        .as_str()
438        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
439    let payload = payload_hex.trim_start_matches("0x");
440
441    let bytes = hex::decode(payload)
442        .map_err(|e| CmaParserError::Message(format!("hex decode error: {}", e)))?;
443
444    if bytes.len() < 20 + 20 + 32 {
445        return Err(CmaParserError::Message(
446            "Invalid payload length".to_string(),
447        ));
448    }
449
450    let token = &bytes[0..20];
451    let sender = &bytes[20..40];
452    let amount_bytes = &bytes[40..72];
453    let amount = U256::from_big_endian(amount_bytes);
454    let exec_layer_data = Bytes::from(bytes[72..].to_vec());
455
456    match t_type {
457        TokenType::Erc20 => Ok(CmaParserInputData::Erc20Deposit(CmaParserErc20Deposit {
458            sender: Address::from_slice(sender),
459            token: Address::from_slice(token),
460            amount,
461            exec_layer_data,
462        })),
463        TokenType::Erc721 => Ok(CmaParserInputData::Erc721Deposit(CmaParserErc721Deposit {
464            sender: Address::from_slice(sender),
465            token: Address::from_slice(token),
466            token_id: amount,
467            exec_layer_data,
468        })),
469    }
470}
471
472fn handle_parse_erc1155_single_deposit(
473    input: JsonValue,
474) -> Result<CmaParserInputData, CmaParserError> {
475    let payload_hex = input["data"]["payload"]
476        .as_str()
477        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
478    let payload = payload_hex.trim_start_matches("0x");
479
480    let bytes = hex::decode(payload)
481        .map_err(|e| CmaParserError::Message(format!("hex decode error: {}", e)))?;
482
483    if bytes.len() < 20 + 20 + 32 + 32 {
484        return Err(CmaParserError::Message(
485            "Invalid payload length".to_string(),
486        ));
487    }
488
489    let token = &bytes[0..20];
490    let sender = &bytes[20..40];
491    let token_id_bytes = &bytes[40..72];
492    let token_id = U256::from_big_endian(token_id_bytes);
493    let amount_bytes = &bytes[72..104];
494    let amount = U256::from_big_endian(amount_bytes);
495    let _base_layer_data = Bytes::from(bytes[104..136].to_vec());
496    let exec_layer_data = Bytes::from(bytes[136..].to_vec());
497
498    Ok(CmaParserInputData::Erc1155SingleDeposit(
499        CmaParserErc1155SingleDeposit {
500            sender: Address::from_slice(sender),
501            token: Address::from_slice(token),
502            token_id,
503            amount,
504            exec_layer_data,
505        },
506    ))
507}
508
509fn handle_parse_erc1155_batch_deposit(
510    input: JsonValue,
511) -> Result<CmaParserInputData, CmaParserError> {
512    let payload_hex = input["data"]["payload"]
513        .as_str()
514        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
515    let payload = payload_hex.trim_start_matches("0x");
516
517    let bytes = hex::decode(payload)
518        .map_err(|e| CmaParserError::Message(format!("hex decode error: {}", e)))?;
519
520    if bytes.len() < 20 + 20 + 32 + 32 + 32 {
521        return Err(CmaParserError::Message(
522            "Invalid payload length".to_string(),
523        ));
524    }
525
526    let u256_from = |b: &[u8]| U256::from_big_endian(b);
527    let as_addr = |b: &[u8]| Address::from_slice(&b[12..32]);
528
529    let token = as_addr(&bytes[0..32]);
530    let sender = as_addr(&bytes[32..64]);
531
532    let token_ids_offset = u256_from(&bytes[64..96]).as_usize();
533    let values_offset = u256_from(&bytes[96..128]).as_usize();
534    let base_offset = u256_from(&bytes[128..160]).as_usize();
535    let exec_offset = u256_from(&bytes[160..192]).as_usize();
536
537    let token_ids_len = u256_from(&bytes[token_ids_offset..token_ids_offset + 32]).as_usize();
538    let mut token_ids = Vec::with_capacity(token_ids_len);
539
540    let mut cursor = token_ids_offset + 32;
541    for _ in 0..token_ids_len {
542        token_ids.push(u256_from(&bytes[cursor..cursor + 32]));
543        cursor += 32;
544    }
545
546    let values_len = u256_from(&bytes[values_offset..values_offset + 32]).as_usize();
547    let mut values = Vec::with_capacity(values_len);
548
549    let mut cursor2 = values_offset + 32;
550    for _ in 0..values_len {
551        values.push(u256_from(&bytes[cursor2..cursor2 + 32]));
552        cursor2 += 32;
553    }
554
555    let base_len = u256_from(&bytes[base_offset..base_offset + 32]).as_usize();
556    let base_start = base_offset + 32;
557    let base_end = base_start + base_len;
558    let base_layer_data = Bytes::from(bytes[base_start..base_end].to_vec());
559
560    let exec_len = u256_from(&bytes[exec_offset..exec_offset + 32]).as_usize();
561    let exec_start = exec_offset + 32;
562    let exec_end = exec_start + exec_len;
563    let exec_layer_data = Bytes::from(bytes[exec_start..exec_end].to_vec());
564
565    if token_ids_len == 0 || values_len == 0 || token_ids_len != values_len {
566        return Err(CmaParserError::Message("Invalid payload data".to_string()));
567    }
568
569    Ok(CmaParserInputData::Erc1155BatchDeposit(
570        CmaParserErc1155BatchDeposit {
571            sender,
572            token,
573            count: token_ids_len,
574            token_ids,
575            amounts: values,
576            base_layer_data,
577            exec_layer_data,
578        },
579    ))
580}
581
582fn handle_ether_withdrawal(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
583    let payload_hex = input["data"]["payload"]
584        .as_str()
585        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
586    let payload_str = hex_to_string(payload_hex)
587        .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
588    let msg_sender =
589        input["data"]["metadata"]["msg_sender"]
590            .as_str()
591            .ok_or(CmaParserError::Message(String::from(
592                "Invalid msg_sender address",
593            )))?;
594
595    match json::parse(&payload_str) {
596        Ok(parsed_json) => {
597            let receiver = msg_sender
598                .parse::<Address>()
599                .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
600            let amount_str = parsed_json["amount"]
601                .as_str()
602                .ok_or(CmaParserError::Message(String::from("Invalid amount")))?;
603            let amount = U256::from_dec_str(amount_str)
604                .map_err(|e| CmaParserError::Message(format!("amount parse error: {}", e)))?;
605            let exec_layer_data = parsed_json["exec_layer_data"].to_string();
606
607            Ok(CmaParserInputData::EtherWithdrawal(
608                CmaParserEtherWithdrawal {
609                    receiver,
610                    amount,
611                    exec_layer_data,
612                },
613            ))
614        }
615        Err(_) => Err(CmaParserError::Message(String::from(
616            "Failed to parse JSON payload",
617        ))),
618    }
619}
620
621fn handle_erc20_withdrawal(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
622    let payload_hex = input["data"]["payload"]
623        .as_str()
624        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
625    let payload_str = hex_to_string(payload_hex)
626        .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
627    let msg_sender =
628        input["data"]["metadata"]["msg_sender"]
629            .as_str()
630            .ok_or(CmaParserError::Message(String::from(
631                "Invalid msg_sender address",
632            )))?;
633
634    match json::parse(&payload_str) {
635        Ok(parsed_json) => {
636            let receiver = msg_sender
637                .parse::<Address>()
638                .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
639            let token_str = parsed_json["token"]
640                .as_str()
641                .ok_or(CmaParserError::Message(String::from(
642                    "Invalid token address",
643                )))?;
644            let token = token_str
645                .parse::<Address>()
646                .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
647            let amount_str = parsed_json["amount"]
648                .as_str()
649                .ok_or(CmaParserError::Message(String::from("Invalid amount")))?;
650            let amount = U256::from_dec_str(amount_str)
651                .map_err(|e| CmaParserError::Message(format!("amount parse error: {}", e)))?;
652            let exec_layer_data = parsed_json["exec_layer_data"].to_string();
653
654            Ok(CmaParserInputData::Erc20Withdrawal(
655                CmaParserErc20Withdrawal {
656                    receiver,
657                    token,
658                    amount,
659                    exec_layer_data,
660                },
661            ))
662        }
663        Err(_) => Err(CmaParserError::Message(String::from(
664            "Failed to parse JSON payload",
665        ))),
666    }
667}
668
669fn handle_erc721_withdrawal(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
670    let payload_hex = input["data"]["payload"]
671        .as_str()
672        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
673    let payload_str = hex_to_string(payload_hex)
674        .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
675    let msg_sender =
676        input["data"]["metadata"]["msg_sender"]
677            .as_str()
678            .ok_or(CmaParserError::Message(String::from(
679                "Invalid msg_sender address",
680            )))?;
681
682    match json::parse(&payload_str) {
683        Ok(parsed_json) => {
684            let receiver = msg_sender
685                .parse::<Address>()
686                .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
687            let token_str = parsed_json["token"]
688                .as_str()
689                .ok_or(CmaParserError::Message(String::from(
690                    "Invalid token address",
691                )))?;
692            let token = token_str
693                .parse::<Address>()
694                .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
695            let token_id_str = parsed_json["id"]
696                .as_str()
697                .ok_or(CmaParserError::Message(String::from("Invalid token id")))?;
698            let token_id = U256::from_dec_str(token_id_str)
699                .map_err(|e| CmaParserError::Message(format!("token id parse error: {}", e)))?;
700            let exec_layer_data = parsed_json["exec_layer_data"].to_string();
701
702            Ok(CmaParserInputData::Erc721Withdrawal(
703                CmaParserErc721Withdrawal {
704                    receiver,
705                    token,
706                    token_id,
707                    exec_layer_data,
708                },
709            ))
710        }
711        Err(_) => Err(CmaParserError::Message(String::from(
712            "Failed to parse JSON payload",
713        ))),
714    }
715}
716
717fn handle_ether_transfer(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
718    let payload_hex = input["data"]["payload"]
719        .as_str()
720        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
721    let payload_str = hex_to_string(payload_hex)
722        .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
723    let msg_sender =
724        input["data"]["metadata"]["msg_sender"]
725            .as_str()
726            .ok_or(CmaParserError::Message(String::from(
727                "Invalid msg_sender address",
728            )))?;
729
730    match json::parse(&payload_str) {
731        Ok(parsed_json) => {
732            let sender = msg_sender
733                .parse::<Address>()
734                .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
735            let receiver_str = parsed_json["receiver"]
736                .as_str()
737                .ok_or(CmaParserError::Message(String::from(
738                    "Invalid receiver address",
739                )))?;
740            let receiver = receiver_str
741                .parse::<Address>()
742                .map_err(|e| CmaParserError::Message(format!("receiver address error: {}", e)))?;
743            let amount_str = parsed_json["amount"]
744                .as_str()
745                .ok_or(CmaParserError::Message(String::from("Invalid amount")))?;
746            let amount = U256::from_dec_str(amount_str)
747                .map_err(|e| CmaParserError::Message(format!("amount parse error: {}", e)))?;
748            let exec_layer_data = parsed_json["exec_layer_data"].to_string();
749
750            Ok(CmaParserInputData::EtherTransfer(CmaParserEtherTransfer {
751                sender,
752                receiver,
753                amount,
754                exec_layer_data,
755            }))
756        }
757        Err(_) => Err(CmaParserError::Message(String::from(
758            "Failed to parse JSON payload",
759        ))),
760    }
761}
762
763fn handle_erc20_transfer(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
764    let payload_hex = input["data"]["payload"]
765        .as_str()
766        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
767    let payload_str = hex_to_string(payload_hex)
768        .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
769    let msg_sender =
770        input["data"]["metadata"]["msg_sender"]
771            .as_str()
772            .ok_or(CmaParserError::Message(String::from(
773                "Invalid msg_sender address",
774            )))?;
775
776    match json::parse(&payload_str) {
777        Ok(parsed_json) => {
778            let sender = msg_sender
779                .parse::<Address>()
780                .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
781            let receiver_str = parsed_json["receiver"]
782                .as_str()
783                .ok_or(CmaParserError::Message(String::from(
784                    "Invalid receiver address",
785                )))?;
786            let receiver = receiver_str
787                .parse::<Address>()
788                .map_err(|e| CmaParserError::Message(format!("receiver address error: {}", e)))?;
789            let token_str = parsed_json["token"]
790                .as_str()
791                .ok_or(CmaParserError::Message(String::from(
792                    "Invalid token address",
793                )))?;
794            let token = token_str
795                .parse::<Address>()
796                .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
797            let amount_str = parsed_json["amount"]
798                .as_str()
799                .ok_or(CmaParserError::Message(String::from("Invalid amount")))?;
800            let amount = U256::from_dec_str(amount_str)
801                .map_err(|e| CmaParserError::Message(format!("amount parse error: {}", e)))?;
802            let exec_layer_data = parsed_json["exec_layer_data"].to_string();
803
804            Ok(CmaParserInputData::Erc20Transfer(CmaParserErc20Transfer {
805                sender,
806                receiver,
807                token,
808                amount,
809                exec_layer_data,
810            }))
811        }
812        Err(_) => Err(CmaParserError::Message(String::from(
813            "Failed to parse JSON payload",
814        ))),
815    }
816}
817
818fn handle_erc721_transfer(input: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
819    let payload_hex = input["data"]["payload"]
820        .as_str()
821        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
822    let payload_str = hex_to_string(payload_hex)
823        .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
824    let msg_sender =
825        input["data"]["metadata"]["msg_sender"]
826            .as_str()
827            .ok_or(CmaParserError::Message(String::from(
828                "Invalid msg_sender address",
829            )))?;
830
831    match json::parse(&payload_str) {
832        Ok(parsed_json) => {
833            let sender = msg_sender
834                .parse::<Address>()
835                .map_err(|e| CmaParserError::Message(format!("msg_sender address error: {}", e)))?;
836            let receiver_str = parsed_json["receiver"]
837                .as_str()
838                .ok_or(CmaParserError::Message(String::from(
839                    "Invalid receiver address",
840                )))?;
841            let receiver = receiver_str
842                .parse::<Address>()
843                .map_err(|e| CmaParserError::Message(format!("receiver address error: {}", e)))?;
844            let token_str = parsed_json["token"]
845                .as_str()
846                .ok_or(CmaParserError::Message(String::from(
847                    "Invalid token address",
848                )))?;
849            let token = token_str
850                .parse::<Address>()
851                .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
852            let token_id_str = parsed_json["id"]
853                .as_str()
854                .ok_or(CmaParserError::Message(String::from("Invalid token id")))?;
855            let token_id = U256::from_dec_str(token_id_str)
856                .map_err(|e| CmaParserError::Message(format!("token id parse error: {}", e)))?;
857            let exec_layer_data = parsed_json["exec_layer_data"].to_string();
858
859            Ok(CmaParserInputData::Erc721Transfer(
860                CmaParserErc721Transfer {
861                    sender,
862                    receiver,
863                    token,
864                    token_id,
865                    exec_layer_data,
866                },
867            ))
868        }
869        Err(_) => Err(CmaParserError::Message(String::from(
870            "Failed to parse JSON payload",
871        ))),
872    }
873}
874
875pub fn cma_decode_advance(input: JsonValue) -> Result<CmaParserInput, CmaParserError> {
876    let msg_sender =
877        input["data"]["metadata"]["msg_sender"]
878            .as_str()
879            .ok_or(CmaParserError::Message(String::from(
880                "Invalid msg_sender address",
881            )))?;
882    let req_type: CmaParserInputType;
883
884    // Determine the portal type based on msg_sender
885    match CARTESI_ADDRESSES.match_portal(msg_sender) {
886        Portals::ERC1155BatchPortal => {
887            req_type = CmaParserInputType::CmaParserInputTypeErc1155BatchDeposit;
888            return handle_parse_erc1155_batch_deposit(input).map(|data| CmaParserInput {
889                req_type,
890                input: data,
891            });
892        }
893        Portals::ERC1155SinglePortal => {
894            req_type = CmaParserInputType::CmaParserInputTypeErc1155SingleDeposit;
895            return handle_parse_erc1155_single_deposit(input).map(|data| CmaParserInput {
896                req_type,
897                input: data,
898            });
899        }
900        Portals::ERC721Portal => {
901            req_type = CmaParserInputType::CmaParserInputTypeErc721Deposit;
902            return handle_parse_erc20_and_erc721_deposit(input, TokenType::Erc721).map(|data| {
903                CmaParserInput {
904                    req_type,
905                    input: data,
906                }
907            });
908        }
909        Portals::ERC20Portal => {
910            req_type = CmaParserInputType::CmaParserInputTypeErc20Deposit;
911            return handle_parse_erc20_and_erc721_deposit(input, TokenType::Erc20).map(|data| {
912                CmaParserInput {
913                    req_type,
914                    input: data,
915                }
916            });
917        }
918        Portals::EtherPortal => {
919            req_type = CmaParserInputType::CmaParserInputTypeEtherDeposit;
920            return handle_parse_ether_deposit(input).map(|data| CmaParserInput {
921                req_type,
922                input: data,
923            });
924        }
925        // IF CALLER IS NOT ANY OF THE ABOVE PORTALS, WE TRY TO PARSE THE PAYLOAD FOR WITHDRAWALS/TRANSFERS
926        Portals::None => {
927            let payload_hex = input["data"]["payload"]
928                .as_str()
929                .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
930            let payload_str = hex_to_string(payload_hex).map_err(|e| {
931                CmaParserError::Message(format!("hex to string conversion error: {}", e))
932            })?;
933
934            match json::parse(&payload_str) {
935                Ok(parsed_json) => {
936                    let function_type =
937                        parsed_json["function_type"]
938                            .as_str()
939                            .ok_or(CmaParserError::Message(String::from(
940                                "Invalid function type",
941                            )))?;
942
943                    // Determine the request type based on function_type
944                    req_type = CmaParserInputType::from_string(function_type);
945
946                    // Handle the request based on the determined type
947                    match req_type {
948                        CmaParserInputType::CmaParserInputTypeEtherWithdrawal => {
949                            return handle_ether_withdrawal(input).map(|data| CmaParserInput {
950                                req_type,
951                                input: data,
952                            });
953                        }
954
955                        CmaParserInputType::CmaParserInputTypeErc20Withdrawal => {
956                            return handle_erc20_withdrawal(input).map(|data| CmaParserInput {
957                                req_type,
958                                input: data,
959                            });
960                        }
961                        CmaParserInputType::CmaParserInputTypeErc721Withdrawal => {
962                            return handle_erc721_withdrawal(input).map(|data| CmaParserInput {
963                                req_type,
964                                input: data,
965                            });
966                        }
967                        CmaParserInputType::CmaParserInputTypeEtherTransfer => {
968                            return handle_ether_transfer(input).map(|data| CmaParserInput {
969                                req_type,
970                                input: data,
971                            });
972                        }
973                        CmaParserInputType::CmaParserInputTypeErc20Transfer => {
974                            return handle_erc20_transfer(input).map(|data| CmaParserInput {
975                                req_type,
976                                input: data,
977                            });
978                        }
979                        CmaParserInputType::CmaParserInputTypeErc721Transfer => {
980                            return handle_erc721_transfer(input).map(|data| CmaParserInput {
981                                req_type,
982                                input: data,
983                            });
984                        }
985                        CmaParserInputType::CmaParserInputTypeUnidentified => {
986                           return handle_unidentified_method(input).map(|data| CmaParserInput {
987                                req_type,
988                                input: data,
989                            });
990                        }
991                        _ => Err(CmaParserError::IncompatibleInput),
992                    }
993                }
994                Err(_) => {
995                    return Err(CmaParserError::Message(String::from(
996                        "Failed to parse JSON payload",
997                    )))
998                }
999            }
1000        }
1001    }
1002}
1003
1004fn handle_ledger_get_balance(parsed_json: JsonValue) -> Result<CmaParserBalance, CmaParserError> {
1005    // Extract params array
1006    let params_val = &parsed_json["params"];
1007    if !params_val.is_array() {
1008        return Err(CmaParserError::Message(
1009            "Invalid params: not an array".into(),
1010        ));
1011    }
1012
1013    // params[0] = account
1014    let account_str = params_val[0]
1015        .as_str()
1016        .ok_or_else(|| CmaParserError::Message("Invalid account param".into()))?;
1017
1018    let account = account_str
1019        .parse::<Address>()
1020        .map_err(|e| CmaParserError::Message(format!("account address error: {}", e)))?;
1021
1022    // params[1] = token
1023    let token_str = params_val[1]
1024        .as_str()
1025        .ok_or_else(|| CmaParserError::Message("Invalid token param".into()))?;
1026
1027    let token = token_str
1028        .parse::<Address>()
1029        .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
1030
1031    // params[2] = optional array containing token id's
1032    let mut token_id: Vec<U256> = Vec::new();
1033    if params_val.len() > 2 && params_val[2].is_array() {
1034        // params_val[2][0] might itself be an array of ids or params_val[2] might be the array
1035        if params_val[2][0].is_array() {
1036            for v in params_val[2][0].members() {
1037                let s = v
1038                    .as_str()
1039                    .ok_or_else(|| CmaParserError::Message("Invalid token id".into()))?;
1040                let id = U256::from_dec_str(s)
1041                    .map_err(|e| CmaParserError::Message(format!("token id parse error: {}", e)))?;
1042                token_id.push(id);
1043            }
1044        } else {
1045            // handle array of strings/numbers or comma-separated string(s)
1046            for v in params_val[2].members() {
1047                if let Some(s) = v.as_str() {
1048                    if s.contains(',') {
1049                        for part in s.split(',').map(str::trim).filter(|p| !p.is_empty()) {
1050                            let id = U256::from_dec_str(part).map_err(|e| {
1051                                CmaParserError::Message(format!("token id parse error: {}", e))
1052                            })?;
1053                            token_id.push(id);
1054                        }
1055                    } else {
1056                        let id = U256::from_dec_str(s).map_err(|e| {
1057                            CmaParserError::Message(format!("token id parse error: {}", e))
1058                        })?;
1059                        token_id.push(id);
1060                    }
1061                } else if v.is_number() {
1062                    let id = U256::from_dec_str(&v.to_string()).map_err(|e| {
1063                        CmaParserError::Message(format!("token id parse error: {}", e))
1064                    })?;
1065                    token_id.push(id);
1066                } else {
1067                    return Err(CmaParserError::Message("Invalid token id format".into()));
1068                }
1069            }
1070        }
1071    }
1072
1073    Ok(CmaParserBalance {
1074        account,
1075        token,
1076        token_ids: Some(token_id),
1077    })
1078}
1079
1080fn handle_ledger_get_supply(parsed_json: JsonValue) -> Result<CmaParserInputData, CmaParserError> {
1081    // Ensure params is an array
1082    let params_val = &parsed_json["params"];
1083    if !params_val.is_array() {
1084        return Err(CmaParserError::Message(
1085            "Invalid params: not an array".into(),
1086        ));
1087    }
1088
1089    // params[0] = token address string
1090    let token_str = params_val[0]
1091        .as_str()
1092        .ok_or_else(|| CmaParserError::Message("Invalid token param".into()))?;
1093
1094    let token = token_str
1095        .parse::<Address>()
1096        .map_err(|e| CmaParserError::Message(format!("token address error: {}", e)))?;
1097
1098    // params[1] = optional array containing token id's
1099    let mut token_id: Vec<U256> = Vec::new();
1100    if params_val.len() > 1 && params_val[1].is_array() {
1101        // params_val[1][0] might itself be an array of ids or params_val[1] might be the array
1102        if params_val[1][0].is_array() {
1103            for v in params_val[1][0].members() {
1104                let s = v
1105                    .as_str()
1106                    .ok_or_else(|| CmaParserError::Message("Invalid token id".into()))?;
1107                let id = U256::from_dec_str(s)
1108                    .map_err(|e| CmaParserError::Message(format!("token id parse error: {}", e)))?;
1109                token_id.push(id);
1110            }
1111        } else {
1112            // handle array of strings/numbers or comma-separated string(s)
1113            for v in params_val[1].members() {
1114                if let Some(s) = v.as_str() {
1115                    if s.contains(',') {
1116                        for part in s.split(',').map(str::trim).filter(|p| !p.is_empty()) {
1117                            let id = U256::from_dec_str(part).map_err(|e| {
1118                                CmaParserError::Message(format!("token id parse error: {}", e))
1119                            })?;
1120                            token_id.push(id);
1121                        }
1122                    } else {
1123                        let id = U256::from_dec_str(s).map_err(|e| {
1124                            CmaParserError::Message(format!("token id parse error: {}", e))
1125                        })?;
1126                        token_id.push(id);
1127                    }
1128                } else if v.is_number() {
1129                    let id = U256::from_dec_str(&v.to_string()).map_err(|e| {
1130                        CmaParserError::Message(format!("token id parse error: {}", e))
1131                    })?;
1132                    token_id.push(id);
1133                } else {
1134                    return Err(CmaParserError::Message("Invalid token id format".into()));
1135                }
1136            }
1137        }
1138    }
1139
1140    Ok(CmaParserInputData::Supply(CmaParserSupply {
1141        token,
1142        token_ids: token_id,
1143    }))
1144}
1145
1146pub fn cma_decode_inspect(input: JsonValue) -> Result<CmaParserInput, CmaParserError> {
1147    let payload_hex = input["data"]["payload"]
1148        .as_str()
1149        .ok_or(CmaParserError::Message(String::from("Invalid payload hex")))?;
1150    let payload_str = hex_to_string(payload_hex)
1151        .map_err(|e| CmaParserError::Message(format!("hex to string conversion error: {}", e)))?;
1152    let payload_json = json::parse(&payload_str)
1153        .map_err(|e| CmaParserError::Message(format!("Error parsing string to JSON: {}", e)))?;
1154
1155    let req_type: CmaParserInputType =
1156        CmaParserInputType::from_string(payload_json["method"].as_str().ok_or(
1157            CmaParserError::Message(String::from("Invalid inspection type")),
1158        )?);
1159
1160    match req_type {
1161        CmaParserInputType::CmaParserInputTypeBalance => {
1162            return handle_ledger_get_balance(payload_json).map(|data| CmaParserInput {
1163                req_type,
1164                input: CmaParserInputData::Balance(data),
1165            });
1166        }
1167        CmaParserInputType::CmaParserInputTypeSupply => {
1168            return handle_ledger_get_supply(payload_json).map(|data| CmaParserInput {
1169                req_type,
1170                input: data,
1171            });
1172        }
1173        _ => {
1174            // Unsupported inspection type
1175            return Err(CmaParserError::IncompatibleInput);
1176        }
1177    }
1178}
1179
1180fn handle_ether_voucher_encoding(
1181    voucher_request: &CmaVoucherFieldType,
1182) -> Result<CmaVoucher, CmaParserError> {
1183    if let CmaVoucherFieldType::EtherVoucherFields(fields) = &voucher_request {
1184        let payload = "0x".to_string();
1185
1186        let mut value_bytes = [0u8; 32];
1187        fields.amount.to_big_endian(&mut value_bytes);
1188
1189        let voucher = CmaVoucher {
1190            destination: to_checksum(&fields.receiver, None),
1191            value: format!("0x{}", hex::encode(value_bytes)),
1192            payload,
1193        };
1194
1195        Ok(voucher)
1196    } else {
1197        Err(CmaParserError::Message(String::from(
1198            "Invalid voucher fields for Ether",
1199        )))
1200    }
1201}
1202
1203fn handle_erc20_voucher_encoding(
1204    voucher_request: &CmaVoucherFieldType,
1205) -> Result<CmaVoucher, CmaParserError> {
1206    if let CmaVoucherFieldType::Erc20VoucherFields(fields) = &voucher_request {
1207        let token = fields.token;
1208
1209        let args: Vec<Token> = vec![Token::Address(fields.receiver), Token::Uint(fields.amount)];
1210
1211        let function_sig = "transfer(address,uint256)";
1212        let selector = &id(function_sig)[..4];
1213
1214        let encoded_args = encode(&args);
1215        let value = fields.value;
1216        let mut payload_bytes = Vec::new();
1217        payload_bytes.extend_from_slice(selector);
1218        payload_bytes.extend_from_slice(&encoded_args);
1219        let payload = format!("0x{}", hex::encode(payload_bytes));
1220
1221        let mut value_bytes = [0u8; 32];
1222        value.to_big_endian(&mut value_bytes);
1223
1224        let voucher = CmaVoucher {
1225            destination: format!("{:?}", token),
1226            value: format!("0x{}", hex::encode(value_bytes)),
1227            payload: format!("{}", payload),
1228        };
1229        return Ok(voucher);
1230    } else {
1231        Err(CmaParserError::Message(String::from(
1232            "Invalid voucher fields for ERC20",
1233        )))
1234    }
1235}
1236
1237fn handle_erc721_voucher_encoding(
1238    voucher_request: &CmaVoucherFieldType,
1239) -> Result<CmaVoucher, CmaParserError> {
1240    if let CmaVoucherFieldType::Erc721VoucherFields(fields) = &voucher_request {
1241        let token = fields.token;
1242
1243        let args: Vec<Token> = vec![
1244            Token::Address(fields.application_address),
1245            Token::Address(fields.receiver),
1246            Token::Uint(fields.token_id.into()),
1247        ];
1248        let function_sig = "transferFrom(address,address,uint256)";
1249        let selector = &id(function_sig)[..4];
1250        let encoded_args = encode(&args);
1251        let value = fields.value;
1252        let mut payload_bytes = Vec::new();
1253        payload_bytes.extend_from_slice(selector);
1254        payload_bytes.extend_from_slice(&encoded_args);
1255        let payload = format!("0x{}", hex::encode(payload_bytes));
1256
1257        let mut value_bytes = [0u8; 32];
1258        value.to_big_endian(&mut value_bytes);
1259
1260        let voucher = CmaVoucher {
1261            destination: format!("{:?}", token),
1262            value: format!("0x{}", hex::encode(value_bytes)),
1263            payload: format!("{}", payload),
1264        };
1265
1266        return Ok(voucher);
1267    } else {
1268        Err(CmaParserError::Message(String::from(
1269            "Invalid voucher fields for ERC721",
1270        )))
1271    }
1272}
1273
1274pub fn cma_encode_voucher(
1275    req_type: CmaParserVoucherType,
1276    voucher_request: CmaVoucherFieldType,
1277) -> Result<CmaVoucher, CmaParserError> {
1278    match req_type {
1279        CmaParserVoucherType::CmaParserVoucherTypeEther => {
1280            return handle_ether_voucher_encoding(&voucher_request);
1281        }
1282        CmaParserVoucherType::CmaParserVoucherTypeErc20 => {
1283            return handle_erc20_voucher_encoding(&voucher_request);
1284        }
1285        CmaParserVoucherType::CmaParserVoucherTypeErc721 => {
1286            return handle_erc721_voucher_encoding(&voucher_request);
1287        }
1288        CmaParserVoucherType::CmaParserVoucherTypeErc1155Single => {
1289            // TODO Implement encoding logic for ERC1155 Single voucher
1290            return Err(CmaParserError::Message(String::from("Not Implemented yet")));
1291        }
1292        CmaParserVoucherType::CmaParserVoucherTypeErc1155Batch => {
1293            // TODO Implement encoding logic for ERC1155 Batch voucher
1294            return Err(CmaParserError::Message(String::from("Not Implemented yet")));
1295        }
1296        CmaParserVoucherType::CmaParserVoucherTypeNone => {
1297            return Err(CmaParserError::Message(String::from("Not Implemented yet")))
1298        }
1299    }
1300}