@@ -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 ) ]
255265struct 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.
10111140fn print_table < T > ( data : T , color : Option < Color > , title : Option < & str > )
10121141where
0 commit comments