From 0e3f84eb5f6802a32d521a6a186663794f273294 Mon Sep 17 00:00:00 2001 From: Nic-dorman Date: Tue, 5 May 2026 10:10:01 +0100 Subject: [PATCH 1/2] feat(antd-kotlin): expose new HealthStatus diagnostic fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors antd-go v0.5.0 / antd-py: HealthStatus now carries version, evmNetwork, uptimeSeconds, buildCommit, paymentTokenAddress, and paymentVaultAddress. All have data-class default values ("" / 0) so the type stays constructable with just (ok, network) and pre-0.4.0 daemons keep deserializing. REST routes through HealthResponseDto.toHealthStatus() — the DTO gains six nullable serial-named properties so kotlinx.serialization tolerates either old or new daemon shapes. gRPC pulls each field from the regenerated HealthCheckResponse proto. Proto stubs regenerate automatically via the protobuf-gradle-plugin during gradle build. RestClientTest mock fixture extended to populate all 6 fields; existing assertion expanded; new HealthStatus-defaults regression test exercises the (ok, network)-only constructor. Part of #37. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../kotlin/com/autonomi/sdk/AntdGrpcClient.kt | 11 +++++- .../kotlin/com/autonomi/sdk/AntdRestClient.kt | 3 +- .../main/kotlin/com/autonomi/sdk/Models.kt | 37 ++++++++++++++++++- .../lib/src/main/proto/antd/v1/chunks.proto | 1 + .../lib/src/main/proto/antd/v1/common.proto | 1 + .../lib/src/main/proto/antd/v1/data.proto | 1 + .../lib/src/main/proto/antd/v1/events.proto | 1 + .../lib/src/main/proto/antd/v1/files.proto | 1 + .../lib/src/main/proto/antd/v1/health.proto | 7 ++++ .../kotlin/com/autonomi/sdk/RestClientTest.kt | 21 ++++++++++- 10 files changed, 78 insertions(+), 6 deletions(-) diff --git a/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/AntdGrpcClient.kt b/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/AntdGrpcClient.kt index ae9b798..63a55fa 100644 --- a/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/AntdGrpcClient.kt +++ b/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/AntdGrpcClient.kt @@ -35,7 +35,16 @@ class AntdGrpcClient(target: String = "localhost:50051") : IAntdClient { override suspend fun health(): HealthStatus = try { val resp = healthStub.check(healthCheckRequest { }) - HealthStatus(resp.status == "ok", resp.network.ifEmpty { "unknown" }) + HealthStatus( + ok = resp.status == "ok", + network = resp.network.ifEmpty { "unknown" }, + version = resp.version, + evmNetwork = resp.evmNetwork, + uptimeSeconds = resp.uptimeSeconds.toULong(), + buildCommit = resp.buildCommit, + paymentTokenAddress = resp.paymentTokenAddress, + paymentVaultAddress = resp.paymentVaultAddress, + ) } catch (ex: StatusRuntimeException) { if (ex.status.code == Status.Code.UNAVAILABLE) { HealthStatus(false, "unknown") diff --git a/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/AntdRestClient.kt b/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/AntdRestClient.kt index b021799..0601a7a 100644 --- a/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/AntdRestClient.kt +++ b/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/AntdRestClient.kt @@ -92,8 +92,7 @@ class AntdRestClient( // ── Health ── override suspend fun health(): HealthStatus = try { - val resp = getJson("/health") - HealthStatus(resp.status == "ok", resp.network ?: "unknown") + getJson("/health").toHealthStatus() } catch (_: Exception) { HealthStatus(false, "unknown") } diff --git a/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/Models.kt b/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/Models.kt index c6bd322..a193cd5 100644 --- a/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/Models.kt +++ b/antd-kotlin/lib/src/main/kotlin/com/autonomi/sdk/Models.kt @@ -3,8 +3,24 @@ package com.autonomi.sdk import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -/** Health check result from the antd daemon. */ -data class HealthStatus(val ok: Boolean, val network: String) +/** + * Health check result from the antd daemon. + * + * The diagnostic fields ([version], [evmNetwork], [uptimeSeconds], + * [buildCommit], [paymentTokenAddress], [paymentVaultAddress]) were added in + * antd 0.4.0. They default to "" / 0 so the type stays constructable from a + * pre-0.4.0 daemon's response. + */ +data class HealthStatus( + val ok: Boolean, + val network: String, + val version: String = "", + val evmNetwork: String = "", + val uptimeSeconds: ULong = 0u, + val buildCommit: String = "", + val paymentTokenAddress: String = "", + val paymentVaultAddress: String = "", +) /** Result of a put/create operation that stores data on the network. */ data class PutResult(val cost: String, val address: String) @@ -77,6 +93,23 @@ data class UploadCostEstimate( internal data class HealthResponseDto( val status: String? = null, val network: String? = null, + val version: String? = null, + @SerialName("evm_network") val evmNetwork: String? = null, + @SerialName("uptime_seconds") val uptimeSeconds: ULong? = null, + @SerialName("build_commit") val buildCommit: String? = null, + @SerialName("payment_token_address") val paymentTokenAddress: String? = null, + @SerialName("payment_vault_address") val paymentVaultAddress: String? = null, +) + +internal fun HealthResponseDto.toHealthStatus(): HealthStatus = HealthStatus( + ok = status == "ok", + network = network ?: "unknown", + version = version ?: "", + evmNetwork = evmNetwork ?: "", + uptimeSeconds = uptimeSeconds ?: 0u, + buildCommit = buildCommit ?: "", + paymentTokenAddress = paymentTokenAddress ?: "", + paymentVaultAddress = paymentVaultAddress ?: "", ) @Serializable diff --git a/antd-kotlin/lib/src/main/proto/antd/v1/chunks.proto b/antd-kotlin/lib/src/main/proto/antd/v1/chunks.proto index 66443f7..09bb9b4 100644 --- a/antd-kotlin/lib/src/main/proto/antd/v1/chunks.proto +++ b/antd-kotlin/lib/src/main/proto/antd/v1/chunks.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package antd.v1; option csharp_namespace = "Antd.V1"; +option go_package = "github.com/WithAutonomi/ant-sdk/antd-go/proto/antd/v1;v1"; import "antd/v1/common.proto"; diff --git a/antd-kotlin/lib/src/main/proto/antd/v1/common.proto b/antd-kotlin/lib/src/main/proto/antd/v1/common.proto index 9646083..f4f44b8 100644 --- a/antd-kotlin/lib/src/main/proto/antd/v1/common.proto +++ b/antd-kotlin/lib/src/main/proto/antd/v1/common.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package antd.v1; option csharp_namespace = "Antd.V1"; +option go_package = "github.com/WithAutonomi/ant-sdk/antd-go/proto/antd/v1;v1"; message Cost { string atto_tokens = 1; // storage cost in atto tokens as string diff --git a/antd-kotlin/lib/src/main/proto/antd/v1/data.proto b/antd-kotlin/lib/src/main/proto/antd/v1/data.proto index 2b1ea69..79f041c 100644 --- a/antd-kotlin/lib/src/main/proto/antd/v1/data.proto +++ b/antd-kotlin/lib/src/main/proto/antd/v1/data.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package antd.v1; option csharp_namespace = "Antd.V1"; +option go_package = "github.com/WithAutonomi/ant-sdk/antd-go/proto/antd/v1;v1"; import "antd/v1/common.proto"; diff --git a/antd-kotlin/lib/src/main/proto/antd/v1/events.proto b/antd-kotlin/lib/src/main/proto/antd/v1/events.proto index 5781714..cf498e3 100644 --- a/antd-kotlin/lib/src/main/proto/antd/v1/events.proto +++ b/antd-kotlin/lib/src/main/proto/antd/v1/events.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package antd.v1; option csharp_namespace = "Antd.V1"; +option go_package = "github.com/WithAutonomi/ant-sdk/antd-go/proto/antd/v1;v1"; service EventService { rpc Subscribe(SubscribeRequest) returns (stream ClientEventProto); diff --git a/antd-kotlin/lib/src/main/proto/antd/v1/files.proto b/antd-kotlin/lib/src/main/proto/antd/v1/files.proto index 57d4958..6ad6a25 100644 --- a/antd-kotlin/lib/src/main/proto/antd/v1/files.proto +++ b/antd-kotlin/lib/src/main/proto/antd/v1/files.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package antd.v1; option csharp_namespace = "Antd.V1"; +option go_package = "github.com/WithAutonomi/ant-sdk/antd-go/proto/antd/v1;v1"; import "antd/v1/common.proto"; diff --git a/antd-kotlin/lib/src/main/proto/antd/v1/health.proto b/antd-kotlin/lib/src/main/proto/antd/v1/health.proto index b98c774..35cea5a 100644 --- a/antd-kotlin/lib/src/main/proto/antd/v1/health.proto +++ b/antd-kotlin/lib/src/main/proto/antd/v1/health.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package antd.v1; option csharp_namespace = "Antd.V1"; +option go_package = "github.com/WithAutonomi/ant-sdk/antd-go/proto/antd/v1;v1"; service HealthService { rpc Check(HealthCheckRequest) returns (HealthCheckResponse); @@ -13,4 +14,10 @@ message HealthCheckRequest {} message HealthCheckResponse { string status = 1; // "ok" string network = 2; // "default", "local", "alpha" + string version = 3; // antd crate version (e.g. "0.4.0") + string evm_network = 4; // EVM preset: "arbitrum-one", "arbitrum-sepolia", "local", "custom" + uint64 uptime_seconds = 5; // seconds since process start + string build_commit = 6; // short git SHA, or "" if built outside a git checkout + string payment_token_address = 7; // token contract, or "" if unconfigured + string payment_vault_address = 8; // payment vault contract, or "" if unconfigured } diff --git a/antd-kotlin/lib/src/test/kotlin/com/autonomi/sdk/RestClientTest.kt b/antd-kotlin/lib/src/test/kotlin/com/autonomi/sdk/RestClientTest.kt index d396374..1119c9b 100644 --- a/antd-kotlin/lib/src/test/kotlin/com/autonomi/sdk/RestClientTest.kt +++ b/antd-kotlin/lib/src/test/kotlin/com/autonomi/sdk/RestClientTest.kt @@ -38,7 +38,7 @@ class RestClientTest { // Health if (method == "GET" && path == "/health") { - 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 @@ -116,6 +116,25 @@ class RestClientTest { val status = client.health() assertTrue(status.ok) assertEquals("local", status.network) + assertEquals("0.4.0", status.version) + assertEquals("local", status.evmNetwork) + assertEquals(42UL, status.uptimeSeconds) + assertEquals("abcdef123456", status.buildCommit) + assertEquals("0xtoken", status.paymentTokenAddress) + assertEquals("0xvault", status.paymentVaultAddress) + } + + @Test + fun `HealthStatus defaults stay empty for pre-0_4_0 daemon shape`() { + // Older daemons reply with just status + network; the data class + // defaults populate the diagnostic fields so callers don't NPE. + val s = HealthStatus(ok = true, network = "default") + assertEquals("", s.version) + assertEquals("", s.evmNetwork) + assertEquals(0UL, s.uptimeSeconds) + assertEquals("", s.buildCommit) + assertEquals("", s.paymentTokenAddress) + assertEquals("", s.paymentVaultAddress) } @Test From 72944154af75a76c3f2c14f8a16b0dc98029cbed Mon Sep 17 00:00:00 2001 From: Nic-dorman Date: Tue, 5 May 2026 10:10:19 +0100 Subject: [PATCH 2/2] docs(antd-kotlin): mention new HealthStatus diagnostic fields Co-Authored-By: Claude Opus 4.7 (1M context) --- antd-kotlin/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/antd-kotlin/README.md b/antd-kotlin/README.md index b2f777e..04f1506 100644 --- a/antd-kotlin/README.md +++ b/antd-kotlin/README.md @@ -64,7 +64,7 @@ All methods are `suspend` functions for use with Kotlin coroutines. | Domain | Methods | |---|---| -| **Health** | `health()` | +| **Health** | `health()` returns `HealthStatus` carrying antd version, EVM network, uptime, build commit, and payment contract addresses (antd ≥ 0.4.0) | | **Data** | `dataPutPublic`, `dataGetPublic`, `dataPutPrivate`, `dataGetPrivate`, `dataCost` | | **Chunks** | `chunkPut`, `chunkGet` | | **Files** | `fileUploadPublic`, `fileDownloadPublic`, `dirUploadPublic`, `dirDownloadPublic`, `fileCost` |