Skip to content

Commit e7b095b

Browse files
committed
gnd: Add prompt to add another contract at end of init
After creating a subgraph from a contract, gnd now prompts "Add another contract from <network>?" in interactive mode. This allows users to add multiple contracts in a single session, similar to graph-cli behavior. The flow: 1. User completes init --from-contract 2. gnd asks if they want to add another contract 3. If yes, prompts for address, name, start block 4. Runs the add command internally with merge_entities=true 5. Repeats until user says no Implements I2 from the PR review feedback plan.
1 parent 211e661 commit e7b095b

2 files changed

Lines changed: 84 additions & 2 deletions

File tree

gnd/src/commands/init.rs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ use anyhow::{anyhow, Context, Result};
1717
use clap::{Parser, ValueEnum};
1818
use graphql_parser::schema as gql;
1919

20+
use crate::commands::add::{run_add, AddOpt};
2021
use crate::config::networks::update_networks_file;
2122
use crate::output::{step, with_spinner, Step};
2223
use crate::prompt::{
23-
get_subgraph_basename, prompt_directory_with_confirm, prompt_subgraph_slug_with_confirm,
24-
InitForm, SourceType,
24+
get_subgraph_basename, prompt_add_another_contract, prompt_contract_address,
25+
prompt_contract_name, prompt_directory_with_confirm, prompt_start_block,
26+
prompt_subgraph_slug_with_confirm, InitForm, SourceType,
2527
};
2628
use crate::scaffold::{generate_scaffold, init_git, install_dependencies, ScaffoldOptions};
2729
use crate::services::{ContractInfo, ContractService, IpfsClient, NetworksRegistry};
@@ -387,6 +389,11 @@ async fn init_from_contract(opt: &InitOpt) -> Result<()> {
387389
&format!("Subgraph created at {}", directory.display()),
388390
);
389391

392+
// Prompt to add more contracts if in interactive mode
393+
if io::stdin().is_terminal() {
394+
add_more_contracts_loop(&directory, network).await?;
395+
}
396+
390397
println!();
391398
println!("Next steps:");
392399
println!(" cd {}", directory.display());
@@ -396,6 +403,73 @@ async fn init_from_contract(opt: &InitOpt) -> Result<()> {
396403
Ok(())
397404
}
398405

406+
/// Loop to add more contracts interactively.
407+
async fn add_more_contracts_loop(directory: &Path, network: &str) -> Result<()> {
408+
while prompt_add_another_contract(network)? {
409+
// Prompt for contract address
410+
let address = prompt_contract_address()?;
411+
412+
// Fetch contract info to get defaults
413+
let fetched_info = fetch_contract_info_for_add(network, &address).await;
414+
415+
// Prompt for contract name with fetched default
416+
let default_name = fetched_info.as_ref().map(|i| i.name.as_str());
417+
let contract_name = prompt_contract_name(default_name)?;
418+
419+
// Prompt for start block with fetched default
420+
let default_start_block = fetched_info.as_ref().and_then(|i| i.start_block);
421+
let start_block = prompt_start_block(default_start_block)?;
422+
423+
// Run the add command
424+
let add_opt = AddOpt {
425+
address,
426+
manifest: directory.join("subgraph.yaml"),
427+
abi: None,
428+
contract_name: Some(contract_name),
429+
merge_entities: true, // Merge by default when adding during init
430+
network_file: PathBuf::from("networks.json"),
431+
start_block: start_block.map(|b| b.to_string()),
432+
};
433+
434+
if let Err(e) = run_add(add_opt).await {
435+
eprintln!("Warning: Failed to add contract: {}", e);
436+
// Continue the loop to allow trying again or adding a different contract
437+
}
438+
}
439+
440+
Ok(())
441+
}
442+
443+
/// Fetch contract info for the add-another-contract flow.
444+
async fn fetch_contract_info_for_add(network: &str, address: &str) -> Option<ContractInfo> {
445+
step(
446+
Step::Load,
447+
&format!("Fetching contract info for {} on {}", address, network),
448+
);
449+
450+
let service = match ContractService::load().await {
451+
Ok(s) => s,
452+
Err(e) => {
453+
step(
454+
Step::Warn,
455+
&format!("Could not load contract service: {}", e),
456+
);
457+
return None;
458+
}
459+
};
460+
461+
match service.get_contract_info(network, address).await {
462+
Ok(info) => {
463+
step(Step::Done, &format!("Found contract: {}", info.name));
464+
Some(info)
465+
}
466+
Err(e) => {
467+
step(Step::Warn, &format!("Could not fetch contract info: {}", e));
468+
None
469+
}
470+
}
471+
}
472+
399473
/// Recursively copy a directory and its contents.
400474
fn copy_dir_recursive(src: &Path, dst: &Path) -> Result<()> {
401475
fs::create_dir_all(dst)?;

gnd/src/prompt.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,14 @@ pub fn prompt_index_events() -> Result<bool> {
196196
.map_err(Into::into)
197197
}
198198

199+
/// Prompt for whether to add another contract to the subgraph.
200+
pub fn prompt_add_another_contract(network: &str) -> Result<bool> {
201+
Confirm::new(&format!("Add another contract from {}?", network))
202+
.with_default(false)
203+
.prompt()
204+
.map_err(Into::into)
205+
}
206+
199207
/// Prompt for the source type (contract, example, subgraph).
200208
#[derive(Debug, Clone, Copy, PartialEq)]
201209
pub enum SourceType {

0 commit comments

Comments
 (0)