11use std:: str:: FromStr ;
22
3- use cairo_lang_starknet_classes:: abi;
43use cairo_lang_starknet_classes:: casm_contract_class:: StarknetSierraCompilationError ;
54use cairo_lang_starknet_classes:: contract_class:: {
65 version_id_from_serialized_sierra_program, ContractEntryPoint , ContractEntryPoints ,
76} ;
7+ use cairo_lang_utils:: bigint:: BigUintAsHex ;
88use serde_json_pythonic:: to_string_pythonic;
99use starknet:: macros:: short_string;
1010use starknet_api:: contract_class:: SierraVersion ;
@@ -18,8 +18,6 @@ pub type ClassHash = Felt;
1818/// The hash of a compiled contract class.
1919pub type CompiledClassHash = Felt ;
2020
21- /// The canonical contract class (Sierra) type.
22- pub type SierraContractClass = cairo_lang_starknet_classes:: contract_class:: ContractClass ;
2321/// The canonical legacy class (Cairo 0) type.
2422pub type LegacyContractClass = starknet_api:: deprecated_contract_class:: ContractClass ;
2523
@@ -29,6 +27,97 @@ pub type CasmContractClass = cairo_lang_starknet_classes::casm_contract_class::C
2927/// ABI for Sierra-based classes.
3028pub type ContractAbi = cairo_lang_starknet_classes:: abi:: Contract ;
3129
30+ #[ derive( Debug , Clone , Eq , PartialEq ) ]
31+ #[ cfg_attr( feature = "serde" , derive( :: serde:: Serialize , :: serde:: Deserialize ) , serde( untagged) ) ]
32+ pub enum MaybeInvalidSierraContractAbi {
33+ Valid ( ContractAbi ) ,
34+ Invalid ( String ) ,
35+ }
36+
37+ impl std:: fmt:: Display for MaybeInvalidSierraContractAbi {
38+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
39+ match self {
40+ MaybeInvalidSierraContractAbi :: Valid ( abi) => {
41+ let s = to_string_pythonic ( abi) . expect ( "failed to serialize abi" ) ;
42+ write ! ( f, "{}" , s)
43+ }
44+ MaybeInvalidSierraContractAbi :: Invalid ( abi) => write ! ( f, "{}" , abi) ,
45+ }
46+ }
47+ }
48+
49+ impl From < String > for MaybeInvalidSierraContractAbi {
50+ fn from ( value : String ) -> Self {
51+ match serde_json:: from_str :: < ContractAbi > ( & value) {
52+ Ok ( abi) => MaybeInvalidSierraContractAbi :: Valid ( abi) ,
53+ Err ( ..) => MaybeInvalidSierraContractAbi :: Invalid ( value) ,
54+ }
55+ }
56+ }
57+
58+ impl From < & str > for MaybeInvalidSierraContractAbi {
59+ fn from ( value : & str ) -> Self {
60+ match serde_json:: from_str :: < ContractAbi > ( value) {
61+ Ok ( abi) => MaybeInvalidSierraContractAbi :: Valid ( abi) ,
62+ Err ( ..) => MaybeInvalidSierraContractAbi :: Invalid ( value. to_string ( ) ) ,
63+ }
64+ }
65+ }
66+
67+ /// Represents a contract in the Starknet network.
68+ ///
69+ /// The canonical contract class (Sierra) type.
70+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
71+ #[ cfg_attr( feature = "serde" , derive( :: serde:: Serialize , :: serde:: Deserialize ) ) ]
72+ pub struct SierraContractClass {
73+ pub sierra_program : Vec < BigUintAsHex > ,
74+ pub sierra_program_debug_info : Option < cairo_lang_sierra:: debug_info:: DebugInfo > ,
75+ pub contract_class_version : String ,
76+ pub entry_points_by_type : ContractEntryPoints ,
77+ pub abi : Option < MaybeInvalidSierraContractAbi > ,
78+ }
79+
80+ impl SierraContractClass {
81+ /// Computes the hash of the Sierra contract class.
82+ pub fn hash ( & self ) -> ClassHash {
83+ let Self { sierra_program, abi, entry_points_by_type, .. } = self ;
84+
85+ let program: Vec < Felt > = sierra_program. iter ( ) . map ( |f| f. value . clone ( ) . into ( ) ) . collect ( ) ;
86+ let abi: String = abi. as_ref ( ) . map ( |abi| abi. to_string ( ) ) . unwrap_or_default ( ) ;
87+
88+ compute_sierra_class_hash ( & abi, entry_points_by_type, & program)
89+ }
90+ }
91+
92+ impl From < SierraContractClass > for cairo_lang_starknet_classes:: contract_class:: ContractClass {
93+ fn from ( value : SierraContractClass ) -> Self {
94+ let abi = value. abi . and_then ( |abi| match abi {
95+ MaybeInvalidSierraContractAbi :: Invalid ( ..) => None ,
96+ MaybeInvalidSierraContractAbi :: Valid ( abi) => Some ( abi) ,
97+ } ) ;
98+
99+ cairo_lang_starknet_classes:: contract_class:: ContractClass {
100+ abi,
101+ sierra_program : value. sierra_program ,
102+ entry_points_by_type : value. entry_points_by_type ,
103+ contract_class_version : value. contract_class_version ,
104+ sierra_program_debug_info : value. sierra_program_debug_info ,
105+ }
106+ }
107+ }
108+
109+ impl From < cairo_lang_starknet_classes:: contract_class:: ContractClass > for SierraContractClass {
110+ fn from ( value : cairo_lang_starknet_classes:: contract_class:: ContractClass ) -> Self {
111+ SierraContractClass {
112+ abi : value. abi . map ( MaybeInvalidSierraContractAbi :: Valid ) ,
113+ sierra_program : value. sierra_program ,
114+ entry_points_by_type : value. entry_points_by_type ,
115+ contract_class_version : value. contract_class_version ,
116+ sierra_program_debug_info : value. sierra_program_debug_info ,
117+ }
118+ }
119+ }
120+
32121#[ derive( Debug , thiserror:: Error ) ]
33122pub enum ContractClassCompilationError {
34123 #[ error( transparent) ]
@@ -51,23 +140,7 @@ impl ContractClass {
51140 /// Computes the hash of the class.
52141 pub fn class_hash ( & self ) -> Result < ClassHash , ComputeClassHashError > {
53142 match self {
54- Self :: Class ( class) => {
55- // Technically we don't have to use the Pythonic JSON style here. Doing this just to
56- // align with the official `cairo-lang` CLI.
57- //
58- // TODO: add an `AbiFormatter` trait and let users choose which one to use.
59- let abi = class. abi . as_ref ( ) ;
60- let abi_str = to_string_pythonic ( abi. unwrap_or ( & abi:: Contract :: default ( ) ) ) . unwrap ( ) ;
61-
62- let sierra_program = & class
63- . sierra_program
64- . iter ( )
65- . map ( |f| f. value . clone ( ) . into ( ) )
66- . collect :: < Vec < Felt > > ( ) ;
67-
68- Ok ( compute_sierra_class_hash ( & abi_str, & class. entry_points_by_type , sierra_program) )
69- }
70-
143+ Self :: Class ( class) => Ok ( class. hash ( ) ) ,
71144 Self :: Legacy ( class) => compute_legacy_class_hash ( class) ,
72145 }
73146 }
@@ -77,7 +150,7 @@ impl ContractClass {
77150 match self {
78151 Self :: Legacy ( class) => Ok ( CompiledClass :: Legacy ( class) ) ,
79152 Self :: Class ( class) => {
80- let casm = CasmContractClass :: from_contract_class ( class, true , usize:: MAX ) ?;
153+ let casm = CasmContractClass :: from_contract_class ( class. into ( ) , true , usize:: MAX ) ?;
81154 let casm = CompiledClass :: Class ( casm) ;
82155 Ok ( casm)
83156 }
0 commit comments