149 lines
4.6 KiB
Go
149 lines
4.6 KiB
Go
// Copyright (c) 2017-2026 Lethean (https://lt.hn)
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
package node
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
// info, err := node.GetChainInfo(LetheanMainnetDaemon)
|
|
// pools := node.DiscoverPools(LetheanTestnetDaemon)
|
|
const (
|
|
LetheanTestnetDaemon = "http://127.0.0.1:46941"
|
|
LetheanMainnetDaemon = "http://127.0.0.1:36941"
|
|
LetheanTestnetPool = "stratum+tcp://pool.lthn.io:5555"
|
|
LetheanMainnetPool = "stratum+tcp://pool.lthn.io:3333"
|
|
)
|
|
|
|
// info, err := node.GetChainInfo("http://127.0.0.1:46941")
|
|
// if info.Synced { log("height:", info.Height, "aliases:", info.AliasCount) }
|
|
type ChainInfo struct {
|
|
Height uint64 `json:"height"`
|
|
AliasCount int `json:"alias_count"`
|
|
Synced bool `json:"synced"`
|
|
PoolSize int `json:"tx_pool_size"`
|
|
Difficulty uint64 `json:"difficulty"`
|
|
}
|
|
|
|
// pools := node.DiscoverPools("http://127.0.0.1:46941")
|
|
// for _, pool := range pools { log(pool.Name, pool.Endpoint) }
|
|
type PoolGateway struct {
|
|
Name string `json:"name"`
|
|
Address string `json:"address"`
|
|
Capabilities string `json:"caps"`
|
|
Endpoint string `json:"endpoint"`
|
|
}
|
|
|
|
// info, err := node.GetChainInfo("http://127.0.0.1:46941")
|
|
// if err == nil && info.Synced { log("chain height:", info.Height) }
|
|
func GetChainInfo(daemonURL string) (*ChainInfo, error) {
|
|
requestBody := `{"jsonrpc":"2.0","id":"0","method":"getinfo","params":{}}`
|
|
response, err := http.Post(daemonURL+"/json_rpc", "application/json", bytes.NewReader([]byte(requestBody)))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer response.Body.Close()
|
|
responseBody, _ := io.ReadAll(response.Body)
|
|
|
|
var rpcResponse struct {
|
|
Result ChainInfo `json:"result"`
|
|
}
|
|
if err := UnmarshalJSON(responseBody, &rpcResponse); err != nil {
|
|
return nil, err
|
|
}
|
|
rpcResponse.Result.Synced = rpcResponse.Result.Height > 0
|
|
return &rpcResponse.Result, nil
|
|
}
|
|
|
|
// pools := node.DiscoverPools("http://127.0.0.1:46941")
|
|
// for _, pool := range pools { log(pool.Name, pool.Endpoint) }
|
|
func DiscoverPools(daemonURL string) []PoolGateway {
|
|
requestBody := `{"jsonrpc":"2.0","id":"0","method":"get_all_alias_details","params":{}}`
|
|
response, err := http.Post(daemonURL+"/json_rpc", "application/json", bytes.NewReader([]byte(requestBody)))
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer response.Body.Close()
|
|
responseBody, _ := io.ReadAll(response.Body)
|
|
|
|
var rpcResponse struct {
|
|
Result struct {
|
|
Aliases []struct {
|
|
Alias string `json:"alias"`
|
|
Address string `json:"address"`
|
|
Comment string `json:"comment"`
|
|
} `json:"aliases"`
|
|
} `json:"result"`
|
|
}
|
|
UnmarshalJSON(responseBody, &rpcResponse) //nolint:errcheck
|
|
|
|
var pools []PoolGateway
|
|
for _, alias := range rpcResponse.Result.Aliases {
|
|
if !bytes.Contains([]byte(alias.Comment), []byte("pool")) {
|
|
continue
|
|
}
|
|
commentFields := parseComment(alias.Comment)
|
|
pools = append(pools, PoolGateway{
|
|
Name: alias.Alias,
|
|
Address: alias.Address,
|
|
Capabilities: commentFields["cap"],
|
|
Endpoint: "stratum+tcp://" + alias.Alias + ".lthn:5555",
|
|
})
|
|
}
|
|
return pools
|
|
}
|
|
|
|
// gateways := node.DiscoverGateways("http://127.0.0.1:46941")
|
|
// for _, gateway := range gateways { log(gateway.Name, gateway.Endpoint) }
|
|
func DiscoverGateways(daemonURL string) []PoolGateway {
|
|
requestBody := `{"jsonrpc":"2.0","id":"0","method":"get_all_alias_details","params":{}}`
|
|
response, err := http.Post(daemonURL+"/json_rpc", "application/json", bytes.NewReader([]byte(requestBody)))
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer response.Body.Close()
|
|
responseBody, _ := io.ReadAll(response.Body)
|
|
|
|
var rpcResponse struct {
|
|
Result struct {
|
|
Aliases []struct {
|
|
Alias string `json:"alias"`
|
|
Address string `json:"address"`
|
|
Comment string `json:"comment"`
|
|
} `json:"aliases"`
|
|
} `json:"result"`
|
|
}
|
|
UnmarshalJSON(responseBody, &rpcResponse) //nolint:errcheck
|
|
|
|
var gateways []PoolGateway
|
|
for _, alias := range rpcResponse.Result.Aliases {
|
|
if !bytes.Contains([]byte(alias.Comment), []byte("type=gateway")) {
|
|
continue
|
|
}
|
|
commentFields := parseComment(alias.Comment)
|
|
gateways = append(gateways, PoolGateway{
|
|
Name: alias.Alias,
|
|
Address: alias.Address,
|
|
Capabilities: commentFields["cap"],
|
|
Endpoint: alias.Alias + ".lthn",
|
|
})
|
|
}
|
|
return gateways
|
|
}
|
|
|
|
// parsed := parseComment("cap=pool;endpoint=stratum+tcp://pool.lthn.io:3333")
|
|
// parsed["cap"] // "pool"
|
|
// parsed["endpoint"] // "stratum+tcp://pool.lthn.io:3333"
|
|
func parseComment(comment string) map[string]string {
|
|
fields := make(map[string]string)
|
|
for _, segment := range bytes.Split([]byte(comment), []byte(";")) {
|
|
separatorIndex := bytes.IndexByte(segment, '=')
|
|
if separatorIndex > 0 {
|
|
fields[string(segment[:separatorIndex])] = string(segment[separatorIndex+1:])
|
|
}
|
|
}
|
|
return fields
|
|
}
|