From 8a0e823d91e92c3cd30302716717065d7eca30af Mon Sep 17 00:00:00 2001 From: Daniel Whelan Date: Mon, 20 Oct 2025 16:18:45 +1100 Subject: [PATCH 1/2] allow for URL to be passed entirely in --- core/rpc.go | 18 +++++++++++++----- core/rpc_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 core/rpc_test.go diff --git a/core/rpc.go b/core/rpc.go index 0ab4b46..acaffa5 100644 --- a/core/rpc.go +++ b/core/rpc.go @@ -9,6 +9,7 @@ import ( "io" "log" "net/http" + "net/url" "sync" "sync/atomic" "time" @@ -32,13 +33,20 @@ const ( // NewCoreRPCClient returns a Dogecoin Core Node client. // Thread-safe, can be shared across Goroutines. -func NewCoreRPCClient(rpcHost string, rpcPort int, rpcUser string, rpcPass string) spec.Blockchain { - url := fmt.Sprintf("http://%s:%d", rpcHost, rpcPort) - return &CoreRPCClient{url: url, user: rpcUser, pass: rpcPass, retryDelay: 5 * time.Second} +func NewCoreRPCClient(rpcHostOrUrl string, rpcPort int, rpcUser string, rpcPass string) spec.Blockchain { + parsedUrl, err := url.Parse(rpcHostOrUrl) + var url string + if err != nil || parsedUrl.Scheme == "" { + url = fmt.Sprintf("http://%s:%d", rpcHostOrUrl, rpcPort) + } else { + url = rpcHostOrUrl + } + + return &CoreRPCClient{URL: url, user: rpcUser, pass: rpcPass, retryDelay: 5 * time.Second} } type CoreRPCClient struct { - url string + URL string user string pass string id atomic.Uint64 // next unique request id @@ -364,7 +372,7 @@ func (c *CoreRPCClient) Request(ctx context.Context, method string, params []any if err != nil { return 0, fmt.Errorf("json-rpc marshal request: %v", err) } - req, err := http.NewRequestWithContext(ctx, "POST", c.url, bytes.NewBuffer(payload)) + req, err := http.NewRequestWithContext(ctx, "POST", c.URL, bytes.NewBuffer(payload)) if err != nil { return 0, fmt.Errorf("json-rpc request: %v", err) } diff --git a/core/rpc_test.go b/core/rpc_test.go new file mode 100644 index 0000000..46fc7e9 --- /dev/null +++ b/core/rpc_test.go @@ -0,0 +1,27 @@ +package core + +import ( + "testing" +) + +func TestNewCoreRPCClient(t *testing.T) { + rpc := NewCoreRPCClient("http://127.0.0.1:22555", 0, "dogecoin", "dogecoin") + if rpc == nil { + t.Fatal("NewCoreRPCClient returned nil") + } + + if rpc.(*CoreRPCClient).URL != "http://127.0.0.1:22555" { + t.Fatal("GetURL returned wrong URL") + } +} + +func TestNewCoreRPCClientWithHostname(t *testing.T) { + rpc := NewCoreRPCClient("hostname", 22555, "dogecoin", "dogecoin") + if rpc == nil { + t.Fatal("NewCoreRPCClient returned nil") + } + + if rpc.(*CoreRPCClient).URL != "http://hostname:22555" { + t.Fatal("GetURL returned wrong URL") + } +} From 626a2d3b2e2457f3c5b1050493d5a73951b9bd9e Mon Sep 17 00:00:00 2001 From: Daniel Whelan Date: Mon, 20 Oct 2025 16:27:54 +1100 Subject: [PATCH 2/2] update comments --- core/rpc.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/rpc.go b/core/rpc.go index acaffa5..5f126db 100644 --- a/core/rpc.go +++ b/core/rpc.go @@ -33,6 +33,8 @@ const ( // NewCoreRPCClient returns a Dogecoin Core Node client. // Thread-safe, can be shared across Goroutines. +// If rpcHostOrUrl is a URL, it will be used directly. +// If rpcHostOrUrl is a hostname, it will be used with the port. func NewCoreRPCClient(rpcHostOrUrl string, rpcPort int, rpcUser string, rpcPass string) spec.Blockchain { parsedUrl, err := url.Parse(rpcHostOrUrl) var url string