@@ -242,6 +242,9 @@ impl Session {
242242 cmd if cmd. starts_with ( "::set_epoch" ) => self . set_epoch ( cmd) ,
243243 cmd if cmd. starts_with ( "::encode" ) => self . encode ( cmd) ,
244244 cmd if cmd. starts_with ( "::decode" ) => self . decode ( cmd) ,
245+ cmd if cmd. starts_with ( "::get_constant" ) => self . get_constant ( cmd) ,
246+ cmd if cmd. starts_with ( "::get_data_var" ) => self . get_data_var ( cmd) ,
247+ cmd if cmd. starts_with ( "::get_map_val" ) => self . get_map_val ( cmd) ,
245248
246249 _ => "Invalid command. Try `::help`" . yellow ( ) . to_string ( ) ,
247250 }
@@ -868,6 +871,18 @@ impl Session {
868871 "{}" ,
869872 "::decode <bytes>\t \t \t Decode a Clarity Value bytes representation" . yellow( )
870873 ) ) ;
874+ output. push ( format ! (
875+ "{}" ,
876+ "::get_constant <contract> <constant>\t Get constant value from a contract" . yellow( )
877+ ) ) ;
878+ output. push ( format ! (
879+ "{}" ,
880+ "::get_data_var <contract> <var>\t \t Get data variable value from a contract" . yellow( )
881+ ) ) ;
882+ output. push ( format ! (
883+ "{}" ,
884+ "::get_map_val <contract> <map> <key>\t Get map value from a contract" . yellow( )
885+ ) ) ;
871886
872887 output. join ( "\n " )
873888 }
@@ -1101,6 +1116,226 @@ impl Session {
11011116 format ! ( "{}" , value_to_string( & value) . green( ) )
11021117 }
11031118
1119+ pub fn get_constant ( & mut self , cmd : & str ) -> String {
1120+ let args: Vec < _ > = cmd. split_whitespace ( ) . skip ( 1 ) . collect ( ) ;
1121+
1122+ if args. len ( ) != 2 {
1123+ return format ! ( "{}" , "Usage: ::get_constant <contract> <constant>" . red( ) ) ;
1124+ }
1125+
1126+ let contract_name = args[ 0 ] ;
1127+ let constant_name = args[ 1 ] ;
1128+
1129+ let default_deployer = match self . settings . initial_deployer . as_ref ( ) {
1130+ Some ( account) => account. address . clone ( ) ,
1131+ None => self . get_tx_sender ( ) ,
1132+ } ;
1133+
1134+ let contract_id = match Self :: desugar_contract_id ( & default_deployer, contract_name) {
1135+ Ok ( id) => id,
1136+ Err ( e) => return format ! ( "{} {}" , "Invalid contract identifier:" . red( ) , e) ,
1137+ } ;
1138+
1139+ let contract = match self . contracts . get ( & contract_id) {
1140+ Some ( contract) => contract,
1141+ None => return format ! ( "{} {}" , "Contract not found:" . red( ) , contract_id) ,
1142+ } ;
1143+
1144+ // Search for constant in the contract's AST
1145+ for function_definition in & contract. ast . expressions {
1146+ if let Some ( expr) = function_definition. match_list ( ) {
1147+ if expr. len ( ) >= 3 {
1148+ if let Some ( name_expr) = expr. get ( 1 ) {
1149+ if let Some ( name) = name_expr. match_atom ( ) {
1150+ if name. as_str ( ) == constant_name && expr. len ( ) >= 3 {
1151+ let expr_str = format ! ( "{}" , expr[ 2 ] ) ;
1152+ return format ! ( "{} {}\n {} {}\n {} {}" ,
1153+ "Contract:" . yellow( ) ,
1154+ contract_id. to_string( ) . green( ) ,
1155+ "Constant:" . yellow( ) ,
1156+ name. green( ) ,
1157+ "Value:" . yellow( ) ,
1158+ expr_str. green( )
1159+ ) ;
1160+ }
1161+ }
1162+ }
1163+ }
1164+ }
1165+ }
1166+
1167+ format ! ( "{} {} {} {}" ,
1168+ "Constant:" . red( ) ,
1169+ constant_name. red( ) ,
1170+ "not found in contract:" . red( ) ,
1171+ contract_id. to_string( ) . red( )
1172+ )
1173+ }
1174+
1175+ pub fn get_data_var ( & mut self , cmd : & str ) -> String {
1176+ let args: Vec < _ > = cmd. split_whitespace ( ) . skip ( 1 ) . collect ( ) ;
1177+
1178+ if args. len ( ) != 2 {
1179+ return format ! ( "{}" , "Usage: ::get_data_var <contract> <var>" . red( ) ) ;
1180+ }
1181+
1182+ let contract_name = args[ 0 ] ;
1183+ let var_name = args[ 1 ] ;
1184+
1185+ let default_deployer = match self . settings . initial_deployer . as_ref ( ) {
1186+ Some ( account) => account. address . clone ( ) ,
1187+ None => self . get_tx_sender ( ) ,
1188+ } ;
1189+
1190+ let contract_id = match Self :: desugar_contract_id ( & default_deployer, contract_name) {
1191+ Ok ( id) => id,
1192+ Err ( e) => return format ! ( "{} {}" , "Invalid contract identifier:" . red( ) , e) ,
1193+ } ;
1194+
1195+ match self . interpreter . get_data_var ( & contract_id, var_name) {
1196+ Some ( value_hex) => {
1197+ // Convert hex string back to Clarity Value for display
1198+ let value_bytes = match decode_hex ( & value_hex) {
1199+ Ok ( bytes) => bytes,
1200+ Err ( e) => return format ! ( "{} {} {} {}" ,
1201+ "Failed to decode value:" . red( ) ,
1202+ e. to_string( ) . red( ) ,
1203+ "from contract:" . red( ) ,
1204+ contract_id. to_string( ) . red( )
1205+ )
1206+ } ;
1207+
1208+ let value = match Value :: consensus_deserialize ( & mut & value_bytes[ ..] ) {
1209+ Ok ( value) => value,
1210+ Err ( e) => return format ! ( "{} {} {} {}" ,
1211+ "Failed to deserialize value:" . red( ) ,
1212+ e. to_string( ) . red( ) ,
1213+ "from contract:" . red( ) ,
1214+ contract_id. to_string( ) . red( )
1215+ )
1216+ } ;
1217+
1218+ format ! ( "{} {}\n {} {}\n {} {}" ,
1219+ "Contract:" . yellow( ) ,
1220+ contract_id. to_string( ) . green( ) ,
1221+ "Data var:" . yellow( ) ,
1222+ var_name. green( ) ,
1223+ "Value:" . yellow( ) ,
1224+ value_to_string( & value) . green( )
1225+ )
1226+ }
1227+ None => {
1228+ format ! ( "{} {} {} {}" ,
1229+ "Data var:" . red( ) ,
1230+ var_name. red( ) ,
1231+ "not found in contract:" . red( ) ,
1232+ contract_id. to_string( ) . red( )
1233+ )
1234+ }
1235+ }
1236+ }
1237+
1238+ pub fn get_map_val ( & mut self , cmd : & str ) -> String {
1239+ let args: Vec < _ > = cmd. split_whitespace ( ) . skip ( 1 ) . collect ( ) ;
1240+
1241+ if args. len ( ) < 3 {
1242+ return format ! ( "{}" , "Usage: ::get_map_val <contract> <map> <key>" . red( ) ) ;
1243+ }
1244+
1245+ let contract_name = args[ 0 ] ;
1246+ let map_name = args[ 1 ] ;
1247+ let key_expr = args[ 2 ..] . join ( " " ) ;
1248+
1249+ let default_deployer = match self . settings . initial_deployer . as_ref ( ) {
1250+ Some ( account) => account. address . clone ( ) ,
1251+ None => self . get_tx_sender ( ) ,
1252+ } ;
1253+
1254+ let contract_id = match Self :: desugar_contract_id ( & default_deployer, contract_name) {
1255+ Ok ( id) => id,
1256+ Err ( e) => return format ! ( "{} {}" , "Invalid contract identifier:" . red( ) , e) ,
1257+ } ;
1258+
1259+ // Parse the key expression to get a Clarity Value
1260+ let key_value = match self . eval_clarity_string ( & key_expr) {
1261+ value => value,
1262+ } ;
1263+
1264+ // Extract the actual Value from the SymbolicExpression
1265+ let key_value = match key_value. match_atom_value ( ) {
1266+ Some ( value) => value. clone ( ) ,
1267+ None => {
1268+ // For complex expressions, we need to evaluate them differently
1269+ let result = match self . eval_with_hooks ( format ! ( "({})" , key_expr) , None , false ) {
1270+ Ok ( result) => {
1271+ match & result. result {
1272+ EvaluationResult :: Snippet ( snippet_result) => snippet_result. result . clone ( ) ,
1273+ _ => return format ! ( "{} {} {} {}" ,
1274+ "Unable to evaluate key expression:" . red( ) ,
1275+ key_expr. red( ) ,
1276+ "for contract:" . red( ) ,
1277+ contract_id. to_string( ) . red( )
1278+ )
1279+ }
1280+ }
1281+ Err ( _) => return format ! ( "{} {} {} {}" ,
1282+ "Unable to evaluate key expression:" . red( ) ,
1283+ key_expr. red( ) ,
1284+ "for contract:" . red( ) ,
1285+ contract_id. to_string( ) . red( )
1286+ )
1287+ } ;
1288+ result
1289+ }
1290+ } ;
1291+
1292+ match self . interpreter . get_map_entry ( & contract_id, map_name, & key_value) {
1293+ Some ( value_hex) => {
1294+ // Convert hex string back to Clarity Value for display
1295+ let value_bytes = match decode_hex ( & value_hex) {
1296+ Ok ( bytes) => bytes,
1297+ Err ( e) => return format ! ( "{} {} {} {}" ,
1298+ "Failed to decode value:" . red( ) ,
1299+ e. to_string( ) . red( ) ,
1300+ "from contract:" . red( ) ,
1301+ contract_id. to_string( ) . red( )
1302+ )
1303+ } ;
1304+
1305+ let value = match Value :: consensus_deserialize ( & mut & value_bytes[ ..] ) {
1306+ Ok ( value) => value,
1307+ Err ( e) => return format ! ( "{} {} {} {}" ,
1308+ "Failed to deserialize value:" . red( ) ,
1309+ e. to_string( ) . red( ) ,
1310+ "from contract:" . red( ) ,
1311+ contract_id. to_string( ) . red( )
1312+ )
1313+ } ;
1314+
1315+ format ! ( "{} {}\n {} {}\n {} {}\n {} {}" ,
1316+ "Contract:" . yellow( ) ,
1317+ contract_id. to_string( ) . green( ) ,
1318+ "Map:" . yellow( ) ,
1319+ map_name. green( ) ,
1320+ "Key:" . yellow( ) ,
1321+ key_expr. green( ) ,
1322+ "Value:" . yellow( ) ,
1323+ value_to_string( & value) . green( )
1324+ )
1325+ }
1326+ None => {
1327+ format ! ( "{} {} {} {} {} {}" ,
1328+ "Map entry not found for key:" . red( ) ,
1329+ key_expr. red( ) ,
1330+ "in map:" . red( ) ,
1331+ map_name. red( ) ,
1332+ "of contract:" . red( ) ,
1333+ contract_id. to_string( ) . red( )
1334+ )
1335+ }
1336+ }
1337+ }
1338+
11041339 #[ cfg( not( target_arch = "wasm32" ) ) ]
11051340 pub fn get_costs ( & mut self , output : & mut Vec < String > , cmd : & str ) {
11061341 let Some ( ( _, expr) ) = cmd. split_once ( ' ' ) else {
0 commit comments