diff --git a/rpc/info.go b/rpc/info.go new file mode 100644 index 0000000..c3be527 --- /dev/null +++ b/rpc/info.go @@ -0,0 +1,58 @@ +// Copyright (c) 2017-2026 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// SPDX-License-Identifier: EUPL-1.2 + +package rpc + +import "fmt" + +// GetInfo returns the daemon status. +// Uses flags=0 for the cheapest query (no expensive calculations). +func (c *Client) GetInfo() (*DaemonInfo, error) { + params := struct { + Flags uint64 `json:"flags"` + }{Flags: 0} + var resp struct { + DaemonInfo + Status string `json:"status"` + } + if err := c.call("getinfo", params, &resp); err != nil { + return nil, err + } + if resp.Status != "OK" { + return nil, fmt.Errorf("getinfo: status %q", resp.Status) + } + return &resp.DaemonInfo, nil +} + +// GetHeight returns the current blockchain height. +// Uses the legacy /getheight endpoint (not available via /json_rpc). +func (c *Client) GetHeight() (uint64, error) { + var resp struct { + Height uint64 `json:"height"` + Status string `json:"status"` + } + if err := c.legacyCall("/getheight", struct{}{}, &resp); err != nil { + return 0, err + } + if resp.Status != "OK" { + return 0, fmt.Errorf("getheight: status %q", resp.Status) + } + return resp.Height, nil +} + +// GetBlockCount returns the total number of blocks (height of top block + 1). +func (c *Client) GetBlockCount() (uint64, error) { + var resp struct { + Count uint64 `json:"count"` + Status string `json:"status"` + } + if err := c.call("getblockcount", struct{}{}, &resp); err != nil { + return 0, err + } + if resp.Status != "OK" { + return 0, fmt.Errorf("getblockcount: status %q", resp.Status) + } + return resp.Count, nil +} diff --git a/rpc/info_test.go b/rpc/info_test.go new file mode 100644 index 0000000..e04a560 --- /dev/null +++ b/rpc/info_test.go @@ -0,0 +1,100 @@ +// Copyright (c) 2017-2026 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// SPDX-License-Identifier: EUPL-1.2 + +package rpc + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "testing" +) + +func TestGetInfo_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(jsonRPCResponse{ + JSONRPC: "2.0", + ID: json.RawMessage(`"0"`), + Result: json.RawMessage(`{ + "height": 6300, + "tx_count": 12345, + "tx_pool_size": 3, + "outgoing_connections_count": 8, + "incoming_connections_count": 4, + "synchronized_connections_count": 7, + "daemon_network_state": 2, + "pow_difficulty": 1000000, + "block_reward": 1000000000000, + "default_fee": 10000000000, + "minimum_fee": 10000000000, + "last_block_hash": "abc123", + "total_coins": "17500000000000000000", + "pos_allowed": true, + "status": "OK" + }`), + }) + })) + defer srv.Close() + + c := NewClient(srv.URL) + info, err := c.GetInfo() + if err != nil { + t.Fatalf("GetInfo: %v", err) + } + if info.Height != 6300 { + t.Errorf("height: got %d, want 6300", info.Height) + } + if info.TxCount != 12345 { + t.Errorf("tx_count: got %d, want 12345", info.TxCount) + } + if info.BlockReward != 1000000000000 { + t.Errorf("block_reward: got %d, want 1000000000000", info.BlockReward) + } + if !info.PosAllowed { + t.Error("pos_allowed: got false, want true") + } +} + +func TestGetHeight_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/getheight" { + t.Errorf("path: got %s, want /getheight", r.URL.Path) + } + w.Header().Set("Content-Type", "application/json") + w.Write([]byte(`{"height":6300,"status":"OK"}`)) + })) + defer srv.Close() + + c := NewClient(srv.URL) + height, err := c.GetHeight() + if err != nil { + t.Fatalf("GetHeight: %v", err) + } + if height != 6300 { + t.Errorf("height: got %d, want 6300", height) + } +} + +func TestGetBlockCount_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(jsonRPCResponse{ + JSONRPC: "2.0", + ID: json.RawMessage(`"0"`), + Result: json.RawMessage(`{"count":6301,"status":"OK"}`), + }) + })) + defer srv.Close() + + c := NewClient(srv.URL) + count, err := c.GetBlockCount() + if err != nil { + t.Fatalf("GetBlockCount: %v", err) + } + if count != 6301 { + t.Errorf("count: got %d, want 6301", count) + } +}