Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions gnd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,52 @@ gnd dev [OPTIONS]
| `--ethereum-rpc` | | Ethereum RPC URL |
| `--ipfs` | | IPFS node URL |

### `gnd indexer`

Manage indexer operations via [`indexer-cli`](https://github.com/graphprotocol/indexer/tree/main/packages/indexer-cli).

Requires `graph-indexer` to be installed and on `$PATH`:

```bash
npm install -g @graphprotocol/indexer-cli
```

```bash
gnd indexer <subcommand> [args...]
```

**Help:**

There are two ways to get help:

| Command | What it shows |
|---------|---------------|
| `gnd indexer --help` | gnd's own help for the indexer subcommand (works without `graph-indexer` installed) |
| `gnd indexer help` | Full `graph-indexer` help with all available commands (requires `graph-indexer`) |

**Examples:**

```bash
# Check indexer status
gnd indexer status --network arbitrum-one

# Manage indexing rules
gnd indexer rules get all --network mainnet
gnd indexer rules set <deployment> decisionBasis always --network mainnet

# Manage allocations
gnd indexer allocations get --network arbitrum-one

# Manage cost models
gnd indexer cost get

# View available indexer commands
gnd indexer help

# Check graph-indexer version
gnd indexer version
```

### `gnd completions`

Generate shell completions.
Expand Down
16 changes: 16 additions & 0 deletions gnd/docs/migrating-from-graph-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ gnd deploy my-subgraph # defaults to Studio
| `graph test` | `gnd test` | Identical flags |
| `graph clean` | `gnd clean` | Identical flags (new in graph-cli 0.80+) |
| `graph publish` | `gnd publish` | Identical flags |
| `graph indexer` | `gnd indexer` | Delegates to `graph-indexer` — requires `indexer-cli` installed |
| `graph local` | N/A | Not implemented - use graph-node's test infrastructure |
| `graph node` | N/A | Not implemented - use `graphman` |

Expand Down Expand Up @@ -67,6 +68,7 @@ Same success checkmarks, step descriptions, and progress indicators:

- `0` for success
- `1` for any error
- `gnd indexer` passes through the exit code from `graph-indexer`

### Configuration Files

Expand All @@ -83,6 +85,20 @@ Code generation produces identical AssemblyScript output (after formatting). You

## What's Different

### Indexer Commands

`gnd indexer` provides access to indexer management commands via [`indexer-cli`](https://github.com/graphprotocol/indexer/tree/main/packages/indexer-cli). Requires `graph-indexer` on `$PATH`:

```bash
npm install -g @graphprotocol/indexer-cli

gnd indexer status --network arbitrum-one
gnd indexer rules get all --network mainnet
gnd indexer allocations get --network arbitrum-one
```

Note: `gnd indexer --help` shows gnd's own help and works without `graph-indexer` installed. Use `gnd indexer help` to see the full list of `graph-indexer` commands.

### Commands Not Available

#### `graph local`
Expand Down
72 changes: 71 additions & 1 deletion gnd/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::ffi::OsString;
use std::io;
use std::process::Command;

use anyhow::Result;
use anyhow::{bail, Result};
use clap::{CommandFactory, Parser, Subcommand, ValueEnum};
use clap_complete::{generate, Shell};
use git_testament::{git_testament, render_testament};
Expand Down Expand Up @@ -83,6 +85,22 @@ enum Commands {
/// Remove build artifacts and generated files
Clean(CleanOpt),

/// Manage indexer operations. Requires `graph-indexer` to be installed and available on $PATH.
///
/// Install it with:
///
/// npm install -g @graphprotocol/indexer-cli
///
/// Arguments are forwarded to `graph-indexer`. For example:
///
/// gnd indexer allocations get --network arbitrum-one
///
/// Use `gnd indexer help` for more details on available commands.
Indexer {
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<OsString>,
},

/// Generate shell completions
Completions(CompletionsOpt),
}
Expand Down Expand Up @@ -153,6 +171,57 @@ fn generate_completions(completions_opt: CompletionsOpt) -> Result<()> {
Ok(())
}

/// Delegates to the `graph-indexer` binary from the `indexer-cli` npm package.
///
/// The `graph-indexer` CLI expects all indexer management commands to be
/// prefixed with `indexer` (e.g. `graph-indexer indexer allocations get ...`).
/// This is because `graph-indexer` uses Gluegun's plugin system where `indexer`
/// is the plugin namespace. We prepend it automatically so that users can write
/// `gnd indexer allocations get` instead of the longer form.
fn run_indexer(args: Vec<OsString>) -> Result<()> {
let mut cmd = Command::new("graph-indexer");
// `version` and `help` are top-level commands, but all other commands
// require the `indexer` namespace prefix (e.g. `graph-indexer indexer allocations get`).
let first = args.first().and_then(|s| s.to_str());
match first {
Some("version" | "--version" | "v" | "-v" | "help" | "h") => {}
// If no arguments are provided, default to showing top-level help
None => {
cmd.arg("help");
}
_ => {
cmd.arg("indexer");
}
}
cmd.args(&args);

#[cfg(unix)]
{
use std::os::unix::process::CommandExt;
let err = cmd.exec();
if err.kind() == io::ErrorKind::NotFound {
bail!(
"'graph-indexer' not found on $PATH. Install indexer-cli: npm install -g @graphprotocol/indexer-cli"
);
}
bail!("failed to exec 'graph-indexer': {err}");
}

#[cfg(not(unix))]
{
match cmd.status() {
Ok(status) if status.success() => Ok(()),
Ok(status) => std::process::exit(status.code().unwrap_or(1)),
Err(e) if e.kind() == io::ErrorKind::NotFound => {
bail!(
"'graph-indexer' not found on $PATH. Install indexer-cli: npm install -g @graphprotocol/indexer-cli"
);
}
Err(e) => bail!("failed to run 'graph-indexer': {e}"),
}
}
}

#[tokio::main]
async fn main() -> Result<()> {
std::env::set_var("ETHEREUM_REORG_THRESHOLD", "10");
Expand Down Expand Up @@ -186,6 +255,7 @@ async fn main() -> Result<()> {
run_test(test_opt).await
}
Commands::Clean(clean_opt) => run_clean(clean_opt),
Commands::Indexer { args } => run_indexer(args),
Commands::Completions(completions_opt) => generate_completions(completions_opt),
};

Expand Down
55 changes: 55 additions & 0 deletions gnd/tests/cli_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,61 @@ fn run_gnd_success(args: &[&str], cwd: &Path) -> std::process::Output {
output
}

// ============================================================================
// gnd indexer tests
// ============================================================================

#[test]
fn test_indexer_missing_binary_error() {
let gnd = verify_gnd_binary();

// Run with an empty PATH so graph-indexer cannot be found.
let output = Command::new(&gnd)
.args(["indexer", "status", "--network", "mainnet"])
.env("PATH", "")
.output()
.expect("Failed to execute gnd");

assert!(
!output.status.success(),
"gnd indexer should fail when graph-indexer is not on $PATH"
);

let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("graph-indexer") && stderr.contains("not found"),
"Error should mention graph-indexer not found. Got:\n{stderr}"
);
assert!(
stderr.contains("indexer-cli"),
"Error should mention indexer-cli install instructions. Got:\n{stderr}"
);
}

#[test]
fn test_indexer_clap_help() {
let gnd = verify_gnd_binary();

// `--help` is intercepted by clap, not forwarded to graph-indexer.
let output = Command::new(&gnd)
.args(["indexer", "--help"])
.env("PATH", "")
.output()
.expect("Failed to execute gnd");

assert!(output.status.success(), "gnd indexer --help should succeed");

let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("indexer-cli"),
"Help should mention indexer-cli. Got:\n{stdout}"
);
assert!(
stdout.contains("graph-indexer"),
"Help should mention graph-indexer. Got:\n{stdout}"
);
}

// ============================================================================
// gnd init tests
// ============================================================================
Expand Down
Loading