Skip to content

Commit 9bcab97

Browse files
authored
Compile contract artifacts in test targets (#1585)
- **Refactor starknet-contract compiler** - **Emit starknet contracts in test targets**
1 parent 72b4984 commit 9bcab97

File tree

10 files changed

+900
-521
lines changed

10 files changed

+900
-521
lines changed

scarb/src/compiler/compilers/starknet_contract.rs

Lines changed: 0 additions & 499 deletions
This file was deleted.
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
use crate::compiler::compilers::starknet_contract::{ContractFileStemCalculator, ContractSelector};
2+
use crate::compiler::compilers::Props;
3+
use crate::compiler::helpers::write_json;
4+
use crate::core::{PackageName, Workspace};
5+
use crate::flock::Filesystem;
6+
use cairo_lang_compiler::db::RootDatabase;
7+
use cairo_lang_defs::ids::NamedLanguageElementId;
8+
use cairo_lang_starknet::contract::ContractDeclaration;
9+
use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass;
10+
use cairo_lang_starknet_classes::contract_class::ContractClass;
11+
use cairo_lang_utils::UpcastMut;
12+
use itertools::{izip, Itertools};
13+
use scarb_stable_hash::short_hash;
14+
use serde::Serialize;
15+
use smol_str::SmolStr;
16+
17+
#[derive(Debug, Serialize)]
18+
struct StarknetArtifacts {
19+
version: usize,
20+
contracts: Vec<ContractArtifacts>,
21+
}
22+
23+
impl Default for StarknetArtifacts {
24+
fn default() -> Self {
25+
Self {
26+
version: 1,
27+
contracts: Vec::new(),
28+
}
29+
}
30+
}
31+
32+
impl StarknetArtifacts {
33+
fn finish(&mut self) {
34+
assert!(
35+
self.contracts.iter().map(|it| &it.id).all_unique(),
36+
"Artifacts IDs must be unique."
37+
);
38+
39+
self.contracts.sort_unstable_by_key(|it| it.id.clone());
40+
}
41+
}
42+
43+
#[derive(Debug, Serialize)]
44+
struct ContractArtifacts {
45+
id: String,
46+
package_name: PackageName,
47+
contract_name: String,
48+
module_path: String,
49+
artifacts: ContractArtifact,
50+
}
51+
52+
impl ContractArtifacts {
53+
fn new(
54+
package_name: PackageName,
55+
contract_name: &str,
56+
contract_path: &str,
57+
module_path: &str,
58+
) -> Self {
59+
Self {
60+
id: short_hash((&package_name, &contract_path)),
61+
package_name,
62+
contract_name: contract_name.to_owned(),
63+
module_path: module_path.to_owned(),
64+
artifacts: ContractArtifact::default(),
65+
}
66+
}
67+
}
68+
69+
#[derive(Debug, Default, Serialize)]
70+
struct ContractArtifact {
71+
sierra: Option<String>,
72+
casm: Option<String>,
73+
}
74+
75+
pub struct ArtifactsWriter {
76+
sierra: bool,
77+
casm: bool,
78+
target_dir: Filesystem,
79+
target_name: SmolStr,
80+
extension_prefix: Option<String>,
81+
}
82+
83+
impl ArtifactsWriter {
84+
pub fn new(target_name: SmolStr, target_dir: Filesystem, props: Props) -> Self {
85+
Self {
86+
sierra: props.sierra,
87+
casm: props.casm,
88+
target_dir,
89+
target_name,
90+
extension_prefix: None,
91+
}
92+
}
93+
94+
pub fn with_extension_prefix(self, prefix: String) -> Self {
95+
Self {
96+
extension_prefix: Some(prefix),
97+
..self
98+
}
99+
}
100+
101+
pub fn write(
102+
self,
103+
contract_paths: Vec<String>,
104+
contracts: &Vec<ContractDeclaration>,
105+
classes: &[ContractClass],
106+
casm_classes: &[Option<CasmContractClass>],
107+
db: &mut RootDatabase,
108+
ws: &Workspace<'_>,
109+
) -> anyhow::Result<()> {
110+
let mut artifacts = StarknetArtifacts::default();
111+
let mut file_stem_calculator = ContractFileStemCalculator::new(contract_paths);
112+
let extension_prefix = self
113+
.extension_prefix
114+
.map(|ext| format!(".{ext}"))
115+
.unwrap_or_default();
116+
117+
for (declaration, class, casm_class) in izip!(contracts, classes, casm_classes) {
118+
let contract_name = declaration.submodule_id.name(db.upcast_mut());
119+
let contract_path = declaration.module_id().full_path(db.upcast_mut());
120+
121+
let contract_selector = ContractSelector(contract_path);
122+
let package_name = contract_selector.package();
123+
let contract_stem = file_stem_calculator.get_stem(contract_selector.full_path());
124+
125+
let file_stem = format!("{}_{contract_stem}", self.target_name);
126+
127+
let mut artifact = ContractArtifacts::new(
128+
package_name,
129+
&contract_name,
130+
contract_selector.full_path().as_str(),
131+
&declaration.module_id().full_path(db.upcast_mut()),
132+
);
133+
134+
if self.sierra {
135+
let file_name = format!("{file_stem}{extension_prefix}.contract_class.json");
136+
write_json(&file_name, "output file", &self.target_dir, ws, class)?;
137+
artifact.artifacts.sierra = Some(file_name);
138+
}
139+
140+
if self.casm {
141+
if let Some(casm_class) = casm_class {
142+
let file_name =
143+
format!("{file_stem}{extension_prefix}.compiled_contract_class.json");
144+
write_json(&file_name, "output file", &self.target_dir, ws, casm_class)?;
145+
artifact.artifacts.casm = Some(file_name);
146+
}
147+
}
148+
149+
artifacts.contracts.push(artifact);
150+
}
151+
152+
artifacts.finish();
153+
154+
write_json(
155+
&format!(
156+
"{}{extension_prefix}.starknet_artifacts.json",
157+
self.target_name
158+
),
159+
"starknet artifacts file",
160+
&self.target_dir,
161+
ws,
162+
&artifacts,
163+
)?;
164+
165+
Ok(())
166+
}
167+
}

0 commit comments

Comments
 (0)