Skip to content

Commit eb1382e

Browse files
authored
feat(sozo): add world factory output (#3362)
* feat(sozo): add world factory output * fix fmt * fix: update factory output with permissions and new params * fix fmt
1 parent 30f8966 commit eb1382e

File tree

1 file changed

+130
-1
lines changed

1 file changed

+130
-1
lines changed

bin/sozo/src/commands/inspect.rs

Lines changed: 130 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ pub struct InspectArgs {
2626
#[arg(long, help = "Output in JSON format")]
2727
json: bool,
2828

29+
#[arg(long, help = "Output Cairo code for FactoryConfig initialization")]
30+
output_factory: bool,
31+
2932
#[command(flatten)]
3033
world: WorldOptions,
3134

@@ -37,13 +40,15 @@ impl InspectArgs {
3740
pub async fn run(self, scarb_metadata: &Metadata, ui: &SozoUi) -> Result<()> {
3841
trace!(args = ?self);
3942

40-
let InspectArgs { world, starknet, element, json } = self;
43+
let InspectArgs { world, starknet, element, json, output_factory } = self;
4144

4245
let (world_diff, _, _) =
4346
utils::get_world_diff_and_provider(starknet.clone(), world, scarb_metadata, ui).await?;
4447

4548
if let Some(element) = element {
4649
inspect_element(&element, &world_diff, json)?;
50+
} else if output_factory {
51+
inspect_world_factory(&world_diff)?;
4752
} else {
4853
inspect_world(&world_diff, json);
4954
}
@@ -141,6 +146,8 @@ struct ModelInspect {
141146
status: ResourceStatus,
142147
#[tabled(rename = "Dojo Selector")]
143148
selector: String,
149+
#[tabled(rename = "Class Hash")]
150+
current_class_hash: String,
144151
}
145152

146153
#[derive(Debug, Tabled, Serialize)]
@@ -151,6 +158,8 @@ struct EventInspect {
151158
status: ResourceStatus,
152159
#[tabled(rename = "Dojo Selector")]
153160
selector: String,
161+
#[tabled(rename = "Class Hash")]
162+
current_class_hash: String,
154163
}
155164

156165
#[derive(Debug, Tabled, Serialize)]
@@ -249,13 +258,15 @@ struct JsonModelInfo {
249258
tag: String,
250259
status: String,
251260
selector: String,
261+
class_hash: String,
252262
}
253263

254264
#[derive(Debug, Serialize)]
255265
struct JsonEventInfo {
256266
tag: String,
257267
status: String,
258268
selector: String,
269+
class_hash: String,
259270
}
260271

261272
#[derive(Debug, Serialize)]
@@ -661,6 +672,7 @@ fn inspect_world(world_diff: &WorldDiff, json: bool) {
661672
tag: resource.tag(),
662673
status,
663674
selector: format!("{:#066x}", resource.dojo_selector()),
675+
class_hash: format!("{:#066x}", resource.current_class_hash()),
664676
});
665677
}
666678
ResourceType::Event => {
@@ -673,6 +685,7 @@ fn inspect_world(world_diff: &WorldDiff, json: bool) {
673685
tag: resource.tag(),
674686
status,
675687
selector: format!("{:#066x}", resource.dojo_selector()),
688+
class_hash: format!("{:#066x}", resource.current_class_hash()),
676689
});
677690
}
678691
ResourceType::ExternalContract => {
@@ -935,6 +948,7 @@ fn resource_diff_display(world_diff: &WorldDiff, resource: &ResourceDiff) -> Res
935948
tag: resource.tag(),
936949
status,
937950
selector: format!("{:#066x}", resource.dojo_selector()),
951+
current_class_hash: format!("{:#066x}", resource.current_class_hash()),
938952
})
939953
}
940954
ResourceType::Event => {
@@ -960,6 +974,7 @@ fn resource_diff_display(world_diff: &WorldDiff, resource: &ResourceDiff) -> Res
960974
tag: resource.tag(),
961975
status,
962976
selector: format!("{:#066x}", resource.dojo_selector()),
977+
current_class_hash: format!("{:#066x}", resource.current_class_hash()),
963978
})
964979
}
965980
ResourceType::ExternalContract => {
@@ -1007,6 +1022,120 @@ fn resource_diff_display(world_diff: &WorldDiff, resource: &ResourceDiff) -> Res
10071022
}
10081023
}
10091024

1025+
/// Generates Cairo code for FactoryConfig initialization.
1026+
fn inspect_world_factory(world_diff: &WorldDiff) -> Result<()> {
1027+
let world_class_hash = format!("{:#066x}", world_diff.world_info.class_hash);
1028+
1029+
// Get the first namespace or use a default
1030+
let default_namespace = world_diff
1031+
.resources
1032+
.values()
1033+
.find(|r| matches!(r.resource_type(), ResourceType::Namespace))
1034+
.map(|r| r.name())
1035+
.unwrap_or_else(|| "dojo".to_string());
1036+
1037+
// Collect contracts (excluding external contracts)
1038+
// (tag, selector, class_hash)
1039+
let mut contracts: Vec<(String, String, String)> = world_diff
1040+
.resources
1041+
.values()
1042+
.filter(|r| matches!(r.resource_type(), ResourceType::Contract))
1043+
.map(|r| {
1044+
let tag = r.tag();
1045+
let selector = format!("{:#066x}", naming::compute_selector_from_tag(&tag));
1046+
(tag, selector, format!("{:#066x}", r.current_class_hash()))
1047+
})
1048+
.collect();
1049+
contracts.sort_by(|a, b| a.0.cmp(&b.0));
1050+
1051+
// Collect models
1052+
let mut models: Vec<String> = world_diff
1053+
.resources
1054+
.values()
1055+
.filter(|r| matches!(r.resource_type(), ResourceType::Model))
1056+
.map(|r| format!("{:#066x}", r.current_class_hash()))
1057+
.collect();
1058+
models.sort();
1059+
1060+
// Collect events
1061+
let mut events: Vec<String> = world_diff
1062+
.resources
1063+
.values()
1064+
.filter(|r| matches!(r.resource_type(), ResourceType::Event))
1065+
.map(|r| format!("{:#066x}", r.current_class_hash()))
1066+
.collect();
1067+
events.sort();
1068+
1069+
// Print the Cairo code
1070+
println!("let factory_config = FactoryConfig {{");
1071+
println!(" version: '1',");
1072+
println!(
1073+
" world_class_hash: TryInto::<felt252, ClassHash>::try_into({}).unwrap(),",
1074+
world_class_hash
1075+
);
1076+
println!(" default_namespace: \"{}\",", default_namespace);
1077+
1078+
// Print contracts
1079+
println!(" contracts: array![");
1080+
for (tag, _, class_hash) in &contracts {
1081+
println!(
1082+
" (selector_from_tag!(\"{}\"), TryInto::<felt252, \
1083+
ClassHash>::try_into({}).unwrap(), array![]),",
1084+
tag, class_hash
1085+
);
1086+
}
1087+
println!(" ],");
1088+
1089+
// Print models
1090+
println!(" models: array![");
1091+
for model_hash in &models {
1092+
println!(" TryInto::<felt252, ClassHash>::try_into({}).unwrap(),", model_hash);
1093+
}
1094+
println!(" ],");
1095+
1096+
// Print events
1097+
println!(" events: array![");
1098+
for event_hash in &events {
1099+
println!(" TryInto::<felt252, ClassHash>::try_into({}).unwrap(),", event_hash);
1100+
}
1101+
println!(" ],");
1102+
1103+
println!("}};");
1104+
1105+
// Print the sozo command line
1106+
println!();
1107+
println!("# Sozo command to execute:");
1108+
print!(
1109+
"sozo -P <PROFILE> execute factory set_config <VERSION> <MAX_ACTION_default_20_is_good> {}",
1110+
world_class_hash
1111+
);
1112+
print!(" str:{}", default_namespace);
1113+
print!(" <BOOL_TO_SET_WRITERS_ALL_CONTRACTS_ON_DEFAULT_NAMESPACE>");
1114+
1115+
// Contracts array
1116+
print!(" {}", contracts.len());
1117+
// For now, init_args, writers and owners are not supported, hence empty array.
1118+
for (_, selector, class_hash) in &contracts {
1119+
print!(" {} {} 0 0 0", selector, class_hash);
1120+
}
1121+
1122+
// Models array
1123+
print!(" {}", models.len());
1124+
for model_hash in &models {
1125+
print!(" {}", model_hash);
1126+
}
1127+
1128+
// Events array
1129+
print!(" {}", events.len());
1130+
for event_hash in &events {
1131+
print!(" {}", event_hash);
1132+
}
1133+
1134+
println!();
1135+
1136+
Ok(())
1137+
}
1138+
10101139
/// Prints a table.
10111140
fn print_table<T>(data: T, color: Option<Color>, title: Option<&str>)
10121141
where

0 commit comments

Comments
 (0)