From cc4134b8293fe47f604ae9d0a79074c6bb536c9e Mon Sep 17 00:00:00 2001 From: Christopher Tarry Date: Tue, 17 Dec 2024 17:47:10 -0500 Subject: [PATCH] add api endpoint --- api/client.go | 6 ++++ api/server.go | 28 +++++++++++++++ explorer/types.go | 91 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 113 insertions(+), 12 deletions(-) diff --git a/api/client.go b/api/client.go index 9316bdc..7936d54 100644 --- a/api/client.go +++ b/api/client.go @@ -264,3 +264,9 @@ func (c *Client) Search(id types.Hash256) (resp explorer.SearchType, err error) err = c.c.GET(fmt.Sprintf("/search/%s", id.String()), &resp) return } + +// HostsList searches the hosts by the given criteria. +func (c *Client) HostsList(params explorer.HostQuery, sortBy explorer.HostSortColumn, dir explorer.HostSortDir, offset, limit uint64) (resp []explorer.Host, err error) { + err = c.c.POST(fmt.Sprintf("/hosts/list?sort=%s&dir=%s&offset=%d&limit=%d", sortBy, dir, offset, limit), params, &resp) + return +} diff --git a/api/server.go b/api/server.go index 597350f..ba5c01e 100644 --- a/api/server.go +++ b/api/server.go @@ -71,6 +71,7 @@ type ( Search(id types.Hash256) (explorer.SearchType, error) Hosts(pks []types.PublicKey) ([]explorer.Host, error) + QueryHosts(params explorer.HostQuery, sortBy explorer.HostSortColumn, dir explorer.HostSortDir, offset, limit uint64) ([]explorer.Host, error) } ) @@ -628,6 +629,31 @@ func (s *server) pubkeyHostHandler(jc jape.Context) { jc.Encode(hosts[0]) } +func (s *server) hostsListHandler(jc jape.Context) { + var params explorer.HostQuery + if jc.Decode(¶ms) != nil { + return + } + + limit := uint64(100) + offset := uint64(0) + if jc.DecodeForm("limit", &limit) != nil || jc.DecodeForm("offset", &offset) != nil { + return + } + + dir := explorer.HostSortAsc + sortBy := explorer.HostSortDateCreated + if jc.DecodeForm("dir", &dir) != nil || jc.DecodeForm("sort", &sortBy) != nil { + return + } + + hosts, err := s.e.QueryHosts(params, sortBy, dir, offset, limit) + if jc.Check("failed to query hosts", err) != nil { + return + } + jc.Encode(hosts) +} + func (s *server) searchIDHandler(jc jape.Context) { const maxLen = len(types.Hash256{}) @@ -709,6 +735,8 @@ func NewServer(e Explorer, cm ChainManager, s Syncer) http.Handler { "GET /metrics/block/:id": srv.blocksMetricsIDHandler, "GET /metrics/host": srv.hostMetricsHandler, + "POST /hosts/list": srv.hostsListHandler, + "GET /search/:id": srv.searchIDHandler, }) } diff --git a/explorer/types.go b/explorer/types.go index c6af5cd..dbdbdea 100644 --- a/explorer/types.go +++ b/explorer/types.go @@ -3,6 +3,7 @@ package explorer import ( "encoding/json" "errors" + "fmt" "time" "go.sia.tech/core/consensus" @@ -378,23 +379,89 @@ const ( HostSortDesc HostSortDir = "DESC" ) +// MarshalText implements encoding.TextMarshaler. +func (h HostSortDir) MarshalText() ([]byte, error) { + switch h { + case HostSortAsc, HostSortDesc: + return []byte(h), nil + default: + return nil, fmt.Errorf("invalid HostSortDir: %s", h) + } +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (h *HostSortDir) UnmarshalText(data []byte) error { + switch string(data) { + case string(HostSortAsc): + *h = HostSortAsc + case string(HostSortDesc): + *h = HostSortDesc + default: + return fmt.Errorf("invalid HostSortDir: %s", data) + } + return nil +} + // HostSortColumn represents the sorting column for host filtering. -type HostSortColumn int +type HostSortColumn string const ( - HostSortDateCreated = iota - HostSortNetAddress - HostSortPublicKey - HostSortAcceptingContracts - HostSortUptime - HostSortStoragePrice - HostSortContractPrice - HostSortDownloadPrice - HostSortUploadPrice - HostSortUsedStorage - HostSortTotalStorage + HostSortDateCreated HostSortColumn = "date_created" + HostSortNetAddress HostSortColumn = "net_address" + HostSortPublicKey HostSortColumn = "public_key" + HostSortAcceptingContracts HostSortColumn = "accepting_contracts" + HostSortUptime HostSortColumn = "uptime" + HostSortStoragePrice HostSortColumn = "storage_price" + HostSortContractPrice HostSortColumn = "contract_price" + HostSortDownloadPrice HostSortColumn = "download_price" + HostSortUploadPrice HostSortColumn = "upload_price" + HostSortUsedStorage HostSortColumn = "used_storage" + HostSortTotalStorage HostSortColumn = "total_storage" ) +// MarshalText implements encoding.TextMarshaler. +func (h HostSortColumn) MarshalText() ([]byte, error) { + switch h { + case HostSortDateCreated, HostSortNetAddress, HostSortPublicKey, HostSortAcceptingContracts, + HostSortUptime, HostSortStoragePrice, HostSortContractPrice, HostSortDownloadPrice, + HostSortUploadPrice, HostSortUsedStorage, HostSortTotalStorage: + return []byte(h), nil + default: + return nil, fmt.Errorf("invalid HostSortColumn: %s", h) + } +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (h *HostSortColumn) UnmarshalText(data []byte) error { + switch string(data) { + case string(HostSortDateCreated): + *h = HostSortDateCreated + case string(HostSortNetAddress): + *h = HostSortNetAddress + case string(HostSortPublicKey): + *h = HostSortPublicKey + case string(HostSortAcceptingContracts): + *h = HostSortAcceptingContracts + case string(HostSortUptime): + *h = HostSortUptime + case string(HostSortStoragePrice): + *h = HostSortStoragePrice + case string(HostSortContractPrice): + *h = HostSortContractPrice + case string(HostSortDownloadPrice): + *h = HostSortDownloadPrice + case string(HostSortUploadPrice): + *h = HostSortUploadPrice + case string(HostSortUsedStorage): + *h = HostSortUsedStorage + case string(HostSortTotalStorage): + *h = HostSortTotalStorage + default: + return fmt.Errorf("invalid HostSortColumn: %s", data) + } + return nil +} + // HostQuery defines the filter and sort parameters for querying hosts. type HostQuery struct { V2 bool