1use serde::{Deserialize, Serialize, Serializer};
2use serde_with::serde_as;
3use starknet_rust_core::{
4 serde::unsigned_field_element::{UfeHex, UfeHexOption},
5 types::Felt,
6};
7use std::sync::Arc;
8
9use super::{
10 contract::{CompressedLegacyContractClass, CompressedSierraClass},
11 serde_impls::u64_hex,
12 transaction::{DataAvailabilityMode, ResourceBoundsMapping},
13 L1Address,
14};
15
16const QUERY_VERSION_ONE: Felt = Felt::from_raw([
18 576460752142433776,
19 18446744073709551584,
20 17407,
21 18446744073700081633,
22]);
23
24const QUERY_VERSION_TWO: Felt = Felt::from_raw([
26 576460752142433232,
27 18446744073709551584,
28 17407,
29 18446744073700081601,
30]);
31
32const QUERY_VERSION_THREE: Felt = Felt::from_raw([
34 576460752142432688,
35 18446744073709551584,
36 17407,
37 18446744073700081569,
38]);
39
40#[serde_as]
41#[derive(Debug, Deserialize)]
42#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
43pub struct AddTransactionResult {
44 pub code: AddTransactionResultCode,
45 #[serde_as(as = "UfeHex")]
46 pub transaction_hash: Felt,
47 #[serde(default)]
48 #[serde_as(as = "UfeHexOption")]
49 pub address: Option<Felt>,
50 #[serde(default)]
51 #[serde_as(as = "UfeHexOption")]
52 pub class_hash: Option<Felt>,
53}
54
55#[derive(Debug, PartialEq, Eq, Deserialize)]
56#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
57pub enum AddTransactionResultCode {
58 #[serde(rename = "TRANSACTION_RECEIVED")]
59 TransactionReceived,
60}
61
62#[derive(Debug, Serialize)]
63#[serde(tag = "type", rename_all = "SCREAMING_SNAKE_CASE")]
64pub enum TransactionRequest {
65 Declare(DeclareTransaction),
66 InvokeFunction(InvokeFunctionTransaction),
67 DeployAccount(DeployAccountTransaction),
68}
69
70#[derive(Debug, Serialize)]
71#[serde(untagged)]
72pub enum DeclareTransaction {
73 V1(DeclareV1Transaction),
74 V2(DeclareV2Transaction),
75 V3(DeclareV3Transaction),
76}
77
78#[derive(Debug)]
79pub struct DeclareV1Transaction {
80 pub contract_class: Arc<CompressedLegacyContractClass>,
81 pub sender_address: Felt,
83 pub max_fee: Felt,
85 pub signature: Vec<Felt>,
87 pub nonce: Felt,
89 pub is_query: bool,
90}
91
92#[derive(Debug)]
93pub struct DeclareV2Transaction {
94 pub contract_class: Arc<CompressedSierraClass>,
95 pub compiled_class_hash: Felt,
100 pub sender_address: Felt,
102 pub max_fee: Felt,
104 pub signature: Vec<Felt>,
106 pub nonce: Felt,
108 pub is_query: bool,
109}
110
111#[derive(Debug)]
112pub struct DeclareV3Transaction {
113 pub contract_class: Arc<CompressedSierraClass>,
114 pub compiled_class_hash: Felt,
119 pub sender_address: Felt,
121 pub signature: Vec<Felt>,
123 pub nonce: Felt,
125 pub nonce_data_availability_mode: DataAvailabilityMode,
126 pub fee_data_availability_mode: DataAvailabilityMode,
127 pub resource_bounds: ResourceBoundsMapping,
128 pub tip: u64,
129 pub paymaster_data: Vec<Felt>,
130 pub account_deployment_data: Vec<Felt>,
131 pub is_query: bool,
132}
133
134#[derive(Debug, Serialize)]
135#[serde(untagged)]
136pub enum InvokeFunctionTransaction {
137 V1(InvokeFunctionV1Transaction),
138 V3(InvokeFunctionV3Transaction),
139}
140
141#[derive(Debug)]
142pub struct InvokeFunctionV1Transaction {
143 pub sender_address: Felt,
144 pub calldata: Vec<Felt>,
145 pub signature: Vec<Felt>,
146 pub max_fee: Felt,
147 pub nonce: Felt,
148 pub is_query: bool,
149}
150
151#[derive(Debug)]
152pub struct InvokeFunctionV3Transaction {
153 pub sender_address: Felt,
154 pub calldata: Vec<Felt>,
155 pub signature: Vec<Felt>,
156 pub nonce: Felt,
157 pub nonce_data_availability_mode: DataAvailabilityMode,
158 pub fee_data_availability_mode: DataAvailabilityMode,
159 pub resource_bounds: ResourceBoundsMapping,
160 pub tip: u64,
161 pub paymaster_data: Vec<Felt>,
162 pub account_deployment_data: Vec<Felt>,
163 pub is_query: bool,
164}
165
166#[derive(Debug, Serialize)]
167#[serde(untagged)]
168pub enum DeployAccountTransaction {
169 V1(DeployAccountV1Transaction),
170 V3(DeployAccountV3Transaction),
171}
172
173#[derive(Debug)]
174pub struct DeployAccountV1Transaction {
175 pub class_hash: Felt,
176 pub contract_address_salt: Felt,
177 pub constructor_calldata: Vec<Felt>,
178 pub max_fee: Felt,
180 pub signature: Vec<Felt>,
182 pub nonce: Felt,
184 pub is_query: bool,
185}
186
187#[derive(Debug)]
188pub struct DeployAccountV3Transaction {
189 pub class_hash: Felt,
190 pub contract_address_salt: Felt,
191 pub constructor_calldata: Vec<Felt>,
192 pub signature: Vec<Felt>,
194 pub nonce: Felt,
196 pub nonce_data_availability_mode: DataAvailabilityMode,
197 pub fee_data_availability_mode: DataAvailabilityMode,
198 pub resource_bounds: ResourceBoundsMapping,
199 pub tip: u64,
200 pub paymaster_data: Vec<Felt>,
201 pub is_query: bool,
202}
203
204impl Serialize for DeclareV1Transaction {
205 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
206 where
207 S: Serializer,
208 {
209 #[serde_as]
210 #[derive(Serialize)]
211 struct Versioned<'a> {
212 #[serde_as(as = "UfeHex")]
213 version: Felt,
214 contract_class: &'a CompressedLegacyContractClass,
215 #[serde_as(as = "UfeHex")]
216 sender_address: &'a Felt,
217 #[serde_as(as = "UfeHex")]
218 max_fee: &'a Felt,
219 signature: &'a Vec<Felt>,
220 #[serde_as(as = "UfeHex")]
221 nonce: &'a Felt,
222 }
223
224 let versioned = Versioned {
225 version: if self.is_query {
226 QUERY_VERSION_ONE
227 } else {
228 Felt::ONE
229 },
230 contract_class: &self.contract_class,
231 sender_address: &self.sender_address,
232 max_fee: &self.max_fee,
233 signature: &self.signature,
234 nonce: &self.nonce,
235 };
236
237 Versioned::serialize(&versioned, serializer)
238 }
239}
240
241impl Serialize for DeclareV2Transaction {
242 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
243 where
244 S: Serializer,
245 {
246 #[serde_as]
247 #[derive(Serialize)]
248 struct Versioned<'a> {
249 #[serde_as(as = "UfeHex")]
250 version: Felt,
251 contract_class: &'a CompressedSierraClass,
252 #[serde_as(as = "UfeHex")]
253 compiled_class_hash: &'a Felt,
254 #[serde_as(as = "UfeHex")]
255 sender_address: &'a Felt,
256 #[serde_as(as = "UfeHex")]
257 max_fee: &'a Felt,
258 signature: &'a Vec<Felt>,
259 #[serde_as(as = "UfeHex")]
260 nonce: &'a Felt,
261 }
262
263 let versioned = Versioned {
264 version: if self.is_query {
265 QUERY_VERSION_TWO
266 } else {
267 Felt::TWO
268 },
269 contract_class: &self.contract_class,
270 compiled_class_hash: &self.compiled_class_hash,
271 sender_address: &self.sender_address,
272 max_fee: &self.max_fee,
273 signature: &self.signature,
274 nonce: &self.nonce,
275 };
276
277 Versioned::serialize(&versioned, serializer)
278 }
279}
280
281impl Serialize for DeclareV3Transaction {
282 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
283 where
284 S: Serializer,
285 {
286 #[serde_as]
287 #[derive(Serialize)]
288 struct Versioned<'a> {
289 #[serde_as(as = "UfeHex")]
290 version: Felt,
291 contract_class: &'a CompressedSierraClass,
292 #[serde_as(as = "UfeHex")]
293 compiled_class_hash: &'a Felt,
294 #[serde_as(as = "UfeHex")]
295 sender_address: &'a Felt,
296 #[serde_as(as = "Vec<UfeHex>")]
297 signature: &'a Vec<Felt>,
298 #[serde_as(as = "UfeHex")]
299 nonce: &'a Felt,
300 nonce_data_availability_mode: &'a DataAvailabilityMode,
301 fee_data_availability_mode: &'a DataAvailabilityMode,
302 resource_bounds: &'a ResourceBoundsMapping,
303 #[serde(with = "u64_hex")]
304 tip: &'a u64,
305 #[serde_as(as = "Vec<UfeHex>")]
306 paymaster_data: &'a Vec<Felt>,
307 #[serde_as(as = "Vec<UfeHex>")]
308 account_deployment_data: &'a Vec<Felt>,
309 }
310
311 let versioned = Versioned {
312 version: if self.is_query {
313 QUERY_VERSION_THREE
314 } else {
315 Felt::THREE
316 },
317 contract_class: &self.contract_class,
318 compiled_class_hash: &self.compiled_class_hash,
319 sender_address: &self.sender_address,
320 signature: &self.signature,
321 nonce: &self.nonce,
322 nonce_data_availability_mode: &self.nonce_data_availability_mode,
323 fee_data_availability_mode: &self.fee_data_availability_mode,
324 resource_bounds: &self.resource_bounds,
325 tip: &self.tip,
326 paymaster_data: &self.paymaster_data,
327 account_deployment_data: &self.account_deployment_data,
328 };
329
330 Versioned::serialize(&versioned, serializer)
331 }
332}
333
334impl Serialize for InvokeFunctionV1Transaction {
335 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
336 where
337 S: Serializer,
338 {
339 #[serde_as]
340 #[derive(Serialize)]
341 struct Versioned<'a> {
342 #[serde_as(as = "UfeHex")]
343 version: Felt,
344 #[serde_as(as = "UfeHex")]
345 sender_address: &'a Felt,
346 calldata: &'a Vec<Felt>,
347 signature: &'a Vec<Felt>,
348 #[serde_as(as = "UfeHex")]
349 max_fee: &'a Felt,
350 #[serde_as(as = "UfeHex")]
351 nonce: &'a Felt,
352 }
353
354 let versioned = Versioned {
355 version: if self.is_query {
356 QUERY_VERSION_ONE
357 } else {
358 Felt::ONE
359 },
360 sender_address: &self.sender_address,
361 calldata: &self.calldata,
362 signature: &self.signature,
363 max_fee: &self.max_fee,
364 nonce: &self.nonce,
365 };
366
367 Versioned::serialize(&versioned, serializer)
368 }
369}
370
371impl Serialize for InvokeFunctionV3Transaction {
372 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
373 where
374 S: Serializer,
375 {
376 #[serde_as]
377 #[derive(Serialize)]
378 struct Versioned<'a> {
379 #[serde_as(as = "UfeHex")]
380 version: Felt,
381 #[serde_as(as = "UfeHex")]
382 sender_address: &'a Felt,
383 calldata: &'a Vec<Felt>,
384 #[serde_as(as = "Vec<UfeHex>")]
385 signature: &'a Vec<Felt>,
386 #[serde_as(as = "UfeHex")]
387 nonce: &'a Felt,
388 nonce_data_availability_mode: &'a DataAvailabilityMode,
389 fee_data_availability_mode: &'a DataAvailabilityMode,
390 resource_bounds: &'a ResourceBoundsMapping,
391 #[serde(with = "u64_hex")]
392 tip: &'a u64,
393 #[serde_as(as = "Vec<UfeHex>")]
394 paymaster_data: &'a Vec<Felt>,
395 #[serde_as(as = "Vec<UfeHex>")]
396 account_deployment_data: &'a Vec<Felt>,
397 }
398
399 let versioned = Versioned {
400 version: if self.is_query {
401 QUERY_VERSION_THREE
402 } else {
403 Felt::THREE
404 },
405 sender_address: &self.sender_address,
406 calldata: &self.calldata,
407 signature: &self.signature,
408 nonce: &self.nonce,
409 nonce_data_availability_mode: &self.nonce_data_availability_mode,
410 fee_data_availability_mode: &self.fee_data_availability_mode,
411 resource_bounds: &self.resource_bounds,
412 tip: &self.tip,
413 paymaster_data: &self.paymaster_data,
414 account_deployment_data: &self.account_deployment_data,
415 };
416
417 Versioned::serialize(&versioned, serializer)
418 }
419}
420
421impl Serialize for DeployAccountV1Transaction {
422 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
423 where
424 S: Serializer,
425 {
426 #[serde_as]
427 #[derive(Serialize)]
428 struct Versioned<'a> {
429 #[serde_as(as = "UfeHex")]
430 version: Felt,
431 #[serde_as(as = "UfeHex")]
432 class_hash: &'a Felt,
433 #[serde_as(as = "UfeHex")]
434 contract_address_salt: &'a Felt,
435 constructor_calldata: &'a Vec<Felt>,
436 #[serde_as(as = "UfeHex")]
437 max_fee: &'a Felt,
438 signature: &'a Vec<Felt>,
439 #[serde_as(as = "UfeHex")]
440 nonce: &'a Felt,
441 }
442
443 let versioned = Versioned {
444 version: if self.is_query {
445 QUERY_VERSION_ONE
446 } else {
447 Felt::ONE
448 },
449 class_hash: &self.class_hash,
450 contract_address_salt: &self.contract_address_salt,
451 constructor_calldata: &self.constructor_calldata,
452 max_fee: &self.max_fee,
453 signature: &self.signature,
454 nonce: &self.nonce,
455 };
456
457 Versioned::serialize(&versioned, serializer)
458 }
459}
460
461impl Serialize for DeployAccountV3Transaction {
462 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
463 where
464 S: Serializer,
465 {
466 #[serde_as]
467 #[derive(Serialize)]
468 struct Versioned<'a> {
469 #[serde_as(as = "UfeHex")]
470 version: Felt,
471 #[serde_as(as = "UfeHex")]
472 class_hash: &'a Felt,
473 #[serde_as(as = "UfeHex")]
474 contract_address_salt: &'a Felt,
475 #[serde_as(as = "Vec<UfeHex>")]
476 constructor_calldata: &'a Vec<Felt>,
477 #[serde_as(as = "Vec<UfeHex>")]
478 signature: &'a Vec<Felt>,
479 #[serde_as(as = "UfeHex")]
480 nonce: &'a Felt,
481 nonce_data_availability_mode: &'a DataAvailabilityMode,
482 fee_data_availability_mode: &'a DataAvailabilityMode,
483 resource_bounds: &'a ResourceBoundsMapping,
484 #[serde(with = "u64_hex")]
485 tip: &'a u64,
486 #[serde_as(as = "Vec<UfeHex>")]
487 paymaster_data: &'a Vec<Felt>,
488 }
489
490 let versioned = Versioned {
491 version: if self.is_query {
492 QUERY_VERSION_THREE
493 } else {
494 Felt::THREE
495 },
496 class_hash: &self.class_hash,
497 contract_address_salt: &self.contract_address_salt,
498 constructor_calldata: &self.constructor_calldata,
499 signature: &self.signature,
500 nonce: &self.nonce,
501 nonce_data_availability_mode: &self.nonce_data_availability_mode,
502 fee_data_availability_mode: &self.fee_data_availability_mode,
503 resource_bounds: &self.resource_bounds,
504 tip: &self.tip,
505 paymaster_data: &self.paymaster_data,
506 };
507
508 Versioned::serialize(&versioned, serializer)
509 }
510}
511
512fn l1_addr_as_dec<S>(value: &L1Address, serializer: S) -> Result<S::Ok, S::Error>
513where
514 S: Serializer,
515{
516 let mut buffer = [0u8; 32];
517 buffer[12..].copy_from_slice(&value.0);
518
519 let addr_in_felt = Felt::from_bytes_be(&buffer);
521
522 serializer.serialize_str(&addr_in_felt.to_string())
523}