diff --git a/antd-java/README.md b/antd-java/README.md index 7c7bbd1..b323bdb 100644 --- a/antd-java/README.md +++ b/antd-java/README.md @@ -90,7 +90,7 @@ All methods throw `AntdException` (or a typed subclass) on failure. | Method | Description | |--------|-------------| -| `health()` | Check daemon status | +| `health()` | Check daemon status — returns `HealthStatus` carrying antd version, EVM network, uptime, build commit, and payment contract addresses (antd ≥ 0.4.0) | ### Data (Immutable) diff --git a/antd-java/src/main/java/com/autonomi/antd/AntdClient.java b/antd-java/src/main/java/com/autonomi/antd/AntdClient.java index 5d08781..9f0e6b3 100644 --- a/antd-java/src/main/java/com/autonomi/antd/AntdClient.java +++ b/antd-java/src/main/java/com/autonomi/antd/AntdClient.java @@ -191,8 +191,24 @@ private static List> listOfMaps(Map m, Strin // ── Health ── public HealthStatus health() { - Map j = doJson("GET", "/health", null); - return new HealthStatus("ok".equals(str(j, "status")), str(j, "network")); + return parseHealthStatus(doJson("GET", "/health", null)); + } + + /** + * Convert a /health JSON response to a typed HealthStatus. Diagnostic + * fields default to empty / 0 when talking to a pre-0.4.0 daemon. Package- + * private so AsyncAntdClient can share the parser. + */ + static HealthStatus parseHealthStatus(Map j) { + return new HealthStatus( + "ok".equals(str(j, "status")), + str(j, "network"), + str(j, "version"), + str(j, "evm_network"), + num(j, "uptime_seconds"), + str(j, "build_commit"), + str(j, "payment_token_address"), + str(j, "payment_vault_address")); } // ── Data (Immutable) ── diff --git a/antd-java/src/main/java/com/autonomi/antd/AsyncAntdClient.java b/antd-java/src/main/java/com/autonomi/antd/AsyncAntdClient.java index 85f0231..9ec4a1e 100644 --- a/antd-java/src/main/java/com/autonomi/antd/AsyncAntdClient.java +++ b/antd-java/src/main/java/com/autonomi/antd/AsyncAntdClient.java @@ -174,7 +174,7 @@ private static List> listOfMaps(Map m, Strin /** Async variant of {@link AntdClient#health()}. */ public CompletableFuture healthAsync() { return doJsonAsync("GET", "/health", null) - .thenApply(j -> new HealthStatus("ok".equals(str(j, "status")), str(j, "network"))); + .thenApply(AntdClient::parseHealthStatus); } // ── Data (Immutable) ── diff --git a/antd-java/src/main/java/com/autonomi/antd/GrpcAntdClient.java b/antd-java/src/main/java/com/autonomi/antd/GrpcAntdClient.java index 5f5ddaa..f230cef 100644 --- a/antd-java/src/main/java/com/autonomi/antd/GrpcAntdClient.java +++ b/antd-java/src/main/java/com/autonomi/antd/GrpcAntdClient.java @@ -155,12 +155,25 @@ private static AntdException mapException(StatusRuntimeException e) { public HealthStatus health() { try { HealthCheckResponse resp = healthStub.check(HealthCheckRequest.getDefaultInstance()); - return new HealthStatus("ok".equals(resp.getStatus()), resp.getNetwork()); + return healthStatusFromGrpc(resp); } catch (StatusRuntimeException e) { throw mapException(e); } } + /** Convert a gRPC HealthCheckResponse into a typed HealthStatus. */ + static HealthStatus healthStatusFromGrpc(HealthCheckResponse resp) { + return new HealthStatus( + "ok".equals(resp.getStatus()), + resp.getNetwork(), + resp.getVersion(), + resp.getEvmNetwork(), + resp.getUptimeSeconds(), + resp.getBuildCommit(), + resp.getPaymentTokenAddress(), + resp.getPaymentVaultAddress()); + } + // ── Data (Immutable) ── /** diff --git a/antd-java/src/main/java/com/autonomi/antd/models/HealthStatus.java b/antd-java/src/main/java/com/autonomi/antd/models/HealthStatus.java index 6dd9dab..31fe77d 100644 --- a/antd-java/src/main/java/com/autonomi/antd/models/HealthStatus.java +++ b/antd-java/src/main/java/com/autonomi/antd/models/HealthStatus.java @@ -3,7 +3,36 @@ /** * Result of a daemon health check. * - * @param ok whether the daemon is healthy - * @param network the network the daemon is connected to + *

The diagnostic fields ({@code version}, {@code evmNetwork}, + * {@code uptimeSeconds}, {@code buildCommit}, {@code paymentTokenAddress}, + * {@code paymentVaultAddress}) were added in antd 0.4.0. They are populated + * with empty strings / 0 when talking to a pre-0.4.0 daemon that doesn't + * report them. + * + * @param ok whether the daemon is healthy + * @param network the network the daemon is connected to + * @param version antd crate version, e.g. "0.4.0"; "" if unknown + * @param evmNetwork "arbitrum-one", "arbitrum-sepolia", "local", "custom" + * @param uptimeSeconds seconds since the daemon process started + * @param buildCommit short git SHA, "" if unknown + * @param paymentTokenAddress payment token contract address, "" if unconfigured + * @param paymentVaultAddress payment vault contract address, "" if unconfigured */ -public record HealthStatus(boolean ok, String network) {} +public record HealthStatus( + boolean ok, + String network, + String version, + String evmNetwork, + long uptimeSeconds, + String buildCommit, + String paymentTokenAddress, + String paymentVaultAddress) { + + /** + * Backward-compatible constructor for callers that only need the original + * two fields. Diagnostic fields default to empty / 0. + */ + public HealthStatus(boolean ok, String network) { + this(ok, network, "", "", 0L, "", "", ""); + } +} diff --git a/antd-java/src/test/java/com/autonomi/antd/AntdClientTest.java b/antd-java/src/test/java/com/autonomi/antd/AntdClientTest.java index 609ccf5..c817396 100644 --- a/antd-java/src/test/java/com/autonomi/antd/AntdClientTest.java +++ b/antd-java/src/test/java/com/autonomi/antd/AntdClientTest.java @@ -47,7 +47,13 @@ public MockResponse dispatch(RecordedRequest request) { // Health if ("GET".equals(method) && "/health".equals(path)) { - return json("{\"status\":\"ok\",\"network\":\"local\"}"); + return json("{\"status\":\"ok\",\"network\":\"local\"," + + "\"version\":\"0.4.0\"," + + "\"evm_network\":\"local\"," + + "\"uptime_seconds\":42," + + "\"build_commit\":\"abcdef123456\"," + + "\"payment_token_address\":\"0xtoken\"," + + "\"payment_vault_address\":\"0xvault\"}"); } // Data put public @@ -125,6 +131,24 @@ void testHealth() { HealthStatus h = client.health(); assertTrue(h.ok()); assertEquals("local", h.network()); + assertEquals("0.4.0", h.version()); + assertEquals("local", h.evmNetwork()); + assertEquals(42L, h.uptimeSeconds()); + assertEquals("abcdef123456", h.buildCommit()); + assertEquals("0xtoken", h.paymentTokenAddress()); + assertEquals("0xvault", h.paymentVaultAddress()); + } + + @Test + void testHealthBackwardCompatConstructor() { + // Pre-0.4.0 callers used new HealthStatus(ok, network); the diagnostic + // fields default to empty so the constructor stays usable. + HealthStatus h = new HealthStatus(true, "default"); + assertTrue(h.ok()); + assertEquals("default", h.network()); + assertEquals("", h.version()); + assertEquals(0L, h.uptimeSeconds()); + assertEquals("", h.paymentTokenAddress()); } @Test diff --git a/antd-java/src/test/java/com/autonomi/antd/GrpcAntdClientTest.java b/antd-java/src/test/java/com/autonomi/antd/GrpcAntdClientTest.java index d2b70c9..162b8e1 100644 --- a/antd-java/src/test/java/com/autonomi/antd/GrpcAntdClientTest.java +++ b/antd-java/src/test/java/com/autonomi/antd/GrpcAntdClientTest.java @@ -98,6 +98,12 @@ public void check(HealthCheckRequest request, HealthCheckResponse.newBuilder() .setStatus("ok") .setNetwork("local") + .setVersion("0.4.0") + .setEvmNetwork("local") + .setUptimeSeconds(42) + .setBuildCommit("abcdef123456") + .setPaymentTokenAddress("0xtoken") + .setPaymentVaultAddress("0xvault") .build()); responseObserver.onCompleted(); } @@ -258,6 +264,12 @@ void testHealth() { HealthStatus h = client.health(); assertTrue(h.ok()); assertEquals("local", h.network()); + assertEquals("0.4.0", h.version()); + assertEquals("local", h.evmNetwork()); + assertEquals(42L, h.uptimeSeconds()); + assertEquals("abcdef123456", h.buildCommit()); + assertEquals("0xtoken", h.paymentTokenAddress()); + assertEquals("0xvault", h.paymentVaultAddress()); } // --- Data (Immutable) ---