use std::{fmt::Display, str::FromStr};
use anyhow::Result;
use cairo_starknet_2_0_1::{
casm_contract_class::CasmContractClass as Cairo201CasmClass,
contract_class::ContractClass as Cairo201Class,
};
use clap::{builder::PossibleValue, ValueEnum};
use starknet::core::types::{
contract::{CompiledClass, SierraClass},
FieldElement,
};
#[derive(Debug)]
pub struct BuiltInCompiler {
version: CompilerVersion,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompilerVersion {
V2_0_1,
}
impl BuiltInCompiler {
pub fn version(&self) -> CompilerVersion {
self.version
}
pub fn compile(&self, class: &SierraClass) -> Result<FieldElement> {
let mut class = class.clone();
class.abi.clear();
let sierra_class_json = serde_json::to_string(&class)?;
let casm_class_json = match self.version {
CompilerVersion::V2_0_1 => {
let contract_class: Cairo201Class = serde_json::from_str(&sierra_class_json)?;
let casm_contract = Cairo201CasmClass::from_contract_class(contract_class, false)?;
serde_json::to_string(&casm_contract)?
}
};
let casm_class = serde_json::from_str::<CompiledClass>(&casm_class_json)?;
let casm_class_hash = casm_class.class_hash()?;
Ok(casm_class_hash)
}
}
impl Default for CompilerVersion {
fn default() -> Self {
Self::V2_0_1
}
}
impl ValueEnum for CompilerVersion {
fn value_variants<'a>() -> &'a [Self] {
&[Self::V2_0_1]
}
fn to_possible_value(&self) -> Option<PossibleValue> {
match self {
Self::V2_0_1 => Some(PossibleValue::new("2.0.1").alias("v2.0.1")),
}
}
}
impl FromStr for CompilerVersion {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self> {
match s {
"2.0.1" | "v2.0.1" => Ok(Self::V2_0_1),
_ => Err(anyhow::anyhow!("unknown version: {}", s)),
}
}
}
impl Display for CompilerVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CompilerVersion::V2_0_1 => write!(f, "2.0.1"),
}
}
}
impl From<CompilerVersion> for BuiltInCompiler {
fn from(value: CompilerVersion) -> Self {
Self { version: value }
}
}