ccnext_abi_encoding/abi/
mod.rs

1use super::common::AbiEncodeResult;
2use alloy::{
3    dyn_abi::DynSolValue,
4    primitives::U256,
5    rpc::types::{Transaction, TransactionReceipt},
6};
7use thiserror::Error;
8
9mod v1;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum EncodingVersion {
13    V1 = 1,
14}
15
16fn encode_receipt(rx: TransactionReceipt) -> Vec<DynSolValue> {
17    let log_blooms = rx.inner.logs_bloom().0.to_vec();
18    let result = vec![
19        DynSolValue::Uint(U256::from(rx.status()), 8),
20        DynSolValue::Uint(U256::from(rx.gas_used), 64),
21        DynSolValue::Array(
22            rx.inner
23                .logs()
24                .iter()
25                .map(|log| {
26                    let topics = DynSolValue::Array(
27                        log.topics()
28                            .iter()
29                            .map(|topic| DynSolValue::FixedBytes(*topic, 32))
30                            .collect(),
31                    );
32
33                    DynSolValue::Tuple(vec![
34                        DynSolValue::Address(log.address()),
35                        topics,
36                        DynSolValue::Bytes(log.data().data.to_vec()),
37                    ])
38                })
39                .collect(),
40        ),
41        DynSolValue::Bytes(log_blooms),
42    ];
43
44    result
45}
46
47#[derive(Debug, Error)]
48pub enum EncodeError {
49    #[error("Custom error: {0}")]
50    Custom(String),
51}
52pub fn abi_encode(
53    tx: Transaction,
54    rx: TransactionReceipt,
55    version: EncodingVersion,
56) -> Result<AbiEncodeResult, Box<dyn std::error::Error>> {
57    let transaction_fields = match version {
58        EncodingVersion::V1 => v1::encode_transaction(tx),
59    };
60    let receipt_fields = encode_receipt(rx);
61    let mut all_fields = Vec::new();
62    all_fields.extend(transaction_fields);
63    all_fields.extend(receipt_fields);
64    let tuple = DynSolValue::Tuple(all_fields.clone());
65    let final_bytes = match tuple.abi_encode_sequence() {
66        Some(final_bytes) => final_bytes,
67        None => {
68            return Err(Box::new(EncodeError::Custom(
69                "Failed to encode sequence".into(),
70            )));
71        }
72    };
73
74    let field_types: Vec<String> = all_fields
75        .into_iter()
76        .map(|field| match field.as_type() {
77            Some(sol_type) => sol_type.sol_type_name().into_owned(),
78            None => "unknown".into(),
79        })
80        .collect();
81
82    Ok(AbiEncodeResult {
83        types: field_types,
84        abi: final_bytes,
85    })
86}