diff --git a/src/services/api/contract_class_errors.rs b/src/services/api/contract_class_errors.rs index fff199688..c7a7c101f 100644 --- a/src/services/api/contract_class_errors.rs +++ b/src/services/api/contract_class_errors.rs @@ -13,4 +13,8 @@ pub enum ContractClassError { NotACasmContractClass, #[error("Not a deprecated contract class")] NotADeprecatedContractClass, + #[error("Parse error")] + ParseError, + #[error("Program error: {0}")] + ProgramError(String), } diff --git a/src/services/api/contract_classes/deprecated_contract_class.rs b/src/services/api/contract_classes/deprecated_contract_class.rs index 9f475c42e..24bf8d8af 100644 --- a/src/services/api/contract_classes/deprecated_contract_class.rs +++ b/src/services/api/contract_classes/deprecated_contract_class.rs @@ -128,6 +128,36 @@ impl ContractClass { }) } + /// Parses a [`ContractClass`] from a compiled Cairo 0 program's JSON and a class hash. + /// + /// This constructor avoids the need to recompute the class hash from the program JSON, + /// but it does not verify that the given class hash is correct. + /// + /// This could return a wrong [`ContractClass`] if the given class hash is wrong. + /// + /// # Parameters + /// - `program_json`: The JSON of the compiled Cairo 0 program. + /// - `hinted_class_hash`: The class hash of the program. + /// + /// # Returns + /// A [`ContractClass`] parsed from the given JSON and class hash. + pub fn from_program_json_and_class_hash( + program_json: &str, + hinted_class_hash: Felt252, + ) -> Result { + let contract_class: starknet_api::deprecated_contract_class::ContractClass = + serde_json::from_str(program_json).map_err(|_| ContractClassError::ParseError)?; + let program = to_cairo_runner_program(contract_class.program) + .map_err(|e| ContractClassError::ProgramError(e.to_string()))?; + let entry_points_by_type = convert_entry_points(contract_class.entry_points_by_type); + Ok(ContractClass { + hinted_class_hash, + program, + entry_points_by_type, + abi: contract_class.abi, + }) + } + /// Parses a [`ContractClass`] from a compiled Cairo 0 program's JSON /// at the given file path. pub fn from_path(path: F) -> Result @@ -393,4 +423,22 @@ mod tests { res.expect("should be able to read file"); } + + #[test] + fn test_from_program_json_and_class_hash_should_equal_from_path() { + let program_json = include_str!("../../../../starknet_programs/fibonacci.json"); + let contract_class_from_path = ContractClass::from_path("starknet_programs/fibonacci.json") + .expect("should be able to read file"); + + let contract_class_from_program_json_and_class_hash = + ContractClass::from_program_json_and_class_hash( + program_json, + contract_class_from_path.hinted_class_hash.clone(), + ) + .expect("should be able to read file"); + assert_eq!( + contract_class_from_path, + contract_class_from_program_json_and_class_hash + ); + } }