diff --git a/antd-js/README.md b/antd-js/README.md index b7c63c2..a1533a1 100644 --- a/antd-js/README.md +++ b/antd-js/README.md @@ -56,7 +56,7 @@ All methods are `async` and return Promises. | Method | Returns | Description | |--------|---------|-------------| -| `health()` | `HealthStatus` | Check daemon health and network status | +| `health()` | `HealthStatus` | Check daemon health — also reports antd version, EVM network, uptime, build commit, and payment contract addresses (antd ≥ 0.4.0) | ### Data diff --git a/antd-js/src/models.ts b/antd-js/src/models.ts index fb9d8aa..0786f38 100644 --- a/antd-js/src/models.ts +++ b/antd-js/src/models.ts @@ -1,7 +1,20 @@ -/** Health check result from the antd daemon. */ +/** + * 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 can still be constructed from the response of + * an older daemon that doesn't report them. + */ export interface HealthStatus { ok: boolean; network: string; // "default", "local", "alpha" + version: string; // antd crate version, e.g. "0.4.0" + evmNetwork: string; // "arbitrum-one", "arbitrum-sepolia", "local", "custom" + uptimeSeconds: number; // seconds since the daemon process started + buildCommit: string; // short git SHA, "" if unknown + paymentTokenAddress: string; // "" if unconfigured + paymentVaultAddress: string; // "" if unconfigured } /** Result of a put/create operation. */ diff --git a/antd-js/src/rest-client.test.ts b/antd-js/src/rest-client.test.ts index ff836a8..0d7fc7c 100644 --- a/antd-js/src/rest-client.test.ts +++ b/antd-js/src/rest-client.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; -import { RestClient } from "./rest-client.js"; +import { healthStatusFromJson, RestClient } from "./rest-client.js"; import { NotFoundError, BadRequestError, @@ -42,7 +42,16 @@ const routes: Route[] = [ { method: "GET", match: (p) => p === "/health", - respond: () => jsonResponse(200, { status: "ok", network: "local" }), + respond: () => jsonResponse(200, { + 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 public PUT @@ -226,9 +235,31 @@ describe("RestClient", () => { // ---- Health ---- describe("health()", () => { - it("returns ok: true and network name", async () => { + it("returns ok, network, and all 6 diagnostic fields", async () => { const result = await client.health(); - expect(result).toEqual({ ok: true, network: "local" }); + expect(result).toEqual({ + ok: true, + network: "local", + version: "0.4.0", + evmNetwork: "local", + uptimeSeconds: 42, + buildCommit: "abcdef123456", + paymentTokenAddress: "0xtoken", + paymentVaultAddress: "0xvault", + }); + }); + + it("defaults diagnostic fields to empty when talking to a pre-0.4.0 daemon", () => { + // Helper-level regression: older daemons reply with just {status, network}. + const status = healthStatusFromJson({ status: "ok", network: "default" }); + expect(status.ok).toBe(true); + expect(status.network).toBe("default"); + expect(status.version).toBe(""); + expect(status.evmNetwork).toBe(""); + expect(status.uptimeSeconds).toBe(0); + expect(status.buildCommit).toBe(""); + expect(status.paymentTokenAddress).toBe(""); + expect(status.paymentVaultAddress).toBe(""); }); }); diff --git a/antd-js/src/rest-client.ts b/antd-js/src/rest-client.ts index 4f3dd47..cf39511 100644 --- a/antd-js/src/rest-client.ts +++ b/antd-js/src/rest-client.ts @@ -14,6 +14,34 @@ import type { WalletBalance, } from "./models.js"; +/** Wire shape of the antd /health response. All diagnostic fields are + * optional so we can still parse responses from a pre-0.4.0 daemon. */ +interface HealthJson { + status?: string; + network?: string; + version?: string; + evm_network?: string; + uptime_seconds?: number; + build_commit?: string; + payment_token_address?: string; + payment_vault_address?: string; +} + +/** Convert a /health JSON response to a typed HealthStatus. Diagnostic fields + * default to empty/zero when talking to a pre-0.4.0 daemon. */ +export function healthStatusFromJson(j: HealthJson): HealthStatus { + return { + ok: j.status === "ok", + network: j.network ?? "unknown", + version: j.version ?? "", + evmNetwork: j.evm_network ?? "", + uptimeSeconds: j.uptime_seconds ?? 0, + buildCommit: j.build_commit ?? "", + paymentTokenAddress: j.payment_token_address ?? "", + paymentVaultAddress: j.payment_vault_address ?? "", + }; +} + /** Options for creating a REST client. */ export interface RestClientOptions { /** Base URL of the antd daemon. Defaults to "http://localhost:8082". */ @@ -131,8 +159,8 @@ export class RestClient { // ---- Health ---- async health(): Promise { - const j = await this.getJson<{ status: string; network: string }>("/health"); - return { ok: j.status === "ok", network: j.network ?? "unknown" }; + const j = await this.getJson("/health"); + return healthStatusFromJson(j); } // ---- Data ----