1use alloc::{string::*, vec::*};
2
3use serde::{Deserialize, Serialize};
4use serde_with::serde_as;
5
6use crate::serde::unsigned_field_element::UfeHex;
7
8pub use starknet_types_core::felt::*;
9
10mod conversions;
11
12mod serde_impls;
13
14pub mod typed_data;
16pub use typed_data::TypedData;
17
18mod codegen;
20pub use codegen::{
21 BinaryNode, BlockHeader, BlockStatus, BlockTag, BlockWithReceipts, BlockWithTxHashes,
22 BlockWithTxs, BroadcastedDeclareTransaction, BroadcastedDeclareTransactionV3,
23 BroadcastedDeployAccountTransaction, BroadcastedDeployAccountTransactionV3,
24 BroadcastedInvokeTransaction, BroadcastedInvokeTransactionV3, CallType,
25 CompressedLegacyContractClass, ContractErrorData, ContractLeafData, ContractStorageDiffItem,
26 ContractStorageKeys, ContractsProof, DataAvailabilityMode, DeclareTransactionReceipt,
27 DeclareTransactionTrace, DeclareTransactionV0, DeclareTransactionV0Content,
28 DeclareTransactionV1, DeclareTransactionV1Content, DeclareTransactionV2,
29 DeclareTransactionV2Content, DeclareTransactionV3, DeclareTransactionV3Content,
30 DeclaredClassItem, DeployAccountTransactionReceipt, DeployAccountTransactionTrace,
31 DeployAccountTransactionV1, DeployAccountTransactionV1Content, DeployAccountTransactionV3,
32 DeployAccountTransactionV3Content, DeployTransaction, DeployTransactionContent,
33 DeployTransactionReceipt, DeployedContractItem, EdgeNode, EmittedEvent,
34 EmittedEventWithFinality, EntryPointType, EntryPointsByType, Event, EventFilter,
35 EventFilterWithPage, EventsChunk, ExecutionResources, FeeEstimate, FeePayment,
36 FlattenedSierraClass, FunctionCall, FunctionInvocation, FunctionStateMutability, GlobalRoots,
37 InnerCallExecutionResources, InnerContractExecutionError, InvokeTransactionReceipt,
38 InvokeTransactionTrace, InvokeTransactionV0, InvokeTransactionV0Content, InvokeTransactionV1,
39 InvokeTransactionV1Content, InvokeTransactionV3, InvokeTransactionV3Content,
40 L1DataAvailabilityMode, L1HandlerTransaction, L1HandlerTransactionContent,
41 L1HandlerTransactionReceipt, L1HandlerTransactionTrace, L2TransactionFinalityStatus,
42 L2TransactionStatus, LegacyContractEntryPoint, LegacyEntryPointsByType, LegacyEventAbiEntry,
43 LegacyEventAbiType, LegacyFunctionAbiEntry, LegacyFunctionAbiType, LegacyStructAbiEntry,
44 LegacyStructAbiType, LegacyStructMember, LegacyTypedParameter, MessageFeeEstimate, MsgFromL1,
45 MsgToL1, NewTransactionStatus, NoTraceAvailableErrorData, NonceUpdate, OrderedEvent,
46 OrderedMessage, PreConfirmedBlockWithReceipts, PreConfirmedBlockWithTxHashes,
47 PreConfirmedBlockWithTxs, PreConfirmedStateUpdate, PriceUnit, ReorgData, ReplacedClassItem,
48 ResourceBounds, ResourceBoundsMapping, ResourcePrice, ResultPageRequest, RevertedInvocation,
49 SequencerTransactionStatus, SierraEntryPoint, SimulatedTransaction, SimulationFlag,
50 SimulationFlagForEstimateFee, StarknetError, StateDiff, StateUpdate, StorageEntry,
51 StorageProof, SubscriptionId, SyncStatus, TransactionExecutionErrorData,
52 TransactionExecutionStatus, TransactionFinalityStatus, TransactionReceiptWithBlockInfo,
53 TransactionTraceWithHash, TransactionWithL2Status, TransactionWithReceipt,
54};
55
56pub mod u256;
58pub use u256::U256;
59
60pub mod eth_address;
62pub use eth_address::EthAddress;
63
64pub mod hash_256;
66pub use hash_256::Hash256;
67
68mod execution_result;
69pub use execution_result::ExecutionResult;
70
71mod message_status;
72pub use message_status::MessageStatus;
73
74mod receipt_block;
75pub use receipt_block::ReceiptBlock;
76
77mod msg;
78pub use msg::MsgToL2;
79
80mod call;
81pub use call::Call;
82
83mod byte_array;
84pub use byte_array::ByteArray;
85
86pub mod requests;
89
90pub mod contract;
92pub use contract::ContractArtifact;
93
94#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
99#[serde(untagged)]
100pub enum MaybePreConfirmedBlockWithTxHashes {
101 Block(BlockWithTxHashes),
103 PreConfirmedBlock(PreConfirmedBlockWithTxHashes),
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
112#[serde(untagged)]
113pub enum MaybePreConfirmedBlockWithTxs {
114 Block(BlockWithTxs),
116 PreConfirmedBlock(PreConfirmedBlockWithTxs),
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
125#[serde(untagged)]
126pub enum MaybePreConfirmedBlockWithReceipts {
127 Block(BlockWithReceipts),
129 PreConfirmedBlock(PreConfirmedBlockWithReceipts),
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
138#[serde(untagged)]
139pub enum MaybePreConfirmedStateUpdate {
140 Update(StateUpdate),
142 PreConfirmedUpdate(PreConfirmedStateUpdate),
144}
145
146#[serde_as]
148#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
149pub struct BlockHashAndNumber {
150 #[serde_as(as = "UfeHex")]
152 pub block_hash: Felt,
153 pub block_number: u64,
155}
156
157#[derive(Debug, Clone, PartialEq, Eq)]
159pub enum SyncStatusType {
160 Syncing(SyncStatus),
162 NotSyncing,
164}
165
166#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
170pub struct EventsPage {
171 pub events: Vec<EmittedEvent>,
173 #[serde(skip_serializing_if = "Option::is_none")]
177 pub continuation_token: Option<String>,
178}
179
180#[serde_as]
182#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
183pub struct InvokeTransactionResult {
184 #[serde_as(as = "UfeHex")]
186 pub transaction_hash: Felt,
187}
188
189#[serde_as]
191#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
192pub struct DeclareTransactionResult {
193 #[serde_as(as = "UfeHex")]
195 pub transaction_hash: Felt,
196 #[serde_as(as = "UfeHex")]
198 pub class_hash: Felt,
199}
200
201#[serde_as]
206#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
207pub struct DeployTransactionResult {
208 #[serde_as(as = "UfeHex")]
210 pub transaction_hash: Felt,
211 #[serde_as(as = "UfeHex")]
213 pub contract_address: Felt,
214}
215
216#[serde_as]
218#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
219pub struct DeployAccountTransactionResult {
220 #[serde_as(as = "UfeHex")]
222 pub transaction_hash: Felt,
223 #[serde_as(as = "UfeHex")]
225 pub contract_address: Felt,
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq)]
230pub enum BlockId {
231 Hash(Felt),
233 Number(u64),
235 Tag(BlockTag),
237}
238
239#[derive(Debug, Clone, Copy, PartialEq, Eq)]
241pub enum ConfirmedBlockId {
242 Hash(Felt),
244 Number(u64),
246 Latest,
248 L1Accepted,
251}
252
253#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
256#[serde(untagged)]
257pub enum ContractClass {
258 Sierra(FlattenedSierraClass),
260 Legacy(CompressedLegacyContractClass),
262}
263
264#[derive(Debug, Clone, PartialEq, Eq)]
266pub enum TransactionStatus {
267 Received,
269 Candidate,
271 PreConfirmed(ExecutionResult),
273 AcceptedOnL2(ExecutionResult),
275 AcceptedOnL1(ExecutionResult),
277}
278
279impl TransactionStatus {
280 pub const fn is_received(&self) -> bool {
282 matches!(self, Self::Received)
283 }
284
285 pub const fn is_candidate(&self) -> bool {
287 matches!(self, Self::Candidate)
288 }
289
290 pub const fn is_pre_confirmed(&self) -> bool {
292 matches!(self, Self::PreConfirmed(_))
293 }
294
295 pub const fn is_accepted_on_l2(&self) -> bool {
297 matches!(self, Self::AcceptedOnL2(_))
298 }
299
300 pub const fn is_accepted_on_l1(&self) -> bool {
302 matches!(self, Self::AcceptedOnL1(_))
303 }
304}
305
306#[allow(clippy::large_enum_variant)]
308#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
309#[serde(untagged)]
310pub enum TransactionOrHash {
311 Transaction(Transaction),
313 Hash(Felt),
315}
316
317#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
319#[serde(tag = "type")]
320pub enum Transaction {
321 #[serde(rename = "INVOKE")]
323 Invoke(InvokeTransaction),
324 #[serde(rename = "L1_HANDLER")]
326 L1Handler(L1HandlerTransaction),
327 #[serde(rename = "DECLARE")]
329 Declare(DeclareTransaction),
330 #[serde(rename = "DEPLOY")]
332 Deploy(DeployTransaction),
333 #[serde(rename = "DEPLOY_ACCOUNT")]
335 DeployAccount(DeployAccountTransaction),
336}
337
338#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
340#[serde(tag = "type")]
341pub enum TransactionContent {
342 #[serde(rename = "INVOKE")]
344 Invoke(InvokeTransactionContent),
345 #[serde(rename = "L1_HANDLER")]
347 L1Handler(L1HandlerTransactionContent),
348 #[serde(rename = "DECLARE")]
350 Declare(DeclareTransactionContent),
351 #[serde(rename = "DEPLOY")]
353 Deploy(DeployTransactionContent),
354 #[serde(rename = "DEPLOY_ACCOUNT")]
356 DeployAccount(DeployAccountTransactionContent),
357}
358
359#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
361#[serde(tag = "type")]
362pub enum BroadcastedTransaction {
363 #[serde(rename = "INVOKE")]
365 Invoke(BroadcastedInvokeTransaction),
366 #[serde(rename = "DECLARE")]
368 Declare(BroadcastedDeclareTransaction),
369 #[serde(rename = "DEPLOY_ACCOUNT")]
371 DeployAccount(BroadcastedDeployAccountTransaction),
372}
373
374#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
376#[serde(tag = "version")]
377pub enum InvokeTransaction {
378 #[serde(rename = "0x0")]
380 V0(InvokeTransactionV0),
381 #[serde(rename = "0x1")]
383 V1(InvokeTransactionV1),
384 #[serde(rename = "0x3")]
386 V3(InvokeTransactionV3),
387}
388
389#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
391#[serde(tag = "version")]
392pub enum InvokeTransactionContent {
393 #[serde(rename = "0x0")]
395 V0(InvokeTransactionV0Content),
396 #[serde(rename = "0x1")]
398 V1(InvokeTransactionV1Content),
399 #[serde(rename = "0x3")]
401 V3(InvokeTransactionV3Content),
402}
403
404#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
406#[serde(tag = "version")]
407pub enum DeclareTransaction {
408 #[serde(rename = "0x0")]
410 V0(DeclareTransactionV0),
411 #[serde(rename = "0x1")]
413 V1(DeclareTransactionV1),
414 #[serde(rename = "0x2")]
416 V2(DeclareTransactionV2),
417 #[serde(rename = "0x3")]
419 V3(DeclareTransactionV3),
420}
421
422#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
424#[serde(tag = "version")]
425pub enum DeclareTransactionContent {
426 #[serde(rename = "0x0")]
428 V0(DeclareTransactionV0Content),
429 #[serde(rename = "0x1")]
431 V1(DeclareTransactionV1Content),
432 #[serde(rename = "0x2")]
434 V2(DeclareTransactionV2Content),
435 #[serde(rename = "0x3")]
437 V3(DeclareTransactionV3Content),
438}
439
440#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
442#[serde(tag = "version")]
443pub enum DeployAccountTransaction {
444 #[serde(rename = "0x1")]
446 V1(DeployAccountTransactionV1),
447 #[serde(rename = "0x3")]
449 V3(DeployAccountTransactionV3),
450}
451
452#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
454#[serde(tag = "version")]
455pub enum DeployAccountTransactionContent {
456 #[serde(rename = "0x1")]
458 V1(DeployAccountTransactionV1Content),
459 #[serde(rename = "0x3")]
461 V3(DeployAccountTransactionV3Content),
462}
463
464#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
466#[serde(tag = "type")]
467pub enum TransactionReceipt {
468 #[serde(rename = "INVOKE")]
470 Invoke(InvokeTransactionReceipt),
471 #[serde(rename = "L1_HANDLER")]
473 L1Handler(L1HandlerTransactionReceipt),
474 #[serde(rename = "DECLARE")]
476 Declare(DeclareTransactionReceipt),
477 #[serde(rename = "DEPLOY")]
479 Deploy(DeployTransactionReceipt),
480 #[serde(rename = "DEPLOY_ACCOUNT")]
482 DeployAccount(DeployAccountTransactionReceipt),
483}
484
485#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
487#[serde(untagged)]
488pub enum LegacyContractAbiEntry {
489 Function(LegacyFunctionAbiEntry),
491 Event(LegacyEventAbiEntry),
493 Struct(LegacyStructAbiEntry),
495}
496
497#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
499#[serde(tag = "type")]
500pub enum TransactionTrace {
501 #[serde(rename = "INVOKE")]
503 Invoke(InvokeTransactionTrace),
504 #[serde(rename = "DEPLOY_ACCOUNT")]
506 DeployAccount(DeployAccountTransactionTrace),
507 #[serde(rename = "L1_HANDLER")]
509 L1Handler(L1HandlerTransactionTrace),
510 #[serde(rename = "DECLARE")]
512 Declare(DeclareTransactionTrace),
513}
514
515#[allow(clippy::large_enum_variant)]
517#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
518#[serde(untagged)]
519pub enum ExecuteInvocation {
520 Success(FunctionInvocation),
522 Reverted(RevertedInvocation),
524}
525
526#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
528#[serde(untagged)]
529pub enum MerkleNode {
530 BinaryNode(BinaryNode),
532 EdgeNode(EdgeNode),
534}
535
536#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
538#[serde(untagged)]
539pub enum ContractExecutionError {
540 Nested(InnerContractExecutionError),
542 Message(String),
544}
545
546mod errors {
547 use core::fmt::{Display, Formatter, Result};
548
549 #[derive(Debug, PartialEq, Eq)]
551 pub enum ParseMsgToL2Error {
552 EmptyCalldata,
554 FromAddressOutOfRange,
556 }
557
558 #[cfg(feature = "std")]
559 impl std::error::Error for ParseMsgToL2Error {}
560
561 impl Display for ParseMsgToL2Error {
562 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
563 match self {
564 Self::EmptyCalldata => {
565 write!(
566 f,
567 "calldata must contain at least 1 element for from_address"
568 )
569 }
570 Self::FromAddressOutOfRange => {
571 write!(f, "from_address is larger than 20 bytes")
572 }
573 }
574 }
575 }
576}
577pub use errors::ParseMsgToL2Error;
578
579impl MaybePreConfirmedBlockWithTxHashes {
580 pub fn transactions(&self) -> &[Felt] {
582 match self {
583 Self::Block(block) => &block.transactions,
584 Self::PreConfirmedBlock(block) => &block.transactions,
585 }
586 }
587
588 pub const fn l1_gas_price(&self) -> &ResourcePrice {
590 match self {
591 Self::Block(block) => &block.l1_gas_price,
592 Self::PreConfirmedBlock(block) => &block.l1_gas_price,
593 }
594 }
595
596 pub const fn l2_gas_price(&self) -> &ResourcePrice {
598 match self {
599 Self::Block(block) => &block.l2_gas_price,
600 Self::PreConfirmedBlock(block) => &block.l2_gas_price,
601 }
602 }
603
604 pub const fn l1_data_gas_price(&self) -> &ResourcePrice {
606 match self {
607 Self::Block(block) => &block.l1_data_gas_price,
608 Self::PreConfirmedBlock(block) => &block.l1_data_gas_price,
609 }
610 }
611}
612
613impl MaybePreConfirmedBlockWithTxs {
614 pub fn transactions(&self) -> &[Transaction] {
616 match self {
617 Self::Block(block) => &block.transactions,
618 Self::PreConfirmedBlock(block) => &block.transactions,
619 }
620 }
621
622 pub const fn l1_gas_price(&self) -> &ResourcePrice {
624 match self {
625 Self::Block(block) => &block.l1_gas_price,
626 Self::PreConfirmedBlock(block) => &block.l1_gas_price,
627 }
628 }
629
630 pub const fn l2_gas_price(&self) -> &ResourcePrice {
632 match self {
633 Self::Block(block) => &block.l2_gas_price,
634 Self::PreConfirmedBlock(block) => &block.l2_gas_price,
635 }
636 }
637
638 pub const fn l1_data_gas_price(&self) -> &ResourcePrice {
640 match self {
641 Self::Block(block) => &block.l1_data_gas_price,
642 Self::PreConfirmedBlock(block) => &block.l1_data_gas_price,
643 }
644 }
645
646 pub fn median_tip(&self) -> u64 {
653 let mut tips: Vec<u64> = self
654 .transactions()
655 .iter()
656 .filter_map(|tx| tx.tip())
657 .collect();
658
659 if tips.is_empty() {
660 0
662 } else {
663 tips.sort_unstable();
664 let len = tips.len();
665 if len.is_multiple_of(2) {
666 (tips[len / 2 - 1] + tips[len / 2]) / 2
668 } else {
669 tips[len / 2]
671 }
672 }
673 }
674}
675
676impl MaybePreConfirmedBlockWithReceipts {
677 pub fn transactions(&self) -> &[TransactionWithReceipt] {
679 match self {
680 Self::Block(block) => &block.transactions,
681 Self::PreConfirmedBlock(block) => &block.transactions,
682 }
683 }
684
685 pub const fn l1_gas_price(&self) -> &ResourcePrice {
687 match self {
688 Self::Block(block) => &block.l1_gas_price,
689 Self::PreConfirmedBlock(block) => &block.l1_gas_price,
690 }
691 }
692}
693
694impl TransactionStatus {
695 pub const fn finality_status(&self) -> SequencerTransactionStatus {
697 match self {
698 Self::Received => SequencerTransactionStatus::Received,
699 Self::Candidate => SequencerTransactionStatus::Candidate,
700 Self::PreConfirmed(_) => SequencerTransactionStatus::PreConfirmed,
701 Self::AcceptedOnL2(_) => SequencerTransactionStatus::AcceptedOnL2,
702 Self::AcceptedOnL1(_) => SequencerTransactionStatus::AcceptedOnL1,
703 }
704 }
705}
706
707impl Transaction {
708 pub const fn transaction_hash(&self) -> &Felt {
710 match self {
711 Self::Invoke(tx) => tx.transaction_hash(),
712 Self::L1Handler(tx) => &tx.transaction_hash,
713 Self::Declare(tx) => tx.transaction_hash(),
714 Self::Deploy(tx) => &tx.transaction_hash,
715 Self::DeployAccount(tx) => tx.transaction_hash(),
716 }
717 }
718
719 pub const fn tip(&self) -> Option<u64> {
723 match self {
724 Self::Invoke(InvokeTransaction::V3(tx)) => Some(tx.tip),
725 Self::Declare(DeclareTransaction::V3(tx)) => Some(tx.tip),
726 Self::DeployAccount(DeployAccountTransaction::V3(tx)) => Some(tx.tip),
727 Self::Invoke(InvokeTransaction::V0(_))
729 | Self::Invoke(InvokeTransaction::V1(_))
730 | Self::L1Handler(_)
731 | Self::Declare(DeclareTransaction::V0(_))
732 | Self::Declare(DeclareTransaction::V1(_))
733 | Self::Declare(DeclareTransaction::V2(_))
734 | Self::Deploy(_)
735 | Self::DeployAccount(DeployAccountTransaction::V1(_)) => None,
736 }
737 }
738}
739
740impl InvokeTransaction {
741 pub const fn transaction_hash(&self) -> &Felt {
743 match self {
744 Self::V0(tx) => &tx.transaction_hash,
745 Self::V1(tx) => &tx.transaction_hash,
746 Self::V3(tx) => &tx.transaction_hash,
747 }
748 }
749}
750
751impl DeclareTransaction {
752 pub const fn transaction_hash(&self) -> &Felt {
754 match self {
755 Self::V0(tx) => &tx.transaction_hash,
756 Self::V1(tx) => &tx.transaction_hash,
757 Self::V2(tx) => &tx.transaction_hash,
758 Self::V3(tx) => &tx.transaction_hash,
759 }
760 }
761}
762
763impl DeployAccountTransaction {
764 pub const fn transaction_hash(&self) -> &Felt {
766 match self {
767 Self::V1(tx) => &tx.transaction_hash,
768 Self::V3(tx) => &tx.transaction_hash,
769 }
770 }
771}
772
773impl TransactionReceipt {
774 pub const fn transaction_hash(&self) -> &Felt {
776 match self {
777 Self::Invoke(receipt) => &receipt.transaction_hash,
778 Self::L1Handler(receipt) => &receipt.transaction_hash,
779 Self::Declare(receipt) => &receipt.transaction_hash,
780 Self::Deploy(receipt) => &receipt.transaction_hash,
781 Self::DeployAccount(receipt) => &receipt.transaction_hash,
782 }
783 }
784
785 pub const fn finality_status(&self) -> &TransactionFinalityStatus {
787 match self {
788 Self::Invoke(receipt) => &receipt.finality_status,
789 Self::L1Handler(receipt) => &receipt.finality_status,
790 Self::Declare(receipt) => &receipt.finality_status,
791 Self::Deploy(receipt) => &receipt.finality_status,
792 Self::DeployAccount(receipt) => &receipt.finality_status,
793 }
794 }
795
796 pub const fn execution_result(&self) -> &ExecutionResult {
798 match self {
799 Self::Invoke(receipt) => &receipt.execution_result,
800 Self::L1Handler(receipt) => &receipt.execution_result,
801 Self::Declare(receipt) => &receipt.execution_result,
802 Self::Deploy(receipt) => &receipt.execution_result,
803 Self::DeployAccount(receipt) => &receipt.execution_result,
804 }
805 }
806
807 pub fn events(&self) -> &[Event] {
809 match self {
810 Self::Invoke(receipt) => &receipt.events,
811 Self::L1Handler(receipt) => &receipt.events,
812 Self::Declare(receipt) => &receipt.events,
813 Self::Deploy(receipt) => &receipt.events,
814 Self::DeployAccount(receipt) => &receipt.events,
815 }
816 }
817}
818
819impl L1HandlerTransaction {
820 pub fn parse_msg_to_l2(&self) -> Result<MsgToL2, ParseMsgToL2Error> {
823 self.calldata.split_first().map_or(
824 Err(ParseMsgToL2Error::EmptyCalldata),
825 |(from_address, payload)| {
826 Ok(MsgToL2 {
827 from_address: (*from_address)
828 .try_into()
829 .map_err(|_| ParseMsgToL2Error::FromAddressOutOfRange)?,
830 to_address: self.contract_address,
831 selector: self.entry_point_selector,
832 payload: payload.into(),
833 nonce: self.nonce,
834 })
835 },
836 )
837 }
838}
839
840impl AsRef<Self> for BlockId {
841 fn as_ref(&self) -> &Self {
842 self
843 }
844}
845
846impl AsRef<Self> for ConfirmedBlockId {
847 fn as_ref(&self) -> &Self {
848 self
849 }
850}
851
852impl AsRef<Self> for FunctionCall {
853 fn as_ref(&self) -> &Self {
854 self
855 }
856}
857
858impl AsRef<Self> for MsgFromL1 {
859 fn as_ref(&self) -> &Self {
860 self
861 }
862}
863
864impl AsRef<Self> for BroadcastedTransaction {
865 fn as_ref(&self) -> &Self {
866 self
867 }
868}
869
870impl AsRef<Self> for BroadcastedInvokeTransaction {
871 fn as_ref(&self) -> &Self {
872 self
873 }
874}
875
876impl AsRef<Self> for BroadcastedDeclareTransaction {
877 fn as_ref(&self) -> &Self {
878 self
879 }
880}
881
882impl AsRef<Self> for BroadcastedDeployAccountTransaction {
883 fn as_ref(&self) -> &Self {
884 self
885 }
886}
887
888impl TryFrom<&L1HandlerTransaction> for MsgToL2 {
889 type Error = ParseMsgToL2Error;
890
891 fn try_from(value: &L1HandlerTransaction) -> Result<Self, Self::Error> {
892 value.parse_msg_to_l2()
893 }
894}
895
896#[cfg(test)]
897mod tests {
898 use super::{requests::*, *};
899
900 #[test]
901 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
902 fn test_felt_to_string() {
903 let felt = Felt::from_dec_str("123456").unwrap();
904
905 assert_eq!(format!("{felt}"), "123456");
906 assert_eq!(format!("{felt:x}"), "1e240");
907 assert_eq!(format!("{felt:X}"), "1E240");
908 assert_eq!(format!("{felt:#x}"), "0x1e240");
909 assert_eq!(format!("{felt:#X}"), "0x1E240");
910 assert_eq!(format!("{felt:010x}"), "000001e240");
911 assert_eq!(format!("{felt:010X}"), "000001E240");
912 assert_eq!(format!("{felt:#010x}"), "0x000001e240");
913 assert_eq!(format!("{felt:#010X}"), "0x000001E240");
914 }
915
916 #[test]
917 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
918 fn test_parse_msg_to_l2() {
919 let l1_handler_tx = L1HandlerTransaction {
920 transaction_hash: Felt::from_hex(
921 "0x374286ae28f201e61ffbc5b022cc9701208640b405ea34ea9799f97d5d2d23c",
922 )
923 .unwrap(),
924 version: Felt::ZERO,
925 nonce: 775628,
926 contract_address: Felt::from_hex(
927 "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82",
928 )
929 .unwrap(),
930 entry_point_selector: Felt::from_hex(
931 "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5",
932 )
933 .unwrap(),
934 calldata: vec![
935 Felt::from_hex("0xc3511006c04ef1d78af4c8e0e74ec18a6e64ff9e").unwrap(),
936 Felt::from_hex("0x689ead7d814e51ed93644bc145f0754839b8dcb340027ce0c30953f38f55d7")
937 .unwrap(),
938 Felt::from_hex("0x2c68af0bb140000").unwrap(),
939 Felt::from_hex("0x0").unwrap(),
940 ],
941 };
942
943 let msg_to_l2 = l1_handler_tx.parse_msg_to_l2().unwrap();
944
945 let expected_hash =
946 Hash256::from_hex("c51a543ef9563ad2545342b390b67edfcddf9886aa36846cf70382362fc5fab3")
947 .unwrap();
948
949 assert_eq!(msg_to_l2.hash(), expected_hash);
950 }
951
952 #[test]
953 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
954 fn test_parse_msg_to_l2_empty_calldata_error() {
955 let l1_handler_tx = L1HandlerTransaction {
956 transaction_hash: Felt::from_hex(
957 "0x374286ae28f201e61ffbc5b022cc9701208640b405ea34ea9799f97d5d2d23c",
958 )
959 .unwrap(),
960 version: Felt::ZERO,
961 nonce: 775628,
962 contract_address: Felt::from_hex(
963 "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82",
964 )
965 .unwrap(),
966 entry_point_selector: Felt::from_hex(
967 "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5",
968 )
969 .unwrap(),
970 calldata: Vec::new(), };
972
973 let result = l1_handler_tx.parse_msg_to_l2();
974
975 assert_eq!(result.unwrap_err(), ParseMsgToL2Error::EmptyCalldata);
976 }
977
978 #[test]
979 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
980 fn test_parse_msg_to_l2_from_address_out_of_range_error() {
981 let l1_handler_tx = L1HandlerTransaction {
982 transaction_hash: Felt::from_hex(
983 "0x374286ae28f201e61ffbc5b022cc9701208640b405ea34ea9799f97d5d2d23c",
984 )
985 .unwrap(),
986 version: Felt::ZERO,
987 nonce: 775628,
988 contract_address: Felt::from_hex(
989 "0x73314940630fd6dcda0d772d4c972c4e0a9946bef9dabf4ef84eda8ef542b82",
990 )
991 .unwrap(),
992 entry_point_selector: Felt::from_hex(
993 "0x2d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5",
994 )
995 .unwrap(),
996 calldata: vec![
997 Felt::from_hex("0x10000000000000000000000000000000000000000").unwrap(),
1000 Felt::from_hex("0x689ead7d814e51ed93644bc145f0754839b8dcb340027ce0c30953f38f55d7")
1001 .unwrap(),
1002 Felt::from_hex("0x2c68af0bb140000").unwrap(),
1003 Felt::from_hex("0x0").unwrap(),
1004 ],
1005 };
1006
1007 let result = l1_handler_tx.parse_msg_to_l2();
1008
1009 assert_eq!(
1010 result.unwrap_err(),
1011 ParseMsgToL2Error::FromAddressOutOfRange
1012 );
1013 }
1014
1015 #[test]
1016 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1017 fn test_parse_get_block_transaction_count_request() {
1018 let as_object = r#"{"block_id":{"block_number":200}}"#;
1019 let as_array = r#"[{"block_number":200}]"#;
1020
1021 assert_eq!(
1022 GetBlockTransactionCountRequest {
1023 block_id: BlockId::Number(200)
1024 },
1025 serde_json::from_str(as_object).unwrap(),
1026 );
1027
1028 assert_eq!(
1029 GetBlockTransactionCountRequest {
1030 block_id: BlockId::Number(200)
1031 },
1032 serde_json::from_str(as_array).unwrap(),
1033 );
1034 }
1035
1036 #[test]
1037 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1038 fn test_parse_get_storage_proof_request() {
1039 let as_object = r#"{"block_id":{"block_number":200},"class_hashes":["0x123"]}"#;
1040 let as_array = r#"[{"block_number":200},["0x123"]]"#;
1041
1042 assert_eq!(
1043 GetStorageProofRequest {
1044 block_id: ConfirmedBlockId::Number(200),
1045 class_hashes: Some(vec![Felt::from_hex_unchecked("0x123")]),
1046 contract_addresses: None,
1047 contracts_storage_keys: None
1048 },
1049 serde_json::from_str(as_object).unwrap(),
1050 );
1051
1052 assert_eq!(
1053 GetStorageProofRequest {
1054 block_id: ConfirmedBlockId::Number(200),
1055 class_hashes: Some(vec![Felt::from_hex_unchecked("0x123")]),
1056 contract_addresses: None,
1057 contracts_storage_keys: None
1058 },
1059 serde_json::from_str(as_array).unwrap(),
1060 );
1061 }
1062}