1use crate::{Bytes, SignedAuthorization};
22use cfx_rpc_cfx_types::Transaction as CfxTransaction;
23use cfx_types::{
24 cal_contract_address, CreateContractAddressType, H160, H256, H512, U256,
25 U64,
26};
27use primitives::{
28 transaction::eth_transaction::eip155_signature, AccessList, Action,
29 SignedTransaction,
30};
31use rlp::Encodable;
32use serde::{Deserialize, Serialize};
33
34#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
36#[serde(rename_all = "camelCase")]
37pub struct Transaction {
38 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
40 pub transaction_type: Option<U64>,
41 pub hash: H256,
43 pub nonce: U256,
45 pub block_hash: Option<H256>,
47 pub block_number: Option<U256>,
49 pub transaction_index: Option<U256>,
51 pub from: H160,
53 pub to: Option<H160>,
55 pub value: U256,
57 pub gas_price: Option<U256>,
59 #[serde(skip_serializing_if = "Option::is_none")]
61 pub max_fee_per_gas: Option<U256>,
62 pub gas: U256,
64 pub input: Bytes,
66 pub creates: Option<H160>,
68 pub raw: Option<Bytes>,
70 pub public_key: Option<H512>,
72 pub chain_id: Option<U64>,
74 #[serde(skip_serializing_if = "Option::is_none")]
77 pub standard_v: Option<U256>,
78 pub v: U64,
80 pub r: U256,
82 pub s: U256,
84 pub status: Option<U64>,
86 #[serde(skip_serializing_if = "Option::is_none")]
88 pub access_list: Option<AccessList>,
89 #[serde(skip_serializing_if = "Option::is_none")]
91 pub max_priority_fee_per_gas: Option<U256>,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub y_parity: Option<U64>,
94 #[serde(skip_serializing_if = "Option::is_none")]
98 pub authorization_list: Option<Vec<SignedAuthorization>>,
99}
100
101impl Transaction {
102 pub fn from_signed(
104 t: &SignedTransaction,
105 block_info: (Option<H256>, Option<U256>, Option<U256>),
106 exec_info: (Option<U64>, Option<H160>),
107 ) -> Transaction {
108 let signature = t.signature();
109
110 let (v, y_parity) = if t.is_2718() {
112 (U64::from(signature.v()), Some(U64::from(signature.v())))
113 } else {
114 (
115 eip155_signature::add_chain_replay_protection(
116 signature.v(),
117 t.chain_id().map(|x| x as u64),
118 )
119 .into(),
120 None,
121 )
122 };
123
124 let mut r: U256 = signature.r().into();
128 let mut s: U256 = signature.s().into();
129 if r == U256::zero() || s == U256::zero() {
130 let chain_id = t
131 .chain_id()
132 .map(|x| U256::from(x as u64))
133 .expect("should have chain_id");
134 r = chain_id;
135 s = chain_id;
136 }
137
138 Transaction {
139 hash: t.hash(),
140 nonce: *t.nonce(),
141 block_hash: block_info.0,
142 block_number: block_info.1,
143 transaction_index: block_info.2,
144 from: t.sender().address,
145 to: match t.action() {
146 Action::Create => None,
147 Action::Call(ref address) => Some(*address),
148 },
149 value: *t.value(),
150 gas_price: Some(*t.gas_price()),
151 gas: *t.gas(),
152 input: Bytes::new(t.data().clone()),
153 creates: exec_info.1,
154 raw: Some(Bytes::new(t.transaction.transaction.rlp_bytes())),
155 public_key: t.public().map(Into::into),
156 chain_id: t.chain_id().map(|x| U64::from(x as u64)),
157 standard_v: Some(signature.v().into()),
158 v,
159 r,
160 s,
161 status: exec_info.0,
162 access_list: t.access_list().cloned(),
163 max_fee_per_gas: t.after_1559().then_some(*t.gas_price()),
164 max_priority_fee_per_gas: t
165 .after_1559()
166 .then_some(*t.max_priority_gas_price()),
167 y_parity,
168 transaction_type: Some(U64::from(t.type_id())),
169 authorization_list: t.authorization_list().map(|list| {
170 list.iter()
171 .map(|item| SignedAuthorization::from(item.clone()))
172 .collect()
173 }),
174 }
175 }
176
177 pub fn deployed_contract_address(t: &SignedTransaction) -> Option<H160> {
178 match t.action() {
179 Action::Create => {
180 let (new_contract_address, _) = cal_contract_address(
181 CreateContractAddressType::FromSenderNonce,
182 0,
183 &t.sender().address,
184 t.nonce(),
185 t.data(),
186 );
187 Some(new_contract_address)
188 }
189 Action::Call(_) => None,
190 }
191 }
192}
193
194#[derive(Debug, Clone, PartialEq, Serialize)]
195#[serde(rename_all = "camelCase")]
196pub enum WrapTransaction {
197 NativeTransaction(CfxTransaction),
198 EthTransaction(Transaction),
199}