@@ -8,7 +8,8 @@ use console::{style, Term};
88use inquire:: validator:: Validation ;
99use inquire:: { Autocomplete , Confirm , CustomUserError , Select , Text } ;
1010
11- use crate :: services:: { Network , NetworksRegistry } ;
11+ use crate :: output:: { step, Step } ;
12+ use crate :: services:: { ContractInfo , ContractService , Network , NetworksRegistry } ;
1213
1314/// Format a network for display.
1415fn format_network ( network : & Network ) -> String {
@@ -347,8 +348,14 @@ pub struct InitForm {
347348
348349impl InitForm {
349350 /// Run the interactive form, filling in missing values.
351+ ///
352+ /// The flow for contract mode is:
353+ /// 1. Prompt for network (if not provided)
354+ /// 2. Prompt for contract address (if not provided)
355+ /// 3. Fetch contract info from Etherscan/Sourcify (ABI, name, start block)
356+ /// 4. Use fetched values as defaults for remaining prompts
350357 #[ allow( clippy:: too_many_arguments) ]
351- pub fn run_interactive (
358+ pub async fn run_interactive (
352359 registry : & NetworksRegistry ,
353360 // Pre-filled values from CLI args
354361 network : Option < String > ,
@@ -398,22 +405,34 @@ impl InitForm {
398405
399406 // For contract mode, we need network, address, etc.
400407
401- // Network
408+ // Step 1: Network
402409 let network = match network {
403410 Some ( n) => n,
404411 None => prompt_network_interactive ( registry) ?,
405412 } ;
406413
407- // Contract address
414+ // Step 2: Contract address
408415 let contract_address = match from_contract {
409416 Some ( addr) => addr,
410417 None => prompt_contract_address ( ) ?,
411418 } ;
412419
413- // Contract name
420+ // Step 3: Fetch contract info immediately after getting address
421+ // This allows us to use fetched values as defaults for remaining prompts
422+ let fetched_info = if abi_path. is_none ( ) {
423+ fetch_contract_info_interactive ( & network, & contract_address) . await
424+ } else {
425+ None
426+ } ;
427+
428+ // Step 4: Contract name (use fetched name as default)
429+ let default_contract_name = fetched_info
430+ . as_ref ( )
431+ . map ( |info| info. name . clone ( ) )
432+ . or_else ( || contract_name. clone ( ) ) ;
414433 let contract_name = match contract_name {
415434 Some ( n) => n,
416- None => prompt_contract_name ( None ) ?,
435+ None => prompt_contract_name ( default_contract_name . as_deref ( ) ) ?,
417436 } ;
418437
419438 // Subgraph name
@@ -430,17 +449,28 @@ impl InitForm {
430449 None => prompt_directory ( Some ( & default_dir) ) ?,
431450 } ;
432451
433- // ABI path (optional)
452+ // ABI path - only prompt if we didn't fetch it successfully
434453 let abi_path = match abi_path {
435454 Some ( p) => Some ( p) ,
436- None => prompt_abi_path ( ) ?,
455+ None => {
456+ if fetched_info. is_some ( ) {
457+ // We successfully fetched the ABI, no need to prompt
458+ None
459+ } else {
460+ prompt_abi_path ( ) ?
461+ }
462+ }
437463 } ;
438464
439- // Start block
465+ // Start block (use fetched start block as default)
466+ let default_start_block = fetched_info
467+ . as_ref ( )
468+ . and_then ( |info| info. start_block )
469+ . or ( start_block) ;
440470 let start_block = if start_block. is_some ( ) {
441471 start_block
442472 } else {
443- prompt_start_block ( None ) ?
473+ prompt_start_block ( default_start_block ) ?
444474 } ;
445475
446476 // Index events
@@ -464,6 +494,46 @@ impl InitForm {
464494 }
465495}
466496
497+ /// Fetch contract info from Etherscan/Sourcify with status feedback.
498+ ///
499+ /// Returns None if fetching fails (the prompts will fall back to manual entry).
500+ async fn fetch_contract_info_interactive ( network : & str , address : & str ) -> Option < ContractInfo > {
501+ step (
502+ Step :: Load ,
503+ & format ! ( "Fetching contract info for {} on {}" , address, network) ,
504+ ) ;
505+
506+ // Load the contract service
507+ let service = match ContractService :: load ( ) . await {
508+ Ok ( s) => s,
509+ Err ( e) => {
510+ step (
511+ Step :: Warn ,
512+ & format ! ( "Could not load contract service: {}" , e) ,
513+ ) ;
514+ return None ;
515+ }
516+ } ;
517+
518+ // Fetch the contract info
519+ match service. get_contract_info ( network, address) . await {
520+ Ok ( info) => {
521+ step ( Step :: Done , & format ! ( "Found contract: {}" , info. name) ) ;
522+ Some ( info)
523+ }
524+ Err ( e) => {
525+ step (
526+ Step :: Warn ,
527+ & format ! (
528+ "Could not fetch contract info: {}. You'll need to provide an ABI file." ,
529+ e
530+ ) ,
531+ ) ;
532+ None
533+ }
534+ }
535+ }
536+
467537/// Prompt for network selection using the simple completer.
468538fn prompt_network_interactive ( registry : & NetworksRegistry ) -> Result < String > {
469539 let completer = SimpleNetworkCompleter :: new ( registry) ;
0 commit comments