cpchain_rust_sdk/
types.rs

1use rlp::RlpStream;
2use serde::{Deserialize, Serialize};
3use web3::{signing::{self, Signature}, types::{SignedTransaction, CallRequest}};
4
5pub type Result = web3::Result;
6pub type U256 = web3::types::U256;
7pub type U128 = web3::types::U128;
8pub type U64 = web3::types::U64;
9pub type H160 = web3::types::H160;
10pub type H256 = web3::types::H256;
11pub type Bytes = web3::types::Bytes;
12pub type Options = web3::contract::Options;
13pub type Transaction = web3::types::Transaction;
14pub type TransactionReceipt = web3::types::TransactionReceipt;
15pub type TransactionLog = web3::types::Log;
16pub type BlockWithHash = web3::types::Block<H256>;
17pub type BlockWithTx = web3::types::Block<Transaction>;
18
19#[derive(Debug, Clone, Deserialize, Serialize)]
20pub struct TransactionParameters {
21    /// Transaction type
22    #[serde(rename="type")]
23    pub tx_type: U256,
24    /// Transaction nonce (None for account transaction count)
25    pub nonce: U256,
26    /// To address
27    pub to: Option<H160>,
28    /// Supplied gas
29    pub gas: U256,
30    /// Gas price (None for estimated gas price)
31    #[serde(rename="gasPrice")]
32    pub gas_price: U256,
33    /// Transferred value
34    pub value: U256,
35    /// Data
36    pub data: Bytes,
37    /// The chain ID (None for network ID)
38    pub chain_id: u64,
39}
40
41impl TransactionParameters {
42    pub fn new(
43        chain_id: u64,
44        nonce: U256,
45        to: Option<H160>,
46        gas: U256,
47        gas_price: U256,
48        value: U256,
49        data: Bytes,
50    ) -> TransactionParameters {
51        Self {
52            nonce,
53            to,
54            gas,
55            gas_price,
56            value,
57            data,
58            chain_id,
59            tx_type: U256::from(0)
60        }
61    }
62    pub fn to_call_request(&self) -> CallRequest {
63        CallRequest {
64            from: None,
65            to: self.to,
66            gas: None,
67            gas_price: Some(self.gas_price),
68            value: Some(self.value),
69            data: Some(self.data.clone()),
70            transaction_type: None,
71            access_list: None,
72            max_fee_per_gas: None,
73            max_priority_fee_per_gas: None,
74        }
75    }
76    fn rlp_append_legacy(&self, stream: &mut RlpStream) {
77        // transactinon type for CPChain
78        stream.append(&self.tx_type);
79        stream.append(&self.nonce);
80        stream.append(&self.gas_price);
81        stream.append(&self.gas);
82        if let Some(to) = self.to {
83            stream.append(&to);
84        } else {
85            stream.append(&"");
86        }
87        stream.append(&self.value);
88        stream.append(&self.data.0);
89    }
90    fn rlp_append_signature(&self, stream: &mut RlpStream, signature: &Signature) {
91        stream.append(&signature.v);
92        stream.append(&U256::from_big_endian(signature.r.as_bytes()));
93        stream.append(&U256::from_big_endian(signature.s.as_bytes()));
94    }
95    fn encode(&self, chain_id: u64, signature: Option<&Signature>) -> RlpStream {
96        let mut stream = RlpStream::new();
97        stream.begin_list(10);
98
99        self.rlp_append_legacy(&mut stream);
100
101        if let Some(signature) = signature {
102            self.rlp_append_signature(&mut stream, signature);
103        } else {
104            stream.append(&chain_id);
105            stream.append(&0u8);
106            stream.append(&0u8);
107        }
108        stream
109    }
110    pub fn sign(&self, sign: impl signing::Key) -> SignedTransaction {
111        let encoded = self.encode(self.chain_id, None).out().to_vec();
112
113        let hash = signing::keccak256(encoded.as_ref());
114
115        let signature = sign.sign(&hash, Some(self.chain_id)).expect("hash is non-zero 32-bytes; qed");
116
117        let signed = self.encode(self.chain_id, Some(&signature)).out().to_vec();
118        let transaction_hash = signing::keccak256(signed.as_ref()).into();
119
120        SignedTransaction {
121            message_hash: hash.into(),
122            v: signature.v,
123            r: signature.r,
124            s: signature.s,
125            raw_transaction: signed.into(),
126            transaction_hash,
127        }
128    }
129}