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