Skip to content
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project are documented here.
This project adheres to [Semantic Versioning](https://semver.org) and
[Conventional Commits](https://www.conventionalcommits.org).

## [0.18.0] - 2026-07-20

### Features
- **cli:** Add `store-status <store_id>` subcommand — reports a store's aggregate on-chain status (live/melted/not-found, confirmations, live root, owner, coin id) by consuming the fail-closed `dig_store::get_store_status` via a coinset-backed `dig_chainsource_interface::ChainSource` adapter; supports `--json`, `--confirmation-target`, and a `--coinset-url` / `$DIG_COINSET_URL` endpoint override (#1349)

## [0.17.2] - 2026-07-20

### Chores
Expand Down
82 changes: 76 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ exclude = ["crates/digstore-prover/guest", "crates/dig-client-wasm"]

[workspace.package]
edition = "2021"
version = "0.17.2"
version = "0.18.0"
license = "GPL-2.0-only"

[workspace.dependencies]
Expand Down
9 changes: 9 additions & 0 deletions crates/digstore-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ clap_mangen = "0.2"
anyhow = "1"
thiserror = "1"
chia-protocol = "0.26"
# `store-status` (#1349): the fail-closed on-chain store-status aggregator lives in the `dig-store`
# LIBRARY crate (NC-9, triple-gated); this CLI is a thin consumer of `dig_store::get_store_status`,
# reading through a coinset-backed adapter over the canonical `dig_chainsource_interface::ChainSource`
# trait. NEVER re-implement the status/lineage logic here.
dig-store = "0.5"
dig-chainsource-interface = "0.1"
async-trait = "0.1"
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros", "net", "time"] }
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json"] }
Expand Down Expand Up @@ -69,3 +75,6 @@ axum = "0.7"
assert_cmd = "2"
predicates = "3"
tempfile = "3"
# The in-memory canonical ChainSource for exercising `get_store_status` (Live/Melted/NotFound +
# fail-closed) without a network, and the adapter's transport-mapping tests.
dig-chainsource-interface = { version = "0.1", features = ["testing"] }
61 changes: 61 additions & 0 deletions crates/digstore-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,32 @@ pub enum Command {
Did(DidArgs),
/// Make, take, and inspect Chia offers (XCH/CAT trades).
Offer(OfferArgs),
/// Show a store's aggregate ON-CHAIN status by store id (live/melted/not-found,
/// confirmations, live root, owner, coin id). Reads Chia chain state via coinset;
/// needs no local store. Distinct from `status` (the local working-tree view).
#[command(name = "store-status")]
StoreStatus(StoreStatusArgs),
}

/// Arguments for `store-status` (#1349) — a read-only on-chain status lookup by store id.
#[derive(Debug, Args)]
#[command(
after_help = "Reads the store's on-chain status from Chia chain state (coin records + spends) \
via coinset — NOT the dig-node content ladder. Point at a custom Chia read endpoint with \
--coinset-url or $DIG_COINSET_URL.\n\nEXAMPLES:\n dig-store store-status \
<64-hex-store-id>\n dig-store store-status urn:dig:chia:<store-id> --json\n dig-store store-status \
<store-id> --confirmation-target 16 --coinset-url https://api.coinset.org"
)]
pub struct StoreStatusArgs {
/// The store id: 32-byte hex (with or without `0x`), or a `urn:dig:chia:<store_id>` URN.
pub store_id: String,
/// Confirmation depth (blocks under the peak) at which the live tip is treated as settled.
#[arg(long, default_value_t = dig_store::DEFAULT_CONFIRMATION_TARGET)]
pub confirmation_target: u32,
/// Custom coinset read endpoint (overrides `$DIG_COINSET_URL` and the default). This surface
/// reads raw Chia chain state, so it uses a coinset endpoint, not the §5.3 node ladder.
#[arg(long)]
pub coinset_url: Option<String>,
}

// ===========================================================================
Expand Down Expand Up @@ -1310,6 +1336,41 @@ mod tests {
}
}

#[test]
fn parses_store_status_defaults_and_flags() {
// Defaults: confirmation-target from the library const, no coinset override.
let cli = Cli::try_parse_from(["digstore", "store-status", "abcd"]).unwrap();
match cli.command {
Command::StoreStatus(a) => {
assert_eq!(a.store_id, "abcd");
assert_eq!(
a.confirmation_target,
dig_store::DEFAULT_CONFIRMATION_TARGET
);
assert!(a.coinset_url.is_none());
}
_ => panic!("expected store-status"),
}
// Flags parse.
let cli = Cli::try_parse_from([
"digstore",
"store-status",
"urn:dig:chia:ab",
"--confirmation-target",
"16",
"--coinset-url",
"https://example.org",
])
.unwrap();
match cli.command {
Command::StoreStatus(a) => {
assert_eq!(a.confirmation_target, 16);
assert_eq!(a.coinset_url.as_deref(), Some("https://example.org"));
}
_ => panic!("expected store-status"),
}
}

#[test]
fn parses_cat_urn() {
let cli = Cli::try_parse_from(["digstore", "cat", "urn:dig:chia:abcd/readme"]).unwrap();
Expand Down
6 changes: 6 additions & 0 deletions crates/digstore-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub mod serve;
pub mod setup;
pub mod staged;
pub mod status;
pub mod store_status;
pub mod stores;
pub mod unstage;
pub mod update;
Expand Down Expand Up @@ -222,6 +223,10 @@ pub fn dispatch(cli: Cli) -> Result<(), CliError> {
let ctx = CliContext::workspace_only(workspace_dir, cli.json, cli.verbose);
return balance::run(&ctx, &ui);
}
// `store-status` reads a store's on-chain status by store id alone — it needs no local
// store/workspace (like `did`/`offer`), and reads raw Chia chain state via coinset (NOT
// the §5.3 dig-node content ladder). See `store_status` for the endpoint resolution.
Command::StoreStatus(a) => return store_status::run(&ui, a),
_ => {}
}

Expand Down Expand Up @@ -317,6 +322,7 @@ pub fn dispatch(cli: Cli) -> Result<(), CliError> {
| Command::Did(_)
| Command::Offer(_)
| Command::Collection(_)
| Command::StoreStatus(_)
| Command::Cat(_) => {
unreachable!("handled above")
}
Expand Down
Loading
Loading